Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: conflict detection UI enhancement #3352

Merged
merged 7 commits into from
Jul 6, 2021
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ export class ConflictDetectionChecker implements PostconditionChecker<string> {
)
);
results.different.forEach(file => {
channelService.appendLine(normalize(file));
channelService.appendLine(normalize(file.path));
});
channelService.showChannelOutput();

Expand Down Expand Up @@ -346,7 +346,7 @@ export class TimestampConflictChecker implements PostconditionChecker<string> {
)
);
results.different.forEach(file => {
channelService.appendLine(normalize(file));
channelService.appendLine(normalize(file.path));
});
channelService.showChannelOutput();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ import { telemetryService } from '../telemetry';
import {
CommonDirDirectoryDiffer,
DirectoryDiffer,
DirectoryDiffResults
DirectoryDiffResults,
TimestampFileProperties
} from './directoryDiffer';
import {
MetadataCacheCallback,
Expand All @@ -42,7 +43,7 @@ export class ConflictDetector {
private static EMPTY_DIFFS = {
localRoot: '',
remoteRoot: '',
different: new Set<string>(),
different: new Set<TimestampFileProperties>(),
scannedLocal: 0,
scannedRemote: 0
};
Expand Down
23 changes: 21 additions & 2 deletions packages/salesforcedx-vscode-core/src/conflict/conflictNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ export type ConflictFile = {
relPath: string;
localPath: string;
remotePath: string;
localLastModifiedDate: string | undefined;
remoteLastModifiedDate: string | undefined;
};

export class ConflictNode extends vscode.TreeItem {
Expand All @@ -23,11 +25,17 @@ export class ConflictNode extends vscode.TreeItem {
constructor(
label: string,
collapsibleState: vscode.TreeItemCollapsibleState,
parent?: ConflictNode
parent?: ConflictNode,
description?: string | boolean
) {
super(label, collapsibleState);
this._children = [];
this._parent = parent;
this.description = description;
}

public addChildConflictNode(conflictNode: ConflictNode) {
this._children.push(conflictNode);
}

get conflict() {
Expand All @@ -43,7 +51,18 @@ export class ConflictNode extends vscode.TreeItem {
}

get tooltip() {
return this._conflict ? this._conflict.relPath : this.label;
if (this._conflict) {
let tooptipMessage: string = '';
if (this._conflict.remoteLastModifiedDate) {
tooptipMessage += `Org LastModifiedDate: ${new Date(this._conflict.remoteLastModifiedDate).toLocaleString()} \n`;
violetyao marked this conversation as resolved.
Show resolved Hide resolved
}
if (this._conflict.localLastModifiedDate) {
tooptipMessage += `Local LastModifiedDate: ${new Date(this._conflict.localLastModifiedDate).toLocaleString()}`;
}
return tooptipMessage;
} else {
return this.label;
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,12 @@ export class ConflictView {
diffResults.different.forEach(p => {
conflicts.push({
remoteLabel,
relPath: p,
fileName: path.basename(p),
relPath: p.path,
fileName: path.basename(p.path),
localPath: diffResults.localRoot,
remotePath: diffResults.remoteRoot
remotePath: diffResults.remoteRoot,
localLastModifiedDate: p.localLastModifiedDate,
remoteLastModifiedDate: p.remoteLastModifiedDate
} as ConflictFile);
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,14 @@
import * as fs from 'fs';
import * as path from 'path';

export interface TimestampFileProperties {
path: string;
localLastModifiedDate?: string | undefined;
remoteLastModifiedDate?: string | undefined;
}

export interface DirectoryDiffResults {
different: Set<string>;
different: Set<TimestampFileProperties>;
localRoot: string;
remoteRoot: string;
scannedLocal: number;
Expand All @@ -34,7 +40,7 @@ export class CommonDirDirectoryDiffer implements DirectoryDiffer {
remoteSourcePath: string
): DirectoryDiffResults {
const localSet = this.listFiles(localSourcePath);
const different = new Set<string>();
const different = new Set<TimestampFileProperties>();

// process remote files to generate differences
let scannedRemote = 0;
Expand All @@ -44,7 +50,9 @@ export class CommonDirDirectoryDiffer implements DirectoryDiffer {
const file1 = path.join(localSourcePath, stats.relPath);
const file2 = path.join(remoteSourcePath, stats.relPath);
if (this.filesDiffer(file1, file2)) {
different.add(stats.relPath);
different.add({
path: stats.relPath
});
}
}
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,15 @@ import {
PersistentStorageService
} from './';
import { diffComponents } from './componentDiffer';
import { TimestampFileProperties } from './directoryDiffer';
import { CorrelatedComponent } from './metadataCacheService';

export class TimestampConflictDetector {
private diffs: DirectoryDiffResults;
private static EMPTY_DIFFS = {
localRoot: '',
remoteRoot: '',
different: new Set<string>(),
different: new Set<TimestampFileProperties>(),
scannedLocal: 0,
scannedRemote: 0
};
Expand All @@ -46,10 +47,10 @@ export class TimestampConflictDetector {
data: CorrelatedComponent[]
) {
const cache = PersistentStorageService.getInstance();
const conflicts: Set<string> = new Set<string>();
const conflicts: Set<TimestampFileProperties> = new Set<TimestampFileProperties>();
data.forEach(component => {
let lastModifiedInOrg;
let lastModifiedInCache;
let lastModifiedInOrg: string | undefined;
let lastModifiedInCache: string | undefined;

lastModifiedInOrg = component.lastModifiedDate;
const key = cache.makeKey(component.cacheComponent.type.name, component.cacheComponent.fullName);
Expand All @@ -60,7 +61,11 @@ export class TimestampConflictDetector {
const cachePathRelative = relative(this.diffs.remoteRoot, difference.cachePath);
const projectPathRelative = relative(this.diffs.localRoot, difference.projectPath);
if (cachePathRelative === projectPathRelative) {
conflicts.add(cachePathRelative);
conflicts.add({
path: cachePathRelative,
localLastModifiedDate: lastModifiedInCache,
remoteLastModifiedDate: lastModifiedInOrg
});
}
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
conflictView,
DirectoryDiffResults
} from '../../../../src/conflict';
import { TimestampFileProperties } from '../../../../src/conflict/directoryDiffer';
import { nls } from '../../../../src/messages';
import { notificationService } from '../../../../src/notifications';
import { sfdxCoreSettings } from '../../../../src/settings';
Expand Down Expand Up @@ -361,7 +362,7 @@ describe('Postcondition Checkers', () => {
const response = await postChecker.handleConflicts(
'manifest.xml',
'admin@example.com',
{ different: new Set<string>() } as DirectoryDiffResults
{ different: new Set<TimestampFileProperties>() } as DirectoryDiffResults
);

expect(response.type).to.equal('CONTINUE');
Expand All @@ -374,10 +375,13 @@ describe('Postcondition Checkers', () => {
it('Should post a warning and return CancelResponse when conflicts are detected and cancelled', async () => {
const postChecker = new ConflictDetectionChecker(retrieveMessages);
const results = {
different: new Set<string>([
'main/default/objects/Property__c/fields/Broker__c.field-meta.xml',
'main/default/aura/auraPropertySummary/auraPropertySummaryController.js'
]),
different: new Set<TimestampFileProperties>([
{
path: 'main/default/objects/Property__c/fields/Broker__c.field-meta.xml'
},
{
path: 'main/default/aura/auraPropertySummary/auraPropertySummaryController.js'
}]),
scannedLocal: 4,
scannedRemote: 6
} as DirectoryDiffResults;
Expand Down Expand Up @@ -412,7 +416,10 @@ describe('Postcondition Checkers', () => {
it('Should post a warning and return ContinueResponse when conflicts are detected and overwritten', async () => {
const postChecker = new ConflictDetectionChecker(retrieveMessages);
const results = {
different: new Set<string>('MyClass.cls')
different: new Set<TimestampFileProperties>([
{
path: 'MyClass.cls'
}])
} as DirectoryDiffResults;
modalStub.returns(nls.localize('conflict_detect_override'));

Expand All @@ -432,7 +439,10 @@ describe('Postcondition Checkers', () => {
it('Should post a warning and return CancelResponse when conflicts are detected and conflicts are shown', async () => {
const postChecker = new ConflictDetectionChecker(retrieveMessages);
const results = {
different: new Set<string>('MyClass.cls')
different: new Set<TimestampFileProperties>([
{
path: 'MyClass.cls'
}])
} as DirectoryDiffResults;
modalStub.returns(nls.localize('conflict_detect_show_conflicts'));

Expand Down Expand Up @@ -521,7 +531,7 @@ describe('Postcondition Checkers', () => {
const response = await postChecker.handleConflicts(
'manifest.xml',
'admin@example.com',
{ different: new Set<string>() } as DirectoryDiffResults
{ different: new Set<TimestampFileProperties>() } as DirectoryDiffResults
);

expect(response.type).to.equal('CONTINUE');
Expand All @@ -534,10 +544,17 @@ describe('Postcondition Checkers', () => {
it('Should post a warning and return CancelResponse when conflicts are detected and cancelled', async () => {
const postChecker = new TimestampConflictChecker(false, retrieveMessages);
const results = {
different: new Set<string>([
'main/default/objects/Property__c/fields/Broker__c.field-meta.xml',
'main/default/aura/auraPropertySummary/auraPropertySummaryController.js'
]),
different: new Set<TimestampFileProperties>([
{
path: 'main/default/objects/Property__c/fields/Broker__c.field-meta.xml',
localLastModifiedDate: 'Yesterday',
remoteLastModifiedDate: 'Today'
},
{
path: 'main/default/aura/auraPropertySummary/auraPropertySummaryController.js',
localLastModifiedDate: 'Yesterday',
remoteLastModifiedDate: 'Today'
}]),
scannedLocal: 4,
scannedRemote: 6
} as DirectoryDiffResults;
Expand Down Expand Up @@ -572,7 +589,12 @@ describe('Postcondition Checkers', () => {
it('Should post a warning and return ContinueResponse when conflicts are detected and overwritten', async () => {
const postChecker = new TimestampConflictChecker(false, retrieveMessages);
const results = {
different: new Set<string>('MyClass.cls')
different: new Set<TimestampFileProperties>([
{
path: 'MyClass.cls',
localLastModifiedDate: 'Yesterday',
remoteLastModifiedDate: 'Today'
}])
} as DirectoryDiffResults;
modalStub.returns(nls.localize('conflict_detect_override'));

Expand All @@ -592,7 +614,12 @@ describe('Postcondition Checkers', () => {
it('Should post a warning and return CancelResponse when conflicts are detected and conflicts are shown', async () => {
const postChecker = new TimestampConflictChecker(false, retrieveMessages);
const results = {
different: new Set<string>('MyClass.cls')
different: new Set<TimestampFileProperties>([
{
path: 'MyClass.cls',
localLastModifiedDate: 'Yesterday',
remoteLastModifiedDate: 'Today'
}])
} as DirectoryDiffResults;
modalStub.returns(nls.localize('conflict_detect_show_conflicts'));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
PersistentStorageService
} from '../../../src/conflict';
import * as differ from '../../../src/conflict/componentDiffer';
import { TimestampFileProperties } from '../../../src/conflict/directoryDiffer';
import { MetadataCacheResult } from '../../../src/conflict/metadataCacheService';
import { TimestampConflictDetector } from '../../../src/conflict/timestampConflictDetector';
import { nls } from '../../../src/messages';
Expand Down Expand Up @@ -130,9 +131,11 @@ describe('Timestamp Conflict Detector Execution', () => {
path.normalize('/a/b/c')
]);

expect(results.different).to.have.all.keys(
path.normalize('classes/HandlerCostCenter.cls')
);
expect(results.different).to.eql(new Set([{
path: path.normalize('classes/HandlerCostCenter.cls'),
localLastModifiedDate: 'Yesteday',
remoteLastModifiedDate: 'Today'
}]));
});

it('Should not report differences if the component is only local', async () => {
Expand Down Expand Up @@ -164,7 +167,7 @@ describe('Timestamp Conflict Detector Execution', () => {
expect(executorSpy.callCount).to.equal(1);
expect(cacheStub.callCount).to.equal(0);
expect(differStub.callCount).to.equal(0);
expect(results.different).to.eql(new Set<string>());
expect(results.different).to.eql(new Set<TimestampFileProperties>());
});

it('Should not report differences if the component is only remote', async () => {
Expand Down Expand Up @@ -196,7 +199,7 @@ describe('Timestamp Conflict Detector Execution', () => {
expect(executorSpy.callCount).to.equal(1);
expect(cacheStub.callCount).to.equal(0);
expect(differStub.callCount).to.equal(0);
expect(results.different).to.eql(new Set<string>());
expect(results.different).to.eql(new Set<TimestampFileProperties>());
});

it('Should not report differences if the timestamps match', async () => {
Expand Down Expand Up @@ -239,7 +242,7 @@ describe('Timestamp Conflict Detector Execution', () => {
expect(executorSpy.callCount).to.equal(1);
expect(cacheStub.callCount).to.equal(1);
expect(differStub.callCount).to.equal(0);
expect(results.different).to.eql(new Set<string>());
expect(results.different).to.eql(new Set<TimestampFileProperties>());
});

it('Should not report differences if the files match', async () => {
Expand Down Expand Up @@ -303,7 +306,7 @@ describe('Timestamp Conflict Detector Execution', () => {
path.normalize('/a/b/c')
]);

expect(results.different).to.eql(new Set<string>());
expect(results.different).to.eql(new Set<TimestampFileProperties>());
});

it('Should report an error during conflict detection', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,14 @@ describe('Directory Differ', () => {
const differ = new CommonDirDirectoryDiffer();
const results = differ.diff(dirOne, dirTwo);

expect(results.different).to.have.keys([cls1ToChange, layoutToChange]);
expect(results.different).to.eql(new Set([
{
path: cls1ToChange
},
{
path: layoutToChange
}
]));
expect(
results.scannedLocal,
'incorrect number of files scanned in dirOne'
Expand Down Expand Up @@ -121,9 +128,11 @@ describe('Directory Differ', () => {
shell.cp(source, target);
const results = differ.diff(dirOne, dirTwo);

expect(results.different).to.have.keys([
path.join('staticresources', 'leaflet', 'images', 'marker-icon.png')
]);
expect(results.different).to.eql(new Set([
{
path: path.join('staticresources', 'leaflet', 'images', 'marker-icon.png')
}
]));
expect(
results.scannedLocal,
'incorrect number of files scanned in dirOne'
Expand Down