提交 e3dfc219 编写于 作者: S Sandeep Somavarapu

Fix #90239

上级 5da116f3
......@@ -29,6 +29,12 @@ export function merge(localExtensions: ISyncExtension[], remoteExtensions: ISync
};
}
// massage incoming extension - add disabled property
const massageIncomingExtension = (extension: ISyncExtension): ISyncExtension => ({ ...extension, ...{ disabled: !!extension.disabled } });
localExtensions = localExtensions.map(massageIncomingExtension);
remoteExtensions = remoteExtensions.map(massageIncomingExtension);
lastSyncExtensions = lastSyncExtensions ? lastSyncExtensions.map(massageIncomingExtension) : null;
const uuids: Map<string, string> = new Map<string, string>();
const addUUID = (identifier: IExtensionIdentifier) => { if (identifier.uuid) { uuids.set(identifier.id.toLowerCase(), identifier.uuid); } };
localExtensions.forEach(({ identifier }) => addUUID(identifier));
......@@ -37,10 +43,12 @@ export function merge(localExtensions: ISyncExtension[], remoteExtensions: ISync
lastSyncExtensions.forEach(({ identifier }) => addUUID(identifier));
}
const addExtensionToMap = (map: Map<string, ISyncExtension>, extension: ISyncExtension) => {
const getKey = (extension: ISyncExtension): string => {
const uuid = extension.identifier.uuid || uuids.get(extension.identifier.id.toLowerCase());
const key = uuid ? `uuid:${uuid}` : `id:${extension.identifier.id.toLowerCase()}`;
map.set(key, extension);
return uuid ? `uuid:${uuid}` : `id:${extension.identifier.id.toLowerCase()}`;
};
const addExtensionToMap = (map: Map<string, ISyncExtension>, extension: ISyncExtension) => {
map.set(getKey(extension), extension);
return map;
};
const localExtensionsMap = localExtensions.reduce(addExtensionToMap, new Map<string, ISyncExtension>());
......@@ -62,14 +70,17 @@ export function merge(localExtensions: ISyncExtension[], remoteExtensions: ISync
const baseToLocal = compare(lastSyncExtensionsMap, localExtensionsMap, ignoredExtensionsSet);
const baseToRemote = compare(lastSyncExtensionsMap, remoteExtensionsMap, ignoredExtensionsSet);
const massageSyncExtension = (extension: ISyncExtension, key: string): ISyncExtension => {
// massage outgoing extension - remove disabled property
const massageOutgoingExtension = (extension: ISyncExtension, key: string): ISyncExtension => {
const massagedExtension: ISyncExtension = {
identifier: {
id: extension.identifier.id,
uuid: startsWith(key, 'uuid:') ? key.substring('uuid:'.length) : undefined
},
enabled: extension.enabled,
};
if (extension.disabled) {
massagedExtension.disabled = true;
}
if (extension.version) {
massagedExtension.version = extension.version;
}
......@@ -90,25 +101,25 @@ export function merge(localExtensions: ISyncExtension[], remoteExtensions: ISync
if (baseToLocal.added.has(key)) {
// Is different from local to remote
if (localToRemote.updated.has(key)) {
updated.push(massageSyncExtension(remoteExtensionsMap.get(key)!, key));
updated.push(massageOutgoingExtension(remoteExtensionsMap.get(key)!, key));
}
} else {
// Add to local
added.push(massageSyncExtension(remoteExtensionsMap.get(key)!, key));
added.push(massageOutgoingExtension(remoteExtensionsMap.get(key)!, key));
}
}
// Remotely updated extensions
for (const key of values(baseToRemote.updated)) {
// Update in local always
updated.push(massageSyncExtension(remoteExtensionsMap.get(key)!, key));
updated.push(massageOutgoingExtension(remoteExtensionsMap.get(key)!, key));
}
// Locally added extensions
for (const key of values(baseToLocal.added)) {
// Not there in remote
if (!baseToRemote.added.has(key)) {
newRemoteExtensionsMap.set(key, massageSyncExtension(localExtensionsMap.get(key)!, key));
newRemoteExtensionsMap.set(key, localExtensionsMap.get(key)!);
}
}
......@@ -121,7 +132,7 @@ export function merge(localExtensions: ISyncExtension[], remoteExtensions: ISync
// If not updated in remote
if (!baseToRemote.updated.has(key)) {
newRemoteExtensionsMap.set(key, massageSyncExtension(localExtensionsMap.get(key)!, key));
newRemoteExtensionsMap.set(key, localExtensionsMap.get(key)!);
}
}
......@@ -133,9 +144,13 @@ export function merge(localExtensions: ISyncExtension[], remoteExtensions: ISync
}
}
const remote: ISyncExtension[] = [];
const remoteChanges = compare(remoteExtensionsMap, newRemoteExtensionsMap, new Set<string>());
const remote = remoteChanges.added.size > 0 || remoteChanges.updated.size > 0 || remoteChanges.removed.size > 0 ? values(newRemoteExtensionsMap) : null;
return { added, removed, updated, remote };
if (remoteChanges.added.size > 0 || remoteChanges.updated.size > 0 || remoteChanges.removed.size > 0) {
newRemoteExtensionsMap.forEach((value, key) => remote.push(massageOutgoingExtension(value, key)));
}
return { added, removed, updated, remote: remote.length ? remote : null };
}
function compare(from: Map<string, ISyncExtension> | null, to: Map<string, ISyncExtension>, ignoredExtensions: Set<string>): { added: Set<string>, removed: Set<string>, updated: Set<string> } {
......@@ -152,7 +167,7 @@ function compare(from: Map<string, ISyncExtension> | null, to: Map<string, ISync
const fromExtension = from!.get(key)!;
const toExtension = to.get(key);
if (!toExtension
|| fromExtension.enabled !== toExtension.enabled
|| fromExtension.disabled !== toExtension.disabled
|| fromExtension.version !== toExtension.version
) {
updated.add(key);
......
......@@ -14,7 +14,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur
import { localize } from 'vs/nls';
import { merge } from 'vs/platform/userDataSync/common/extensionsMerge';
import { isNonEmptyArray } from 'vs/base/common/arrays';
import { AbstractSynchroniser, IRemoteUserData } from 'vs/platform/userDataSync/common/abstractSynchronizer';
import { AbstractSynchroniser, IRemoteUserData, ISyncData } from 'vs/platform/userDataSync/common/abstractSynchronizer';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
interface ISyncPreviewResult {
......@@ -34,7 +34,7 @@ interface ILastSyncUserData extends IRemoteUserData {
export class ExtensionsSynchroniser extends AbstractSynchroniser implements IUserDataSynchroniser {
readonly resourceKey: ResourceKey = 'extensions';
protected readonly version: number = 1;
protected readonly version: number = 2;
constructor(
@IEnvironmentService environmentService: IEnvironmentService,
......@@ -75,7 +75,7 @@ export class ExtensionsSynchroniser extends AbstractSynchroniser implements IUse
if (remoteUserData.syncData !== null) {
const localExtensions = await this.getLocalExtensions();
const remoteExtensions: ISyncExtension[] = JSON.parse(remoteUserData.syncData.content);
const remoteExtensions = this.parseExtensions(remoteUserData.syncData);
const { added, updated, remote } = merge(localExtensions, remoteExtensions, [], [], this.getIgnoredExtensions());
await this.apply({ added, removed: [], updated, remote, remoteUserData, skippedExtensions: [], lastSyncUserData });
}
......@@ -165,8 +165,8 @@ export class ExtensionsSynchroniser extends AbstractSynchroniser implements IUse
}
private async getPreview(remoteUserData: IRemoteUserData, lastSyncUserData: ILastSyncUserData | null): Promise<ISyncPreviewResult> {
const remoteExtensions: ISyncExtension[] = remoteUserData.syncData ? JSON.parse(remoteUserData.syncData.content) : null;
const lastSyncExtensions: ISyncExtension[] | null = lastSyncUserData ? JSON.parse(lastSyncUserData.syncData!.content) : null;
const remoteExtensions: ISyncExtension[] | null = remoteUserData.syncData ? this.parseExtensions(remoteUserData.syncData) : null;
const lastSyncExtensions: ISyncExtension[] | null = lastSyncUserData ? this.parseExtensions(lastSyncUserData.syncData!) : null;
const skippedExtensions: ISyncExtension[] = lastSyncUserData ? lastSyncUserData.skippedExtensions || [] : [];
const localExtensions = await this.getLocalExtensions();
......@@ -236,14 +236,14 @@ export class ExtensionsSynchroniser extends AbstractSynchroniser implements IUse
// Builtin Extension: Sync only enablement state
if (installedExtension && installedExtension.type === ExtensionType.System) {
if (e.enabled) {
this.logService.trace('Extensions: Enabling extension...', e.identifier.id);
await this.extensionEnablementService.enableExtension(e.identifier);
this.logService.info('Extensions: Enabled extension', e.identifier.id);
} else {
if (e.disabled) {
this.logService.trace('Extensions: Disabling extension...', e.identifier.id);
await this.extensionEnablementService.disableExtension(e.identifier);
this.logService.info('Extensions: Disabled extension', e.identifier.id);
} else {
this.logService.trace('Extensions: Enabling extension...', e.identifier.id);
await this.extensionEnablementService.enableExtension(e.identifier);
this.logService.info('Extensions: Enabled extension', e.identifier.id);
}
removeFromSkipped.push(e.identifier);
return;
......@@ -252,14 +252,14 @@ export class ExtensionsSynchroniser extends AbstractSynchroniser implements IUse
const extension = await this.extensionGalleryService.getCompatibleExtension(e.identifier, e.version);
if (extension) {
try {
if (e.enabled) {
this.logService.trace('Extensions: Enabling extension...', e.identifier.id, extension.version);
await this.extensionEnablementService.enableExtension(extension.identifier);
this.logService.info('Extensions: Enabled extension', e.identifier.id, extension.version);
} else {
if (e.disabled) {
this.logService.trace('Extensions: Disabling extension...', e.identifier.id, extension.version);
await this.extensionEnablementService.disableExtension(extension.identifier);
this.logService.info('Extensions: Disabled extension', e.identifier.id, extension.version);
} else {
this.logService.trace('Extensions: Enabling extension...', e.identifier.id, extension.version);
await this.extensionEnablementService.enableExtension(extension.identifier);
this.logService.info('Extensions: Enabled extension', e.identifier.id, extension.version);
}
// Install only if the extension does not exist
if (!installedExtension || installedExtension.manifest.version !== extension.version) {
......@@ -293,11 +293,33 @@ export class ExtensionsSynchroniser extends AbstractSynchroniser implements IUse
return newSkippedExtensions;
}
private parseExtensions(syncData: ISyncData): ISyncExtension[] {
let extensions: ISyncExtension[] = JSON.parse(syncData.content);
if (syncData.version !== this.version) {
extensions = extensions.map(e => {
// #region Migration from v1 (enabled -> disabled)
if (!(<any>e).enabled) {
e.disabled = true;
}
delete (<any>e).enabled;
// #endregion
return e;
});
}
return extensions;
}
private async getLocalExtensions(): Promise<ISyncExtension[]> {
const installedExtensions = await this.extensionManagementService.getInstalled();
const disabledExtensions = await this.extensionEnablementService.getDisabledExtensions();
const disabledExtensions = this.extensionEnablementService.getDisabledExtensions();
return installedExtensions
.map(({ identifier }) => ({ identifier, enabled: !disabledExtensions.some(disabledExtension => areSameExtensions(disabledExtension, identifier)) }));
.map(({ identifier }) => {
const syncExntesion: ISyncExtension = { identifier };
if (disabledExtensions.some(disabledExtension => areSameExtensions(disabledExtension, identifier))) {
syncExntesion.disabled = true;
}
return syncExntesion;
});
}
}
......@@ -11,9 +11,9 @@ suite('ExtensionsMerge - No Conflicts', () => {
test('merge returns local extension if remote does not exist', async () => {
const localExtensions: ISyncExtension[] = [
{ identifier: { id: 'a', uuid: 'a' }, enabled: true },
{ identifier: { id: 'b', uuid: 'b' }, enabled: true },
{ identifier: { id: 'c', uuid: 'c' }, enabled: true },
{ identifier: { id: 'a', uuid: 'a' } },
{ identifier: { id: 'b', uuid: 'b' } },
{ identifier: { id: 'c', uuid: 'c' } },
];
const actual = merge(localExtensions, null, null, [], []);
......@@ -26,13 +26,13 @@ suite('ExtensionsMerge - No Conflicts', () => {
test('merge returns local extension if remote does not exist with ignored extensions', async () => {
const localExtensions: ISyncExtension[] = [
{ identifier: { id: 'a', uuid: 'a' }, enabled: true },
{ identifier: { id: 'b', uuid: 'b' }, enabled: true },
{ identifier: { id: 'c', uuid: 'c' }, enabled: true },
{ identifier: { id: 'a', uuid: 'a' } },
{ identifier: { id: 'b', uuid: 'b' } },
{ identifier: { id: 'c', uuid: 'c' } },
];
const expected: ISyncExtension[] = [
{ identifier: { id: 'b', uuid: 'b' }, enabled: true },
{ identifier: { id: 'c', uuid: 'c' }, enabled: true },
{ identifier: { id: 'b', uuid: 'b' } },
{ identifier: { id: 'c', uuid: 'c' } },
];
const actual = merge(localExtensions, null, null, [], ['a']);
......@@ -45,13 +45,13 @@ suite('ExtensionsMerge - No Conflicts', () => {
test('merge returns local extension if remote does not exist with ignored extensions (ignore case)', async () => {
const localExtensions: ISyncExtension[] = [
{ identifier: { id: 'a', uuid: 'a' }, enabled: true },
{ identifier: { id: 'b', uuid: 'b' }, enabled: true },
{ identifier: { id: 'c', uuid: 'c' }, enabled: true },
{ identifier: { id: 'a', uuid: 'a' } },
{ identifier: { id: 'b', uuid: 'b' } },
{ identifier: { id: 'c', uuid: 'c' } },
];
const expected: ISyncExtension[] = [
{ identifier: { id: 'b', uuid: 'b' }, enabled: true },
{ identifier: { id: 'c', uuid: 'c' }, enabled: true },
{ identifier: { id: 'b', uuid: 'b' } },
{ identifier: { id: 'c', uuid: 'c' } },
];
const actual = merge(localExtensions, null, null, [], ['A']);
......@@ -64,17 +64,17 @@ suite('ExtensionsMerge - No Conflicts', () => {
test('merge returns local extension if remote does not exist with skipped extensions', async () => {
const localExtensions: ISyncExtension[] = [
{ identifier: { id: 'a', uuid: 'a' }, enabled: true },
{ identifier: { id: 'b', uuid: 'b' }, enabled: true },
{ identifier: { id: 'c', uuid: 'c' }, enabled: true },
{ identifier: { id: 'a', uuid: 'a' } },
{ identifier: { id: 'b', uuid: 'b' } },
{ identifier: { id: 'c', uuid: 'c' } },
];
const skippedExtension: ISyncExtension[] = [
{ identifier: { id: 'b', uuid: 'b' }, enabled: true },
{ identifier: { id: 'b', uuid: 'b' } },
];
const expected: ISyncExtension[] = [
{ identifier: { id: 'a', uuid: 'a' }, enabled: true },
{ identifier: { id: 'b', uuid: 'b' }, enabled: true },
{ identifier: { id: 'c', uuid: 'c' }, enabled: true },
{ identifier: { id: 'a', uuid: 'a' } },
{ identifier: { id: 'b', uuid: 'b' } },
{ identifier: { id: 'c', uuid: 'c' } },
];
const actual = merge(localExtensions, null, null, skippedExtension, []);
......@@ -87,16 +87,16 @@ suite('ExtensionsMerge - No Conflicts', () => {
test('merge returns local extension if remote does not exist with skipped and ignored extensions', async () => {
const localExtensions: ISyncExtension[] = [
{ identifier: { id: 'a', uuid: 'a' }, enabled: true },
{ identifier: { id: 'b', uuid: 'b' }, enabled: true },
{ identifier: { id: 'c', uuid: 'c' }, enabled: true },
{ identifier: { id: 'a', uuid: 'a' } },
{ identifier: { id: 'b', uuid: 'b' } },
{ identifier: { id: 'c', uuid: 'c' } },
];
const skippedExtension: ISyncExtension[] = [
{ identifier: { id: 'b', uuid: 'b' }, enabled: true },
{ identifier: { id: 'b', uuid: 'b' } },
];
const expected: ISyncExtension[] = [
{ identifier: { id: 'b', uuid: 'b' }, enabled: true },
{ identifier: { id: 'c', uuid: 'c' }, enabled: true },
{ identifier: { id: 'b', uuid: 'b' } },
{ identifier: { id: 'c', uuid: 'c' } },
];
const actual = merge(localExtensions, null, null, skippedExtension, ['a']);
......@@ -109,23 +109,23 @@ suite('ExtensionsMerge - No Conflicts', () => {
test('merge local and remote extensions when there is no base', async () => {
const localExtensions: ISyncExtension[] = [
{ identifier: { id: 'a', uuid: 'a' }, enabled: true },
{ identifier: { id: 'd', uuid: 'd' }, enabled: true },
{ identifier: { id: 'a', uuid: 'a' } },
{ identifier: { id: 'd', uuid: 'd' } },
];
const remoteExtensions: ISyncExtension[] = [
{ identifier: { id: 'b', uuid: 'b' }, enabled: true },
{ identifier: { id: 'c', uuid: 'c' }, enabled: true },
{ identifier: { id: 'b', uuid: 'b' } },
{ identifier: { id: 'c', uuid: 'c' } },
];
const expected: ISyncExtension[] = [
{ identifier: { id: 'b', uuid: 'b' }, enabled: true },
{ identifier: { id: 'c', uuid: 'c' }, enabled: true },
{ identifier: { id: 'a', uuid: 'a' }, enabled: true },
{ identifier: { id: 'd', uuid: 'd' }, enabled: true },
{ identifier: { id: 'b', uuid: 'b' } },
{ identifier: { id: 'c', uuid: 'c' } },
{ identifier: { id: 'a', uuid: 'a' } },
{ identifier: { id: 'd', uuid: 'd' } },
];
const actual = merge(localExtensions, remoteExtensions, null, [], []);
assert.deepEqual(actual.added, [{ identifier: { id: 'b', uuid: 'b' }, enabled: true }, { identifier: { id: 'c', uuid: 'c' }, enabled: true }]);
assert.deepEqual(actual.added, [{ identifier: { id: 'b', uuid: 'b' } }, { identifier: { id: 'c', uuid: 'c' } }]);
assert.deepEqual(actual.removed, []);
assert.deepEqual(actual.updated, []);
assert.deepEqual(actual.remote, expected);
......@@ -133,22 +133,22 @@ suite('ExtensionsMerge - No Conflicts', () => {
test('merge local and remote extensions when there is no base and with ignored extensions', async () => {
const localExtensions: ISyncExtension[] = [
{ identifier: { id: 'a', uuid: 'a' }, enabled: true },
{ identifier: { id: 'd', uuid: 'd' }, enabled: true },
{ identifier: { id: 'a', uuid: 'a' } },
{ identifier: { id: 'd', uuid: 'd' } },
];
const remoteExtensions: ISyncExtension[] = [
{ identifier: { id: 'b', uuid: 'b' }, enabled: true },
{ identifier: { id: 'c', uuid: 'c' }, enabled: true },
{ identifier: { id: 'b', uuid: 'b' } },
{ identifier: { id: 'c', uuid: 'c' } },
];
const expected: ISyncExtension[] = [
{ identifier: { id: 'b', uuid: 'b' }, enabled: true },
{ identifier: { id: 'c', uuid: 'c' }, enabled: true },
{ identifier: { id: 'd', uuid: 'd' }, enabled: true },
{ identifier: { id: 'b', uuid: 'b' } },
{ identifier: { id: 'c', uuid: 'c' } },
{ identifier: { id: 'd', uuid: 'd' } },
];
const actual = merge(localExtensions, remoteExtensions, null, [], ['a']);
assert.deepEqual(actual.added, [{ identifier: { id: 'b', uuid: 'b' }, enabled: true }, { identifier: { id: 'c', uuid: 'c' }, enabled: true }]);
assert.deepEqual(actual.added, [{ identifier: { id: 'b', uuid: 'b' } }, { identifier: { id: 'c', uuid: 'c' } }]);
assert.deepEqual(actual.removed, []);
assert.deepEqual(actual.updated, []);
assert.deepEqual(actual.remote, expected);
......@@ -156,43 +156,66 @@ suite('ExtensionsMerge - No Conflicts', () => {
test('merge local and remote extensions when remote is moved forwarded', async () => {
const baseExtensions: ISyncExtension[] = [
{ identifier: { id: 'a', uuid: 'a' }, enabled: true },
{ identifier: { id: 'd', uuid: 'd' }, enabled: true },
{ identifier: { id: 'a', uuid: 'a' } },
{ identifier: { id: 'd', uuid: 'd' } },
];
const localExtensions: ISyncExtension[] = [
{ identifier: { id: 'a', uuid: 'a' }, enabled: true },
{ identifier: { id: 'd', uuid: 'd' }, enabled: true },
{ identifier: { id: 'a', uuid: 'a' } },
{ identifier: { id: 'd', uuid: 'd' } },
];
const remoteExtensions: ISyncExtension[] = [
{ identifier: { id: 'b', uuid: 'b' }, enabled: true },
{ identifier: { id: 'c', uuid: 'c' }, enabled: true },
{ identifier: { id: 'b', uuid: 'b' } },
{ identifier: { id: 'c', uuid: 'c' } },
];
const actual = merge(localExtensions, remoteExtensions, baseExtensions, [], []);
assert.deepEqual(actual.added, [{ identifier: { id: 'b', uuid: 'b' }, enabled: true }, { identifier: { id: 'c', uuid: 'c' }, enabled: true }]);
assert.deepEqual(actual.added, [{ identifier: { id: 'b', uuid: 'b' } }, { identifier: { id: 'c', uuid: 'c' } }]);
assert.deepEqual(actual.removed, [{ id: 'a', uuid: 'a' }, { id: 'd', uuid: 'd' }]);
assert.deepEqual(actual.updated, []);
assert.equal(actual.remote, null);
});
test('merge local and remote extensions when remote is moved forwarded with disabled extension', async () => {
const baseExtensions: ISyncExtension[] = [
{ identifier: { id: 'a', uuid: 'a' } },
{ identifier: { id: 'd', uuid: 'd' } },
];
const localExtensions: ISyncExtension[] = [
{ identifier: { id: 'a', uuid: 'a' } },
{ identifier: { id: 'd', uuid: 'd' } },
];
const remoteExtensions: ISyncExtension[] = [
{ identifier: { id: 'b', uuid: 'b' } },
{ identifier: { id: 'c', uuid: 'c' } },
{ identifier: { id: 'd', uuid: 'd' }, disabled: true },
];
const actual = merge(localExtensions, remoteExtensions, baseExtensions, [], []);
assert.deepEqual(actual.added, [{ identifier: { id: 'b', uuid: 'b' } }, { identifier: { id: 'c', uuid: 'c' } }]);
assert.deepEqual(actual.removed, [{ id: 'a', uuid: 'a' }]);
assert.deepEqual(actual.updated, [{ identifier: { id: 'd', uuid: 'd' }, disabled: true }]);
assert.equal(actual.remote, null);
});
test('merge local and remote extensions when remote moved forwarded with ignored extensions', async () => {
const baseExtensions: ISyncExtension[] = [
{ identifier: { id: 'a', uuid: 'a' }, enabled: true },
{ identifier: { id: 'd', uuid: 'd' }, enabled: true },
{ identifier: { id: 'a', uuid: 'a' } },
{ identifier: { id: 'd', uuid: 'd' } },
];
const localExtensions: ISyncExtension[] = [
{ identifier: { id: 'a', uuid: 'a' }, enabled: true },
{ identifier: { id: 'd', uuid: 'd' }, enabled: true },
{ identifier: { id: 'a', uuid: 'a' } },
{ identifier: { id: 'd', uuid: 'd' } },
];
const remoteExtensions: ISyncExtension[] = [
{ identifier: { id: 'b', uuid: 'b' }, enabled: true },
{ identifier: { id: 'c', uuid: 'c' }, enabled: true },
{ identifier: { id: 'b', uuid: 'b' } },
{ identifier: { id: 'c', uuid: 'c' } },
];
const actual = merge(localExtensions, remoteExtensions, baseExtensions, [], ['a']);
assert.deepEqual(actual.added, [{ identifier: { id: 'b', uuid: 'b' }, enabled: true }, { identifier: { id: 'c', uuid: 'c' }, enabled: true }]);
assert.deepEqual(actual.added, [{ identifier: { id: 'b', uuid: 'b' } }, { identifier: { id: 'c', uuid: 'c' } }]);
assert.deepEqual(actual.removed, [{ id: 'd', uuid: 'd' }]);
assert.deepEqual(actual.updated, []);
assert.equal(actual.remote, null);
......@@ -200,23 +223,23 @@ suite('ExtensionsMerge - No Conflicts', () => {
test('merge local and remote extensions when remote is moved forwarded with skipped extensions', async () => {
const baseExtensions: ISyncExtension[] = [
{ identifier: { id: 'a', uuid: 'a' }, enabled: true },
{ identifier: { id: 'd', uuid: 'd' }, enabled: true },
{ identifier: { id: 'a', uuid: 'a' } },
{ identifier: { id: 'd', uuid: 'd' } },
];
const localExtensions: ISyncExtension[] = [
{ identifier: { id: 'd', uuid: 'd' }, enabled: true },
{ identifier: { id: 'd', uuid: 'd' } },
];
const skippedExtensions: ISyncExtension[] = [
{ identifier: { id: 'a', uuid: 'a' }, enabled: true },
{ identifier: { id: 'a', uuid: 'a' } },
];
const remoteExtensions: ISyncExtension[] = [
{ identifier: { id: 'b', uuid: 'b' }, enabled: true },
{ identifier: { id: 'c', uuid: 'c' }, enabled: true },
{ identifier: { id: 'b', uuid: 'b' } },
{ identifier: { id: 'c', uuid: 'c' } },
];
const actual = merge(localExtensions, remoteExtensions, baseExtensions, skippedExtensions, []);
assert.deepEqual(actual.added, [{ identifier: { id: 'b', uuid: 'b' }, enabled: true }, { identifier: { id: 'c', uuid: 'c' }, enabled: true }]);
assert.deepEqual(actual.added, [{ identifier: { id: 'b', uuid: 'b' } }, { identifier: { id: 'c', uuid: 'c' } }]);
assert.deepEqual(actual.removed, [{ id: 'd', uuid: 'd' }]);
assert.deepEqual(actual.updated, []);
assert.equal(actual.remote, null);
......@@ -224,23 +247,23 @@ suite('ExtensionsMerge - No Conflicts', () => {
test('merge local and remote extensions when remote is moved forwarded with skipped and ignored extensions', async () => {
const baseExtensions: ISyncExtension[] = [
{ identifier: { id: 'a', uuid: 'a' }, enabled: true },
{ identifier: { id: 'd', uuid: 'd' }, enabled: true },
{ identifier: { id: 'a', uuid: 'a' } },
{ identifier: { id: 'd', uuid: 'd' } },
];
const localExtensions: ISyncExtension[] = [
{ identifier: { id: 'd', uuid: 'd' }, enabled: true },
{ identifier: { id: 'd', uuid: 'd' } },
];
const skippedExtensions: ISyncExtension[] = [
{ identifier: { id: 'a', uuid: 'a' }, enabled: true },
{ identifier: { id: 'a', uuid: 'a' } },
];
const remoteExtensions: ISyncExtension[] = [
{ identifier: { id: 'b', uuid: 'b' }, enabled: true },
{ identifier: { id: 'c', uuid: 'c' }, enabled: true },
{ identifier: { id: 'b', uuid: 'b' } },
{ identifier: { id: 'c', uuid: 'c' } },
];
const actual = merge(localExtensions, remoteExtensions, baseExtensions, skippedExtensions, ['b']);
assert.deepEqual(actual.added, [{ identifier: { id: 'c', uuid: 'c' }, enabled: true }]);
assert.deepEqual(actual.added, [{ identifier: { id: 'c', uuid: 'c' } }]);
assert.deepEqual(actual.removed, [{ id: 'd', uuid: 'd' }]);
assert.deepEqual(actual.updated, []);
assert.equal(actual.remote, null);
......@@ -248,16 +271,39 @@ suite('ExtensionsMerge - No Conflicts', () => {
test('merge local and remote extensions when local is moved forwarded', async () => {
const baseExtensions: ISyncExtension[] = [
{ identifier: { id: 'a', uuid: 'a' }, enabled: true },
{ identifier: { id: 'd', uuid: 'd' }, enabled: true },
{ identifier: { id: 'a', uuid: 'a' } },
{ identifier: { id: 'd', uuid: 'd' } },
];
const localExtensions: ISyncExtension[] = [
{ identifier: { id: 'b', uuid: 'b' } },
{ identifier: { id: 'c', uuid: 'c' } },
];
const remoteExtensions: ISyncExtension[] = [
{ identifier: { id: 'a', uuid: 'a' } },
{ identifier: { id: 'd', uuid: 'd' } },
];
const actual = merge(localExtensions, remoteExtensions, baseExtensions, [], []);
assert.deepEqual(actual.added, []);
assert.deepEqual(actual.removed, []);
assert.deepEqual(actual.updated, []);
assert.deepEqual(actual.remote, localExtensions);
});
test('merge local and remote extensions when local is moved forwarded with disabled extensions', async () => {
const baseExtensions: ISyncExtension[] = [
{ identifier: { id: 'a', uuid: 'a' } },
{ identifier: { id: 'd', uuid: 'd' } },
];
const localExtensions: ISyncExtension[] = [
{ identifier: { id: 'b', uuid: 'b' }, enabled: true },
{ identifier: { id: 'c', uuid: 'c' }, enabled: true },
{ identifier: { id: 'a', uuid: 'a' }, disabled: true },
{ identifier: { id: 'b', uuid: 'b' } },
{ identifier: { id: 'c', uuid: 'c' } },
];
const remoteExtensions: ISyncExtension[] = [
{ identifier: { id: 'a', uuid: 'a' }, enabled: true },
{ identifier: { id: 'd', uuid: 'd' }, enabled: true },
{ identifier: { id: 'a', uuid: 'a' } },
{ identifier: { id: 'd', uuid: 'd' } },
];
const actual = merge(localExtensions, remoteExtensions, baseExtensions, [], []);
......@@ -270,16 +316,16 @@ suite('ExtensionsMerge - No Conflicts', () => {
test('merge local and remote extensions when local is moved forwarded with ignored settings', async () => {
const baseExtensions: ISyncExtension[] = [
{ identifier: { id: 'a', uuid: 'a' }, enabled: true },
{ identifier: { id: 'd', uuid: 'd' }, enabled: true },
{ identifier: { id: 'a', uuid: 'a' } },
{ identifier: { id: 'd', uuid: 'd' } },
];
const localExtensions: ISyncExtension[] = [
{ identifier: { id: 'b', uuid: 'b' }, enabled: true },
{ identifier: { id: 'c', uuid: 'c' }, enabled: true },
{ identifier: { id: 'b', uuid: 'b' } },
{ identifier: { id: 'c', uuid: 'c' } },
];
const remoteExtensions: ISyncExtension[] = [
{ identifier: { id: 'a', uuid: 'a' }, enabled: true },
{ identifier: { id: 'd', uuid: 'd' }, enabled: true },
{ identifier: { id: 'a', uuid: 'a' } },
{ identifier: { id: 'd', uuid: 'd' } },
];
const actual = merge(localExtensions, remoteExtensions, baseExtensions, [], ['b']);
......@@ -288,30 +334,30 @@ suite('ExtensionsMerge - No Conflicts', () => {
assert.deepEqual(actual.removed, []);
assert.deepEqual(actual.updated, []);
assert.deepEqual(actual.remote, [
{ identifier: { id: 'c', uuid: 'c' }, enabled: true },
{ identifier: { id: 'c', uuid: 'c' } },
]);
});
test('merge local and remote extensions when local is moved forwarded with skipped extensions', async () => {
const baseExtensions: ISyncExtension[] = [
{ identifier: { id: 'a', uuid: 'a' }, enabled: true },
{ identifier: { id: 'd', uuid: 'd' }, enabled: true },
{ identifier: { id: 'a', uuid: 'a' } },
{ identifier: { id: 'd', uuid: 'd' } },
];
const skippedExtensions: ISyncExtension[] = [
{ identifier: { id: 'd', uuid: 'd' }, enabled: true },
{ identifier: { id: 'd', uuid: 'd' } },
];
const localExtensions: ISyncExtension[] = [
{ identifier: { id: 'b', uuid: 'b' }, enabled: true },
{ identifier: { id: 'c', uuid: 'c' }, enabled: true },
{ identifier: { id: 'b', uuid: 'b' } },
{ identifier: { id: 'c', uuid: 'c' } },
];
const remoteExtensions: ISyncExtension[] = [
{ identifier: { id: 'a', uuid: 'a' }, enabled: true },
{ identifier: { id: 'd', uuid: 'd' }, enabled: true },
{ identifier: { id: 'a', uuid: 'a' } },
{ identifier: { id: 'd', uuid: 'd' } },
];
const expected: ISyncExtension[] = [
{ identifier: { id: 'd', uuid: 'd' }, enabled: true },
{ identifier: { id: 'b', uuid: 'b' }, enabled: true },
{ identifier: { id: 'c', uuid: 'c' }, enabled: true },
{ identifier: { id: 'd', uuid: 'd' } },
{ identifier: { id: 'b', uuid: 'b' } },
{ identifier: { id: 'c', uuid: 'c' } },
];
const actual = merge(localExtensions, remoteExtensions, baseExtensions, skippedExtensions, []);
......@@ -324,23 +370,23 @@ suite('ExtensionsMerge - No Conflicts', () => {
test('merge local and remote extensions when local is moved forwarded with skipped and ignored extensions', async () => {
const baseExtensions: ISyncExtension[] = [
{ identifier: { id: 'a', uuid: 'a' }, enabled: true },
{ identifier: { id: 'd', uuid: 'd' }, enabled: true },
{ identifier: { id: 'a', uuid: 'a' } },
{ identifier: { id: 'd', uuid: 'd' } },
];
const skippedExtensions: ISyncExtension[] = [
{ identifier: { id: 'd', uuid: 'd' }, enabled: true },
{ identifier: { id: 'd', uuid: 'd' } },
];
const localExtensions: ISyncExtension[] = [
{ identifier: { id: 'b', uuid: 'b' }, enabled: true },
{ identifier: { id: 'c', uuid: 'c' }, enabled: true },
{ identifier: { id: 'b', uuid: 'b' } },
{ identifier: { id: 'c', uuid: 'c' } },
];
const remoteExtensions: ISyncExtension[] = [
{ identifier: { id: 'a', uuid: 'a' }, enabled: true },
{ identifier: { id: 'd', uuid: 'd' }, enabled: true },
{ identifier: { id: 'a', uuid: 'a' } },
{ identifier: { id: 'd', uuid: 'd' } },
];
const expected: ISyncExtension[] = [
{ identifier: { id: 'd', uuid: 'd' }, enabled: true },
{ identifier: { id: 'b', uuid: 'b' }, enabled: true },
{ identifier: { id: 'd', uuid: 'd' } },
{ identifier: { id: 'b', uuid: 'b' } },
];
const actual = merge(localExtensions, remoteExtensions, baseExtensions, skippedExtensions, ['c']);
......@@ -353,28 +399,28 @@ suite('ExtensionsMerge - No Conflicts', () => {
test('merge local and remote extensions when both moved forwarded', async () => {
const baseExtensions: ISyncExtension[] = [
{ identifier: { id: 'a', uuid: 'a' }, enabled: true },
{ identifier: { id: 'd', uuid: 'd' }, enabled: true },
{ identifier: { id: 'a', uuid: 'a' } },
{ identifier: { id: 'd', uuid: 'd' } },
];
const localExtensions: ISyncExtension[] = [
{ identifier: { id: 'a', uuid: 'a' }, enabled: true },
{ identifier: { id: 'b', uuid: 'b' }, enabled: true },
{ identifier: { id: 'c', uuid: 'c' }, enabled: true },
{ identifier: { id: 'a', uuid: 'a' } },
{ identifier: { id: 'b', uuid: 'b' } },
{ identifier: { id: 'c', uuid: 'c' } },
];
const remoteExtensions: ISyncExtension[] = [
{ identifier: { id: 'd', uuid: 'd' }, enabled: true },
{ identifier: { id: 'b', uuid: 'b' }, enabled: true },
{ identifier: { id: 'e', uuid: 'e' }, enabled: true },
{ identifier: { id: 'd', uuid: 'd' } },
{ identifier: { id: 'b', uuid: 'b' } },
{ identifier: { id: 'e', uuid: 'e' } },
];
const expected: ISyncExtension[] = [
{ identifier: { id: 'b', uuid: 'b' }, enabled: true },
{ identifier: { id: 'e', uuid: 'e' }, enabled: true },
{ identifier: { id: 'c', uuid: 'c' }, enabled: true },
{ identifier: { id: 'b', uuid: 'b' } },
{ identifier: { id: 'e', uuid: 'e' } },
{ identifier: { id: 'c', uuid: 'c' } },
];
const actual = merge(localExtensions, remoteExtensions, baseExtensions, [], []);
assert.deepEqual(actual.added, [{ identifier: { id: 'e', uuid: 'e' }, enabled: true }]);
assert.deepEqual(actual.added, [{ identifier: { id: 'e', uuid: 'e' } }]);
assert.deepEqual(actual.removed, [{ id: 'a', uuid: 'a' }]);
assert.deepEqual(actual.updated, []);
assert.deepEqual(actual.remote, expected);
......@@ -382,23 +428,23 @@ suite('ExtensionsMerge - No Conflicts', () => {
test('merge local and remote extensions when both moved forwarded with ignored extensions', async () => {
const baseExtensions: ISyncExtension[] = [
{ identifier: { id: 'a', uuid: 'a' }, enabled: true },
{ identifier: { id: 'd', uuid: 'd' }, enabled: true },
{ identifier: { id: 'a', uuid: 'a' } },
{ identifier: { id: 'd', uuid: 'd' } },
];
const localExtensions: ISyncExtension[] = [
{ identifier: { id: 'a', uuid: 'a' }, enabled: true },
{ identifier: { id: 'b', uuid: 'b' }, enabled: true },
{ identifier: { id: 'c', uuid: 'c' }, enabled: true },
{ identifier: { id: 'a', uuid: 'a' } },
{ identifier: { id: 'b', uuid: 'b' } },
{ identifier: { id: 'c', uuid: 'c' } },
];
const remoteExtensions: ISyncExtension[] = [
{ identifier: { id: 'd', uuid: 'd' }, enabled: true },
{ identifier: { id: 'b', uuid: 'b' }, enabled: true },
{ identifier: { id: 'e', uuid: 'e' }, enabled: true },
{ identifier: { id: 'd', uuid: 'd' } },
{ identifier: { id: 'b', uuid: 'b' } },
{ identifier: { id: 'e', uuid: 'e' } },
];
const expected: ISyncExtension[] = [
{ identifier: { id: 'b', uuid: 'b' }, enabled: true },
{ identifier: { id: 'e', uuid: 'e' }, enabled: true },
{ identifier: { id: 'c', uuid: 'c' }, enabled: true },
{ identifier: { id: 'b', uuid: 'b' } },
{ identifier: { id: 'e', uuid: 'e' } },
{ identifier: { id: 'c', uuid: 'c' } },
];
const actual = merge(localExtensions, remoteExtensions, baseExtensions, [], ['a', 'e']);
......@@ -411,30 +457,30 @@ suite('ExtensionsMerge - No Conflicts', () => {
test('merge local and remote extensions when both moved forwarded with skipped extensions', async () => {
const baseExtensions: ISyncExtension[] = [
{ identifier: { id: 'a', uuid: 'a' }, enabled: true },
{ identifier: { id: 'd', uuid: 'd' }, enabled: true },
{ identifier: { id: 'a', uuid: 'a' } },
{ identifier: { id: 'd', uuid: 'd' } },
];
const skippedExtensions: ISyncExtension[] = [
{ identifier: { id: 'a', uuid: 'a' }, enabled: true },
{ identifier: { id: 'a', uuid: 'a' } },
];
const localExtensions: ISyncExtension[] = [
{ identifier: { id: 'b', uuid: 'b' }, enabled: true },
{ identifier: { id: 'c', uuid: 'c' }, enabled: true },
{ identifier: { id: 'b', uuid: 'b' } },
{ identifier: { id: 'c', uuid: 'c' } },
];
const remoteExtensions: ISyncExtension[] = [
{ identifier: { id: 'd', uuid: 'd' }, enabled: true },
{ identifier: { id: 'b', uuid: 'b' }, enabled: true },
{ identifier: { id: 'e', uuid: 'e' }, enabled: true },
{ identifier: { id: 'd', uuid: 'd' } },
{ identifier: { id: 'b', uuid: 'b' } },
{ identifier: { id: 'e', uuid: 'e' } },
];
const expected: ISyncExtension[] = [
{ identifier: { id: 'b', uuid: 'b' }, enabled: true },
{ identifier: { id: 'e', uuid: 'e' }, enabled: true },
{ identifier: { id: 'c', uuid: 'c' }, enabled: true },
{ identifier: { id: 'b', uuid: 'b' } },
{ identifier: { id: 'e', uuid: 'e' } },
{ identifier: { id: 'c', uuid: 'c' } },
];
const actual = merge(localExtensions, remoteExtensions, baseExtensions, skippedExtensions, []);
assert.deepEqual(actual.added, [{ identifier: { id: 'e', uuid: 'e' }, enabled: true }]);
assert.deepEqual(actual.added, [{ identifier: { id: 'e', uuid: 'e' } }]);
assert.deepEqual(actual.removed, []);
assert.deepEqual(actual.updated, []);
assert.deepEqual(actual.remote, expected);
......@@ -442,25 +488,25 @@ suite('ExtensionsMerge - No Conflicts', () => {
test('merge local and remote extensions when both moved forwarded with skipped and ignoredextensions', async () => {
const baseExtensions: ISyncExtension[] = [
{ identifier: { id: 'a', uuid: 'a' }, enabled: true },
{ identifier: { id: 'd', uuid: 'd' }, enabled: true },
{ identifier: { id: 'a', uuid: 'a' } },
{ identifier: { id: 'd', uuid: 'd' } },
];
const skippedExtensions: ISyncExtension[] = [
{ identifier: { id: 'a', uuid: 'a' }, enabled: true },
{ identifier: { id: 'a', uuid: 'a' } },
];
const localExtensions: ISyncExtension[] = [
{ identifier: { id: 'b', uuid: 'b' }, enabled: true },
{ identifier: { id: 'c', uuid: 'c' }, enabled: true },
{ identifier: { id: 'b', uuid: 'b' } },
{ identifier: { id: 'c', uuid: 'c' } },
];
const remoteExtensions: ISyncExtension[] = [
{ identifier: { id: 'd', uuid: 'd' }, enabled: true },
{ identifier: { id: 'b', uuid: 'b' }, enabled: true },
{ identifier: { id: 'e', uuid: 'e' }, enabled: true },
{ identifier: { id: 'd', uuid: 'd' } },
{ identifier: { id: 'b', uuid: 'b' } },
{ identifier: { id: 'e', uuid: 'e' } },
];
const expected: ISyncExtension[] = [
{ identifier: { id: 'b', uuid: 'b' }, enabled: true },
{ identifier: { id: 'e', uuid: 'e' }, enabled: true },
{ identifier: { id: 'c', uuid: 'c' }, enabled: true },
{ identifier: { id: 'b', uuid: 'b' } },
{ identifier: { id: 'e', uuid: 'e' } },
{ identifier: { id: 'c', uuid: 'c' } },
];
const actual = merge(localExtensions, remoteExtensions, baseExtensions, skippedExtensions, ['e']);
......@@ -473,24 +519,24 @@ suite('ExtensionsMerge - No Conflicts', () => {
test('merge when remote extension has no uuid and different extension id case', async () => {
const localExtensions: ISyncExtension[] = [
{ identifier: { id: 'a', uuid: 'a' }, enabled: true },
{ identifier: { id: 'b', uuid: 'b' }, enabled: true },
{ identifier: { id: 'c', uuid: 'c' }, enabled: true },
{ identifier: { id: 'a', uuid: 'a' } },
{ identifier: { id: 'b', uuid: 'b' } },
{ identifier: { id: 'c', uuid: 'c' } },
];
const remoteExtensions: ISyncExtension[] = [
{ identifier: { id: 'A' }, enabled: true },
{ identifier: { id: 'd', uuid: 'd' }, enabled: true },
{ identifier: { id: 'A' } },
{ identifier: { id: 'd', uuid: 'd' } },
];
const expected: ISyncExtension[] = [
{ identifier: { id: 'A' }, enabled: true },
{ identifier: { id: 'd', uuid: 'd' }, enabled: true },
{ identifier: { id: 'b', uuid: 'b' }, enabled: true },
{ identifier: { id: 'c', uuid: 'c' }, enabled: true },
{ identifier: { id: 'A', uuid: 'a' } },
{ identifier: { id: 'd', uuid: 'd' } },
{ identifier: { id: 'b', uuid: 'b' } },
{ identifier: { id: 'c', uuid: 'c' } },
];
const actual = merge(localExtensions, remoteExtensions, null, [], []);
assert.deepEqual(actual.added, [{ identifier: { id: 'd', uuid: 'd' }, enabled: true }]);
assert.deepEqual(actual.added, [{ identifier: { id: 'd', uuid: 'd' } }]);
assert.deepEqual(actual.removed, []);
assert.deepEqual(actual.updated, []);
assert.deepEqual(actual.remote, expected);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册