#155990 Improve extension merging (#162829)

- handle custom buultin extensions
This commit is contained in:
Sandeep Somavarapu 2022-10-06 14:35:17 +02:00 committed by GitHub
parent b2b7e0be6e
commit 3f21113b39
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 351 additions and 170 deletions

View file

@ -6,7 +6,7 @@
import { IStringDictionary } from 'vs/base/common/collections';
import { deepClone, equals } from 'vs/base/common/objects';
import * as semver from 'vs/base/common/semver/semver';
import { isUndefined } from 'vs/base/common/types';
import { assertIsDefined } from 'vs/base/common/types';
import { IExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import { ISyncExtension, ISyncExtensionWithVersion } from 'vs/platform/userDataSync/common/userDataSync';
@ -15,7 +15,7 @@ export interface IMergeResult {
readonly remote: { added: ISyncExtension[]; removed: ISyncExtension[]; updated: ISyncExtension[]; all: ISyncExtension[] } | null;
}
export function merge(localExtensions: ISyncExtensionWithVersion[], remoteExtensions: ISyncExtension[] | null, lastSyncExtensions: ISyncExtension[] | null, skippedExtensions: ISyncExtension[], ignoredExtensions: string[]): IMergeResult {
export function merge(localExtensions: ISyncExtensionWithVersion[], remoteExtensions: ISyncExtension[] | null, lastSyncExtensions: ISyncExtension[] | null, skippedExtensions: ISyncExtension[], ignoredExtensions: string[], lastSyncBuiltinExtensions: IExtensionIdentifier[]): IMergeResult {
const added: ISyncExtension[] = [];
const removed: IExtensionIdentifier[] = [];
const updated: ISyncExtensionWithVersion[] = [];
@ -57,138 +57,164 @@ export function merge(localExtensions: ISyncExtensionWithVersion[], remoteExtens
};
const localExtensionsMap: Map<string, ISyncExtensionWithVersion> = localExtensions.reduce(addExtensionToMap, new Map<string, ISyncExtensionWithVersion>());
const remoteExtensionsMap = remoteExtensions.reduce(addExtensionToMap, new Map<string, ISyncExtension>());
const newRemoteExtensionsMap = remoteExtensions.reduce((map: Map<string, ISyncExtension>, extension: ISyncExtension) => {
const key = getKey(extension);
extension = deepClone(extension);
const localExtension = localExtensionsMap.get(key);
if (localExtension) {
if (localExtension.installed) {
extension.installed = true;
}
if (!extension.version) {
extension.version = localExtension.version;
}
}
return addExtensionToMap(map, extension);
}, new Map<string, ISyncExtension>());
const newRemoteExtensionsMap = remoteExtensions.reduce((map: Map<string, ISyncExtension>, extension: ISyncExtension) => addExtensionToMap(map, deepClone(extension)), new Map<string, ISyncExtension>());
const lastSyncExtensionsMap = lastSyncExtensions ? lastSyncExtensions.reduce(addExtensionToMap, new Map<string, ISyncExtension>()) : null;
const skippedExtensionsMap = skippedExtensions.reduce(addExtensionToMap, new Map<string, ISyncExtension>());
const ignoredExtensionsSet = ignoredExtensions.reduce((set, id) => {
const uuid = uuids.get(id.toLowerCase());
return set.add(uuid ? `uuid:${uuid}` : `id:${id.toLowerCase()}`);
}, new Set<string>());
const lastSyncBuiltinExtensionsSet = lastSyncBuiltinExtensions.reduce((set, { id, uuid }) => {
uuid = uuid ?? uuids.get(id.toLowerCase());
return set.add(uuid ? `uuid:${uuid}` : `id:${id.toLowerCase()}`);
}, new Set<string>());
const localToRemote = compare(localExtensionsMap, remoteExtensionsMap, ignoredExtensionsSet);
const localToRemote = compare(localExtensionsMap, remoteExtensionsMap, ignoredExtensionsSet, false);
if (localToRemote.added.size > 0 || localToRemote.removed.size > 0 || localToRemote.updated.size > 0) {
const baseToLocal = compare(lastSyncExtensionsMap, localExtensionsMap, ignoredExtensionsSet);
const baseToRemote = compare(lastSyncExtensionsMap, remoteExtensionsMap, ignoredExtensionsSet);
const baseToLocal = compare(lastSyncExtensionsMap, localExtensionsMap, ignoredExtensionsSet, false);
const baseToRemote = compare(lastSyncExtensionsMap, remoteExtensionsMap, ignoredExtensionsSet, true);
const merge = (key: string, updatedInRemote: boolean): ISyncExtensionWithVersion | undefined => {
const localExtension = localExtensionsMap.get(key);
if (localExtension) {
const remoteExtension = remoteExtensionsMap.get(key)!;
const mergedExtension = updatedInRemote ? remoteExtension : localExtension;
return {
...mergedExtension,
version: remoteExtension.version && (!localExtension.installed || semver.gt(remoteExtension.version, localExtension.version)) ? remoteExtension.version : localExtension.version,
state: mergeExtensionState(localExtension, remoteExtension, lastSyncExtensionsMap?.get(key)),
preRelease: isUndefined(mergedExtension.preRelease) /* from older client*/ ? localExtension.preRelease
: (localExtension.installed ? mergedExtension.preRelease : remoteExtension.preRelease)
};
}
return undefined;
const merge = (key: string, localExtension: ISyncExtensionWithVersion, remoteExtension: ISyncExtension, preferred: ISyncExtension): ISyncExtensionWithVersion => {
return {
...preferred,
installed: localExtension.installed || remoteExtension.installed,
version: remoteExtension.version && (!localExtension.installed || semver.gt(remoteExtension.version, localExtension.version)) ? remoteExtension.version : localExtension.version,
state: mergeExtensionState(localExtension, remoteExtension, lastSyncExtensionsMap?.get(key)),
preRelease: (localExtension.installed ? preferred.preRelease : remoteExtension.preRelease) ?? /* from older client*/ localExtension.preRelease
};
};
// Remotely removed extension.
// Remotely removed extension => exist in base and does not in remote
for (const key of baseToRemote.removed.values()) {
const e = localExtensionsMap.get(key);
if (e) {
removed.push(e.identifier);
const localExtension = localExtensionsMap.get(key);
if (!localExtension) {
continue;
}
const baseExtension = assertIsDefined(lastSyncExtensionsMap?.get(key));
const wasAnInstalledExtensionDuringLastSync = !lastSyncBuiltinExtensionsSet.has(key) && baseExtension.installed;
if (localExtension.installed && wasAnInstalledExtensionDuringLastSync /* It is an installed extension now and during last sync */) {
// Installed extension is removed from remote. Remove it from local.
removed.push(localExtension.identifier);
} else {
// Add to remote: It is a builtin extenision or got installed after last sync
newRemoteExtensionsMap.set(key, localExtension);
}
}
// Remotely added extension
// Remotely added extension => does not exist in base and exist in remote
for (const key of baseToRemote.added.values()) {
// Got added in local
if (baseToLocal.added.has(key)) {
const remoteExtension = assertIsDefined(remoteExtensionsMap.get(key));
const localExtension = localExtensionsMap.get(key);
// Also exist in local
if (localExtension) {
// Is different from local to remote
if (localToRemote.updated.has(key)) {
const mergedExtension = merge(key, true);
if (mergedExtension) {
const mergedExtension = merge(key, localExtension, remoteExtension, remoteExtension);
// Update locally only when the extension has changes in properties other than installed poperty
if (!areSame(localExtension, remoteExtension, false, false)) {
updated.push(massageOutgoingExtension(mergedExtension, key));
newRemoteExtensionsMap.set(key, mergedExtension);
}
newRemoteExtensionsMap.set(key, mergedExtension);
}
} else {
// Add only installed extension to local
const remoteExtension = remoteExtensionsMap.get(key)!;
// Add only if the extension is an installed extension
if (remoteExtension.installed) {
added.push(massageOutgoingExtension(remoteExtension, key));
}
}
}
// Remotely updated extensions
// Remotely updated extension => exist in base and remote
for (const key of baseToRemote.updated.values()) {
// Update in local always
const mergedExtension = merge(key, true);
if (mergedExtension) {
updated.push(massageOutgoingExtension(mergedExtension, key));
newRemoteExtensionsMap.set(key, mergedExtension);
}
}
const remoteExtension = assertIsDefined(remoteExtensionsMap.get(key));
const baseExtension = assertIsDefined(lastSyncExtensionsMap?.get(key));
const localExtension = localExtensionsMap.get(key);
// Locally added extensions
for (const key of baseToLocal.added.values()) {
// Not there in remote
if (!baseToRemote.added.has(key)) {
newRemoteExtensionsMap.set(key, localExtensionsMap.get(key)!);
}
}
// Locally updated extensions
for (const key of baseToLocal.updated.values()) {
// If removed in remote
if (baseToRemote.removed.has(key)) {
continue;
}
// If not updated in remote
if (!baseToRemote.updated.has(key)) {
const mergedExtension = merge(key, false);
if (mergedExtension) {
// Retain installed property
if (newRemoteExtensionsMap.get(key)?.installed) {
mergedExtension.installed = true;
}
// Also exist in local
if (localExtension) {
const wasAnInstalledExtensionDuringLastSync = !lastSyncBuiltinExtensionsSet.has(key) && baseExtension.installed;
if (wasAnInstalledExtensionDuringLastSync && localExtension.installed && !remoteExtension.installed) {
// Remove it locally if it is installed locally and not remotely
removed.push(localExtension.identifier);
} else {
// Update in local always
const mergedExtension = merge(key, localExtension, remoteExtension, remoteExtension);
updated.push(massageOutgoingExtension(mergedExtension, key));
newRemoteExtensionsMap.set(key, mergedExtension);
}
}
// Add it locally if does not exist locally and installed remotely
else if (remoteExtension.installed) {
added.push(massageOutgoingExtension(remoteExtension, key));
}
}
// Locally removed extensions
for (const key of baseToLocal.removed.values()) {
// If not skipped and not updated in remote
if (!skippedExtensionsMap.has(key) && !baseToRemote.updated.has(key)) {
// Remove only if it is an installed extension
if (lastSyncExtensionsMap?.get(key)?.installed) {
newRemoteExtensionsMap.delete(key);
}
// Locally added extension => does not exist in base and exist in local
for (const key of baseToLocal.added.values()) {
// If added in remote (already handled)
if (baseToRemote.added.has(key)) {
continue;
}
newRemoteExtensionsMap.set(key, assertIsDefined(localExtensionsMap.get(key)));
}
// Locally updated extension => exist in base and local
for (const key of baseToLocal.updated.values()) {
// If removed in remote (already handled)
if (baseToRemote.removed.has(key)) {
continue;
}
// If updated in remote (already handled)
if (baseToRemote.updated.has(key)) {
continue;
}
const localExtension = assertIsDefined(localExtensionsMap.get(key));
const remoteExtension = assertIsDefined(remoteExtensionsMap.get(key));
// Update remotely
newRemoteExtensionsMap.set(key, merge(key, localExtension, remoteExtension, localExtension));
}
// Locally removed extensions => exist in base and does not exit in local
for (const key of baseToLocal.removed.values()) {
// If updated in remote (already handled)
if (baseToRemote.updated.has(key)) {
continue;
}
// If removed in remote (already handled)
if (baseToRemote.removed.has(key)) {
continue;
}
// Skipped
if (skippedExtensionsMap.has(key)) {
continue;
}
// Skip if it is a builtin extension
if (!assertIsDefined(remoteExtensionsMap.get(key)).installed) {
continue;
}
// Skip if it was a builtin extension during last sync
if (lastSyncBuiltinExtensionsSet.has(key) || !assertIsDefined(lastSyncExtensionsMap?.get(key)).installed) {
continue;
}
newRemoteExtensionsMap.delete(key);
}
}
const remote: ISyncExtension[] = [];
const remoteChanges = compare(remoteExtensionsMap, newRemoteExtensionsMap, new Set<string>(), { checkInstalledProperty: true, checkVersionProperty: true });
if (remoteChanges.added.size > 0 || remoteChanges.updated.size > 0 || remoteChanges.removed.size > 0) {
const remoteChanges = compare(remoteExtensionsMap, newRemoteExtensionsMap, new Set<string>(), true);
const hasRemoteChanges = remoteChanges.added.size > 0 || remoteChanges.updated.size > 0 || remoteChanges.removed.size > 0;
if (hasRemoteChanges) {
newRemoteExtensionsMap.forEach((value, key) => remote.push(massageOutgoingExtension(value, key)));
}
return {
local: { added, removed, updated },
remote: remote.length ? {
remote: hasRemoteChanges ? {
added: [...remoteChanges.added].map(id => newRemoteExtensionsMap.get(id)!),
updated: [...remoteChanges.updated].map(id => newRemoteExtensionsMap.get(id)!),
removed: [...remoteChanges.removed].map(id => remoteExtensionsMap.get(id)!),
@ -197,7 +223,7 @@ export function merge(localExtensions: ISyncExtensionWithVersion[], remoteExtens
};
}
function compare(from: Map<string, ISyncExtension> | null, to: Map<string, ISyncExtension>, ignoredExtensions: Set<string>, { checkInstalledProperty, checkVersionProperty }: { checkInstalledProperty: boolean; checkVersionProperty: boolean } = { checkInstalledProperty: false, checkVersionProperty: false }): { added: Set<string>; removed: Set<string>; updated: Set<string> } {
function compare(from: Map<string, ISyncExtension> | null, to: Map<string, ISyncExtension>, ignoredExtensions: Set<string>, checkVersionProperty: boolean): { added: Set<string>; removed: Set<string>; updated: Set<string> } {
const fromKeys = from ? [...from.keys()].filter(key => !ignoredExtensions.has(key)) : [];
const toKeys = [...to.keys()].filter(key => !ignoredExtensions.has(key));
const added = toKeys.filter(key => fromKeys.indexOf(key) === -1).reduce((r, key) => { r.add(key); return r; }, new Set<string>());
@ -210,13 +236,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.disabled !== toExtension.disabled
|| (fromExtension.installed && toExtension.installed && fromExtension.preRelease !== toExtension.preRelease)
|| !isSameExtensionState(fromExtension.state, toExtension.state)
|| (checkVersionProperty && fromExtension.version !== toExtension.version)
|| (checkInstalledProperty && fromExtension.installed !== toExtension.installed)
) {
if (!toExtension || !areSame(fromExtension, toExtension, checkVersionProperty, true)) {
updated.add(key);
}
}
@ -224,6 +244,18 @@ function compare(from: Map<string, ISyncExtension> | null, to: Map<string, ISync
return { added, removed, updated };
}
function areSame(fromExtension: ISyncExtension, toExtension: ISyncExtension, checkVersionProperty: boolean, checkInstalledProperty: boolean): boolean {
if (fromExtension.disabled !== toExtension.disabled /* extension enablement changed */
|| (checkInstalledProperty && fromExtension.installed !== toExtension.installed) /* extension installed property changed */
|| (fromExtension.installed && toExtension.installed && fromExtension.preRelease !== toExtension.preRelease) /* installed extension's pre-release version changed */
|| !isSameExtensionState(fromExtension.state, toExtension.state) /* extension state changed */
|| (checkVersionProperty && fromExtension.version !== toExtension.version) /* extension version changed */
) {
return false;
}
return true;
}
function mergeExtensionState(localExtension: ISyncExtensionWithVersion, remoteExtension: ISyncExtension, lastSyncExtension: ISyncExtension | undefined): IStringDictionary<any> | undefined {
const localState = localExtension.state;
const remoteState = remoteExtension.state;

View file

@ -37,12 +37,15 @@ type IExtensionResourceMergeResult = IAcceptResult & IExtensionMergeResult;
interface IExtensionResourcePreview extends IResourcePreview {
readonly localExtensions: ISyncExtensionWithVersion[];
readonly remoteExtensions: ISyncExtension[] | null;
readonly skippedExtensions: ISyncExtension[];
readonly builtinExtensions: IExtensionIdentifier[];
readonly previewResult: IExtensionResourceMergeResult;
}
interface ILastSyncUserData extends IRemoteUserData {
skippedExtensions: ISyncExtension[] | undefined;
builtinExtensions: IExtensionIdentifier[] | undefined;
}
async function parseAndMigrateExtensions(syncData: ISyncData, extensionManagementService: IExtensionManagementService): Promise<ISyncExtension[]> {
@ -127,6 +130,7 @@ export class ExtensionsSynchroniser extends AbstractSynchroniser implements IUse
protected async generateSyncPreview(remoteUserData: IRemoteUserData, lastSyncUserData: ILastSyncUserData | null): Promise<IExtensionResourcePreview[]> {
const remoteExtensions: ISyncExtension[] | null = remoteUserData.syncData ? await parseAndMigrateExtensions(remoteUserData.syncData, this.extensionManagementService) : null;
const skippedExtensions: ISyncExtension[] = lastSyncUserData?.skippedExtensions || [];
const builtinExtensions: IExtensionIdentifier[] = lastSyncUserData?.builtinExtensions || [];
const lastSyncExtensions: ISyncExtension[] | null = lastSyncUserData?.syncData ? await parseAndMigrateExtensions(lastSyncUserData.syncData, this.extensionManagementService) : null;
const installedExtensions = await this.extensionManagementService.getInstalled(undefined, this.profileLocation);
@ -139,7 +143,7 @@ export class ExtensionsSynchroniser extends AbstractSynchroniser implements IUse
this.logService.trace(`${this.syncResourceLogLabel}: Remote extensions does not exist. Synchronizing extensions for the first time.`);
}
const { local, remote } = merge(localExtensions, remoteExtensions, lastSyncExtensions, skippedExtensions, ignoredExtensions);
const { local, remote } = merge(localExtensions, remoteExtensions, lastSyncExtensions, skippedExtensions, ignoredExtensions, builtinExtensions);
const previewResult: IExtensionResourceMergeResult = {
local, remote,
content: this.getPreviewContent(localExtensions, local.added, local.updated, local.removed),
@ -150,12 +154,14 @@ export class ExtensionsSynchroniser extends AbstractSynchroniser implements IUse
const localContent = this.stringify(localExtensions, false);
return [{
skippedExtensions,
builtinExtensions,
baseResource: this.baseResource,
baseContent: lastSyncExtensions ? this.stringify(lastSyncExtensions, false) : localContent,
localResource: this.localResource,
localContent,
localExtensions,
remoteResource: this.remoteResource,
remoteExtensions,
remoteContent: remoteExtensions ? this.stringify(remoteExtensions, false) : null,
previewResource: this.previewResource,
previewResult,
@ -170,7 +176,7 @@ export class ExtensionsSynchroniser extends AbstractSynchroniser implements IUse
const installedExtensions = await this.extensionManagementService.getInstalled(undefined, this.profileLocation);
const localExtensions = await this.getLocalExtensions(installedExtensions);
const ignoredExtensions = this.ignoredExtensionsManagementService.getIgnoredExtensions(installedExtensions);
const { remote } = merge(localExtensions, lastSyncExtensions, lastSyncExtensions, lastSyncUserData.skippedExtensions || [], ignoredExtensions);
const { remote } = merge(localExtensions, lastSyncExtensions, lastSyncExtensions, lastSyncUserData.skippedExtensions || [], ignoredExtensions, lastSyncUserData.builtinExtensions || []);
return remote !== null;
}
@ -225,7 +231,7 @@ export class ExtensionsSynchroniser extends AbstractSynchroniser implements IUse
private async acceptLocal(resourcePreview: IExtensionResourcePreview): Promise<IExtensionResourceMergeResult> {
const installedExtensions = await this.extensionManagementService.getInstalled(undefined, this.profileLocation);
const ignoredExtensions = this.ignoredExtensionsManagementService.getIgnoredExtensions(installedExtensions);
const mergeResult = merge(resourcePreview.localExtensions, null, null, resourcePreview.skippedExtensions, ignoredExtensions);
const mergeResult = merge(resourcePreview.localExtensions, null, null, resourcePreview.skippedExtensions, ignoredExtensions, resourcePreview.builtinExtensions);
const { local, remote } = mergeResult;
return {
content: resourcePreview.localContent,
@ -241,7 +247,7 @@ export class ExtensionsSynchroniser extends AbstractSynchroniser implements IUse
const ignoredExtensions = this.ignoredExtensionsManagementService.getIgnoredExtensions(installedExtensions);
const remoteExtensions = resourcePreview.remoteContent ? JSON.parse(resourcePreview.remoteContent) : null;
if (remoteExtensions !== null) {
const mergeResult = merge(resourcePreview.localExtensions, remoteExtensions, resourcePreview.localExtensions, [], ignoredExtensions);
const mergeResult = merge(resourcePreview.localExtensions, remoteExtensions, resourcePreview.localExtensions, [], ignoredExtensions, resourcePreview.builtinExtensions);
const { local, remote } = mergeResult;
return {
content: resourcePreview.remoteContent,
@ -285,7 +291,8 @@ export class ExtensionsSynchroniser extends AbstractSynchroniser implements IUse
if (lastSyncUserData?.ref !== remoteUserData.ref) {
// update last sync
this.logService.trace(`${this.syncResourceLogLabel}: Updating last synchronized extensions...`);
await this.updateLastSyncUserData(remoteUserData, { skippedExtensions });
const builtinExtensions = localExtensions.filter(e => !e.installed).map(e => e.identifier);
await this.updateLastSyncUserData(remoteUserData, { skippedExtensions, builtinExtensions });
this.logService.info(`${this.syncResourceLogLabel}: Updated last synchronized extensions.${skippedExtensions.length ? ` Skipped: ${JSON.stringify(skippedExtensions.map(e => e.identifier.id))}.` : ''}`);
}
}

View file

@ -16,7 +16,7 @@ suite('ExtensionsMerge', () => {
{ identifier: { id: 'c', uuid: 'c' }, installed: true, version: '1.0.0' },
];
const actual = merge(localExtensions, null, null, [], []);
const actual = merge(localExtensions, null, null, [], [], []);
assert.deepStrictEqual(actual.local.added, []);
assert.deepStrictEqual(actual.local.removed, []);
@ -35,7 +35,7 @@ suite('ExtensionsMerge', () => {
{ identifier: { id: 'c', uuid: 'c' }, installed: true, version: '1.0.0' },
];
const actual = merge(localExtensions, null, null, [], ['a']);
const actual = merge(localExtensions, null, null, [], ['a'], []);
assert.deepStrictEqual(actual.local.added, []);
assert.deepStrictEqual(actual.local.removed, []);
@ -54,7 +54,7 @@ suite('ExtensionsMerge', () => {
{ identifier: { id: 'c', uuid: 'c' }, installed: true, version: '1.0.0' },
];
const actual = merge(localExtensions, null, null, [], ['A']);
const actual = merge(localExtensions, null, null, [], ['A'], []);
assert.deepStrictEqual(actual.local.added, []);
assert.deepStrictEqual(actual.local.removed, []);
@ -77,7 +77,7 @@ suite('ExtensionsMerge', () => {
{ identifier: { id: 'c', uuid: 'c' }, installed: true, version: '1.0.0' },
];
const actual = merge(localExtensions, null, null, skippedExtension, []);
const actual = merge(localExtensions, null, null, skippedExtension, [], []);
assert.deepStrictEqual(actual.local.added, []);
assert.deepStrictEqual(actual.local.removed, []);
@ -99,7 +99,7 @@ suite('ExtensionsMerge', () => {
{ identifier: { id: 'c', uuid: 'c' }, installed: true, version: '1.0.0' },
];
const actual = merge(localExtensions, null, null, skippedExtension, ['a']);
const actual = merge(localExtensions, null, null, skippedExtension, ['a'], []);
assert.deepStrictEqual(actual.local.added, []);
assert.deepStrictEqual(actual.local.removed, []);
@ -123,7 +123,7 @@ suite('ExtensionsMerge', () => {
{ identifier: { id: 'd', uuid: 'd' }, installed: true, version: '1.0.0', preRelease: false },
];
const actual = merge(localExtensions, remoteExtensions, null, [], []);
const actual = merge(localExtensions, remoteExtensions, null, [], [], []);
assert.deepStrictEqual(actual.local.added, [{ identifier: { id: 'b', uuid: 'b' }, installed: true, version: '1.0.0', preRelease: false }, { identifier: { id: 'c', uuid: 'c' }, installed: true, version: '1.0.0', preRelease: false }]);
assert.deepStrictEqual(actual.local.removed, []);
@ -146,7 +146,7 @@ suite('ExtensionsMerge', () => {
{ identifier: { id: 'd', uuid: 'd' }, installed: true, version: '1.0.0', preRelease: false },
];
const actual = merge(localExtensions, remoteExtensions, null, [], ['a']);
const actual = merge(localExtensions, remoteExtensions, null, [], ['a'], []);
assert.deepStrictEqual(actual.local.added, [{ identifier: { id: 'b', uuid: 'b' }, installed: true, version: '1.0.0', preRelease: false }, { identifier: { id: 'c', uuid: 'c' }, installed: true, version: '1.0.0', preRelease: false }]);
assert.deepStrictEqual(actual.local.removed, []);
@ -168,7 +168,7 @@ suite('ExtensionsMerge', () => {
{ identifier: { id: 'c', uuid: 'c' }, installed: true, version: '1.0.0' },
];
const actual = merge(localExtensions, remoteExtensions, baseExtensions, [], []);
const actual = merge(localExtensions, remoteExtensions, baseExtensions, [], [], []);
assert.deepStrictEqual(actual.local.added, [{ identifier: { id: 'b', uuid: 'b' }, installed: true, version: '1.0.0', preRelease: false }, { identifier: { id: 'c', uuid: 'c' }, installed: true, version: '1.0.0', preRelease: false }]);
assert.deepStrictEqual(actual.local.removed, [{ id: 'a', uuid: 'a' }, { id: 'd', uuid: 'd' }]);
@ -191,7 +191,7 @@ suite('ExtensionsMerge', () => {
{ identifier: { id: 'd', uuid: 'd' }, disabled: true, installed: true, version: '1.0.0' },
];
const actual = merge(localExtensions, remoteExtensions, baseExtensions, [], []);
const actual = merge(localExtensions, remoteExtensions, baseExtensions, [], [], []);
assert.deepStrictEqual(actual.local.added, [{ identifier: { id: 'b', uuid: 'b' }, installed: true, version: '1.0.0', preRelease: false }, { identifier: { id: 'c', uuid: 'c' }, installed: true, version: '1.0.0', preRelease: false }]);
assert.deepStrictEqual(actual.local.removed, [{ id: 'a', uuid: 'a' }]);
@ -213,7 +213,7 @@ suite('ExtensionsMerge', () => {
{ identifier: { id: 'c', uuid: 'c' }, installed: true, version: '1.0.0' },
];
const actual = merge(localExtensions, remoteExtensions, baseExtensions, [], ['a']);
const actual = merge(localExtensions, remoteExtensions, baseExtensions, [], ['a'], []);
assert.deepStrictEqual(actual.local.added, [{ identifier: { id: 'b', uuid: 'b' }, installed: true, version: '1.0.0', preRelease: false }, { identifier: { id: 'c', uuid: 'c' }, installed: true, version: '1.0.0', preRelease: false }]);
assert.deepStrictEqual(actual.local.removed, [{ id: 'd', uuid: 'd' }]);
@ -237,7 +237,7 @@ suite('ExtensionsMerge', () => {
{ identifier: { id: 'c', uuid: 'c' }, installed: true, version: '1.0.0' },
];
const actual = merge(localExtensions, remoteExtensions, baseExtensions, skippedExtensions, []);
const actual = merge(localExtensions, remoteExtensions, baseExtensions, skippedExtensions, [], []);
assert.deepStrictEqual(actual.local.added, [{ identifier: { id: 'b', uuid: 'b' }, installed: true, version: '1.0.0', preRelease: false }, { identifier: { id: 'c', uuid: 'c' }, installed: true, version: '1.0.0', preRelease: false }]);
assert.deepStrictEqual(actual.local.removed, [{ id: 'd', uuid: 'd' }]);
@ -261,7 +261,7 @@ suite('ExtensionsMerge', () => {
{ identifier: { id: 'c', uuid: 'c' }, installed: true, version: '1.0.0' },
];
const actual = merge(localExtensions, remoteExtensions, baseExtensions, skippedExtensions, ['b']);
const actual = merge(localExtensions, remoteExtensions, baseExtensions, skippedExtensions, ['b'], []);
assert.deepStrictEqual(actual.local.added, [{ identifier: { id: 'c', uuid: 'c' }, installed: true, version: '1.0.0', preRelease: false }]);
assert.deepStrictEqual(actual.local.removed, [{ id: 'd', uuid: 'd' }]);
@ -270,9 +270,9 @@ suite('ExtensionsMerge', () => {
});
test('merge local and remote extensions when local is moved forwarded', () => {
const baseExtensions: ISyncExtension[] = [
{ identifier: { id: 'a', uuid: 'a' }, installed: true },
{ identifier: { id: 'd', uuid: 'd' }, installed: true },
const baseExtensions: ISyncExtensionWithVersion[] = [
{ identifier: { id: 'a', uuid: 'a' }, installed: true, version: '1.0.0' },
{ identifier: { id: 'd', uuid: 'd' }, installed: true, version: '1.0.0' },
];
const localExtensions: ISyncExtensionWithVersion[] = [
{ identifier: { id: 'b', uuid: 'b' }, installed: true, version: '1.0.0' },
@ -287,7 +287,7 @@ suite('ExtensionsMerge', () => {
{ identifier: { id: 'c', uuid: 'c' }, installed: true, version: '1.0.0', preRelease: false },
];
const actual = merge(localExtensions, remoteExtensions, baseExtensions, [], []);
const actual = merge(localExtensions, remoteExtensions, baseExtensions, [], [], []);
assert.deepStrictEqual(actual.local.added, []);
assert.deepStrictEqual(actual.local.removed, []);
@ -296,9 +296,9 @@ suite('ExtensionsMerge', () => {
});
test('merge local and remote extensions when local is moved forwarded with disabled extensions', () => {
const baseExtensions: ISyncExtension[] = [
{ identifier: { id: 'a', uuid: 'a' }, installed: true },
{ identifier: { id: 'd', uuid: 'd' }, installed: true },
const baseExtensions: ISyncExtensionWithVersion[] = [
{ identifier: { id: 'a', uuid: 'a' }, installed: true, version: '1.0.0' },
{ identifier: { id: 'd', uuid: 'd' }, installed: true, version: '1.0.0' },
];
const localExtensions: ISyncExtensionWithVersion[] = [
{ identifier: { id: 'a', uuid: 'a' }, disabled: true, installed: true, version: '1.0.0' },
@ -315,7 +315,7 @@ suite('ExtensionsMerge', () => {
{ identifier: { id: 'c', uuid: 'c' }, installed: true, version: '1.0.0', preRelease: false },
];
const actual = merge(localExtensions, remoteExtensions, baseExtensions, [], []);
const actual = merge(localExtensions, remoteExtensions, baseExtensions, [], [], []);
assert.deepStrictEqual(actual.local.added, []);
assert.deepStrictEqual(actual.local.removed, []);
@ -324,9 +324,9 @@ suite('ExtensionsMerge', () => {
});
test('merge local and remote extensions when local is moved forwarded with ignored settings', () => {
const baseExtensions: ISyncExtension[] = [
{ identifier: { id: 'a', uuid: 'a' }, installed: true },
{ identifier: { id: 'd', uuid: 'd' }, installed: true },
const baseExtensions: ISyncExtensionWithVersion[] = [
{ identifier: { id: 'a', uuid: 'a' }, installed: true, version: '1.0.0' },
{ identifier: { id: 'd', uuid: 'd' }, installed: true, version: '1.0.0' },
];
const localExtensions: ISyncExtensionWithVersion[] = [
{ identifier: { id: 'b', uuid: 'b' }, installed: true, version: '1.0.0' },
@ -337,7 +337,7 @@ suite('ExtensionsMerge', () => {
{ identifier: { id: 'd', uuid: 'd' }, installed: true, version: '1.0.0' },
];
const actual = merge(localExtensions, remoteExtensions, baseExtensions, [], ['b']);
const actual = merge(localExtensions, remoteExtensions, baseExtensions, [], ['b'], []);
assert.deepStrictEqual(actual.local.added, []);
assert.deepStrictEqual(actual.local.removed, []);
@ -348,9 +348,9 @@ suite('ExtensionsMerge', () => {
});
test('merge local and remote extensions when local is moved forwarded with skipped extensions', () => {
const baseExtensions: ISyncExtension[] = [
{ identifier: { id: 'a', uuid: 'a' }, installed: true },
{ identifier: { id: 'd', uuid: 'd' }, installed: true },
const baseExtensions: ISyncExtensionWithVersion[] = [
{ identifier: { id: 'a', uuid: 'a' }, installed: true, version: '1.0.0' },
{ identifier: { id: 'd', uuid: 'd' }, installed: true, version: '1.0.0' },
];
const skippedExtensions: ISyncExtension[] = [
{ identifier: { id: 'd', uuid: 'd' }, installed: true },
@ -369,7 +369,7 @@ suite('ExtensionsMerge', () => {
{ identifier: { id: 'c', uuid: 'c' }, installed: true, version: '1.0.0', preRelease: false },
];
const actual = merge(localExtensions, remoteExtensions, baseExtensions, skippedExtensions, []);
const actual = merge(localExtensions, remoteExtensions, baseExtensions, skippedExtensions, [], []);
assert.deepStrictEqual(actual.local.added, []);
assert.deepStrictEqual(actual.local.removed, []);
@ -378,9 +378,9 @@ suite('ExtensionsMerge', () => {
});
test('merge local and remote extensions when local is moved forwarded with skipped and ignored extensions', () => {
const baseExtensions: ISyncExtension[] = [
{ identifier: { id: 'a', uuid: 'a' }, installed: true },
{ identifier: { id: 'd', uuid: 'd' }, installed: true },
const baseExtensions: ISyncExtensionWithVersion[] = [
{ identifier: { id: 'a', uuid: 'a' }, installed: true, version: '1.0.0' },
{ identifier: { id: 'd', uuid: 'd' }, installed: true, version: '1.0.0' },
];
const skippedExtensions: ISyncExtension[] = [
{ identifier: { id: 'd', uuid: 'd' }, installed: true },
@ -398,7 +398,7 @@ suite('ExtensionsMerge', () => {
{ identifier: { id: 'b', uuid: 'b' }, installed: true, version: '1.0.0', preRelease: false },
];
const actual = merge(localExtensions, remoteExtensions, baseExtensions, skippedExtensions, ['c']);
const actual = merge(localExtensions, remoteExtensions, baseExtensions, skippedExtensions, ['c'], []);
assert.deepStrictEqual(actual.local.added, []);
assert.deepStrictEqual(actual.local.removed, []);
@ -407,9 +407,9 @@ suite('ExtensionsMerge', () => {
});
test('merge local and remote extensions when both moved forwarded', () => {
const baseExtensions: ISyncExtension[] = [
{ identifier: { id: 'a', uuid: 'a' }, installed: true },
{ identifier: { id: 'd', uuid: 'd' }, installed: true },
const baseExtensions: ISyncExtensionWithVersion[] = [
{ identifier: { id: 'a', uuid: 'a' }, installed: true, version: '1.0.0' },
{ identifier: { id: 'd', uuid: 'd' }, installed: true, version: '1.0.0' },
];
const localExtensions: ISyncExtensionWithVersion[] = [
{ identifier: { id: 'a', uuid: 'a' }, installed: true, version: '1.0.0' },
@ -427,7 +427,7 @@ suite('ExtensionsMerge', () => {
{ identifier: { id: 'c', uuid: 'c' }, installed: true, version: '1.0.0', preRelease: false },
];
const actual = merge(localExtensions, remoteExtensions, baseExtensions, [], []);
const actual = merge(localExtensions, remoteExtensions, baseExtensions, [], [], []);
assert.deepStrictEqual(actual.local.added, [{ identifier: { id: 'e', uuid: 'e' }, installed: true, version: '1.0.0', preRelease: false }]);
assert.deepStrictEqual(actual.local.removed, [{ id: 'a', uuid: 'a' }]);
@ -436,9 +436,9 @@ suite('ExtensionsMerge', () => {
});
test('merge local and remote extensions when both moved forwarded with ignored extensions', () => {
const baseExtensions: ISyncExtension[] = [
{ identifier: { id: 'a', uuid: 'a' }, installed: true },
{ identifier: { id: 'd', uuid: 'd' }, installed: true },
const baseExtensions: ISyncExtensionWithVersion[] = [
{ identifier: { id: 'a', uuid: 'a' }, installed: true, version: '1.0.0' },
{ identifier: { id: 'd', uuid: 'd' }, installed: true, version: '1.0.0' },
];
const localExtensions: ISyncExtensionWithVersion[] = [
{ identifier: { id: 'a', uuid: 'a' }, installed: true, version: '1.0.0' },
@ -456,7 +456,7 @@ suite('ExtensionsMerge', () => {
{ identifier: { id: 'c', uuid: 'c' }, installed: true, version: '1.0.0', preRelease: false },
];
const actual = merge(localExtensions, remoteExtensions, baseExtensions, [], ['a', 'e']);
const actual = merge(localExtensions, remoteExtensions, baseExtensions, [], ['a', 'e'], []);
assert.deepStrictEqual(actual.local.added, []);
assert.deepStrictEqual(actual.local.removed, []);
@ -465,9 +465,9 @@ suite('ExtensionsMerge', () => {
});
test('merge local and remote extensions when both moved forwarded with skipped extensions', () => {
const baseExtensions: ISyncExtension[] = [
{ identifier: { id: 'a', uuid: 'a' }, installed: true },
{ identifier: { id: 'd', uuid: 'd' }, installed: true },
const baseExtensions: ISyncExtensionWithVersion[] = [
{ identifier: { id: 'a', uuid: 'a' }, installed: true, version: '1.0.0' },
{ identifier: { id: 'd', uuid: 'd' }, installed: true, version: '1.0.0' },
];
const skippedExtensions: ISyncExtension[] = [
{ identifier: { id: 'a', uuid: 'a' }, installed: true },
@ -487,7 +487,7 @@ suite('ExtensionsMerge', () => {
{ identifier: { id: 'c', uuid: 'c' }, installed: true, version: '1.0.0', preRelease: false },
];
const actual = merge(localExtensions, remoteExtensions, baseExtensions, skippedExtensions, []);
const actual = merge(localExtensions, remoteExtensions, baseExtensions, skippedExtensions, [], []);
assert.deepStrictEqual(actual.local.added, [{ identifier: { id: 'e', uuid: 'e' }, installed: true, version: '1.0.0', preRelease: false }]);
assert.deepStrictEqual(actual.local.removed, []);
@ -496,9 +496,9 @@ suite('ExtensionsMerge', () => {
});
test('merge local and remote extensions when both moved forwarded with skipped and ignoredextensions', () => {
const baseExtensions: ISyncExtension[] = [
{ identifier: { id: 'a', uuid: 'a' }, installed: true },
{ identifier: { id: 'd', uuid: 'd' }, installed: true },
const baseExtensions: ISyncExtensionWithVersion[] = [
{ identifier: { id: 'a', uuid: 'a' }, installed: true, version: '1.0.0' },
{ identifier: { id: 'd', uuid: 'd' }, installed: true, version: '1.0.0' },
];
const skippedExtensions: ISyncExtension[] = [
{ identifier: { id: 'a', uuid: 'a' }, installed: true },
@ -518,7 +518,7 @@ suite('ExtensionsMerge', () => {
{ identifier: { id: 'c', uuid: 'c' }, installed: true, version: '1.0.0', preRelease: false },
];
const actual = merge(localExtensions, remoteExtensions, baseExtensions, skippedExtensions, ['e']);
const actual = merge(localExtensions, remoteExtensions, baseExtensions, skippedExtensions, ['e'], []);
assert.deepStrictEqual(actual.local.added, []);
assert.deepStrictEqual(actual.local.removed, []);
@ -543,7 +543,7 @@ suite('ExtensionsMerge', () => {
{ identifier: { id: 'c', uuid: 'c' }, installed: true, version: '1.0.0', preRelease: false },
];
const actual = merge(localExtensions, remoteExtensions, null, [], []);
const actual = merge(localExtensions, remoteExtensions, null, [], [], []);
assert.deepStrictEqual(actual.local.added, [{ identifier: { id: 'd', uuid: 'd' }, installed: true, version: '1.0.0', preRelease: false }]);
assert.deepStrictEqual(actual.local.removed, []);
@ -560,7 +560,7 @@ suite('ExtensionsMerge', () => {
{ identifier: { id: 'b', uuid: 'b' }, version: '1.0.0' },
];
const actual = merge(localExtensions, remoteExtensions, null, [], []);
const actual = merge(localExtensions, remoteExtensions, null, [], [], []);
assert.deepStrictEqual(actual.local.added, []);
assert.deepStrictEqual(actual.local.removed, []);
@ -579,7 +579,7 @@ suite('ExtensionsMerge', () => {
{ identifier: { id: 'a', uuid: 'a' }, installed: true, version: '1.0.0', preRelease: false },
];
const actual = merge(localExtensions, remoteExtensions, null, [], []);
const actual = merge(localExtensions, remoteExtensions, null, [], [], []);
assert.deepStrictEqual(actual.local.added, []);
assert.deepStrictEqual(actual.local.removed, []);
@ -596,7 +596,7 @@ suite('ExtensionsMerge', () => {
{ identifier: { id: 'b', uuid: 'b' }, version: '1.0.0' },
];
const actual = merge(localExtensions, remoteExtensions, remoteExtensions, [], []);
const actual = merge(localExtensions, remoteExtensions, remoteExtensions, [], [], []);
assert.deepStrictEqual(actual.local.added, []);
assert.deepStrictEqual(actual.local.removed, []);
@ -615,7 +615,7 @@ suite('ExtensionsMerge', () => {
{ identifier: { id: 'a', uuid: 'a' }, installed: true, disabled: true, version: '1.0.0', preRelease: false },
];
const actual = merge(localExtensions, remoteExtensions, remoteExtensions, [], []);
const actual = merge(localExtensions, remoteExtensions, remoteExtensions, [], [], []);
assert.deepStrictEqual(actual.local.added, []);
assert.deepStrictEqual(actual.local.removed, []);
@ -631,7 +631,7 @@ suite('ExtensionsMerge', () => {
{ identifier: { id: 'a', uuid: 'a' }, installed: true, disabled: true, version: '1.0.0' },
];
const actual = merge(localExtensions, remoteExtensions, localExtensions, [], []);
const actual = merge(localExtensions, remoteExtensions, localExtensions, [], [], []);
assert.deepStrictEqual(actual.local.added, []);
assert.deepStrictEqual(actual.local.removed, []);
@ -653,7 +653,7 @@ suite('ExtensionsMerge', () => {
{ identifier: { id: 'a', uuid: 'a' }, version: '1.0.0', preRelease: false },
];
const actual = merge(localExtensions, remoteExtensions, null, [], []);
const actual = merge(localExtensions, remoteExtensions, null, [], [], []);
assert.deepStrictEqual(actual.local.added, []);
assert.deepStrictEqual(actual.local.removed, []);
@ -667,7 +667,7 @@ suite('ExtensionsMerge', () => {
{ identifier: { id: 'a', uuid: 'a' }, version: '1.0.0', installed: true, preRelease: true },
];
const actual = merge(localExtensions, remoteExtensions, null, [], []);
const actual = merge(localExtensions, remoteExtensions, null, [], [], []);
assert.deepStrictEqual(actual.local.added, [{ identifier: { id: 'a', uuid: 'a' }, version: '1.0.0', installed: true, preRelease: true }]);
assert.deepStrictEqual(actual.local.removed, []);
@ -681,7 +681,7 @@ suite('ExtensionsMerge', () => {
];
const remoteExtensions: ISyncExtensionWithVersion[] = [];
const actual = merge(localExtensions, remoteExtensions, null, [], []);
const actual = merge(localExtensions, remoteExtensions, null, [], [], []);
assert.deepStrictEqual(actual.local.added, []);
assert.deepStrictEqual(actual.local.removed, []);
@ -697,7 +697,7 @@ suite('ExtensionsMerge', () => {
{ identifier: { id: 'a', uuid: 'a' }, version: '1.0.0', installed: true, preRelease: true },
];
const actual = merge(localExtensions, remoteExtensions, null, [], []);
const actual = merge(localExtensions, remoteExtensions, null, [], [], []);
assert.deepStrictEqual(actual.local.added, []);
assert.deepStrictEqual(actual.local.removed, []);
@ -713,7 +713,7 @@ suite('ExtensionsMerge', () => {
{ identifier: { id: 'a', uuid: 'a' }, version: '1.0.0', installed: true },
];
const actual = merge(localExtensions, remoteExtensions, null, [], []);
const actual = merge(localExtensions, remoteExtensions, null, [], [], []);
assert.deepStrictEqual(actual.local.added, []);
assert.deepStrictEqual(actual.local.removed, []);
@ -729,7 +729,7 @@ suite('ExtensionsMerge', () => {
{ identifier: { id: 'a', uuid: 'a' }, version: '1.0.0', installed: true, preRelease: true },
];
const actual = merge(localExtensions, remoteExtensions, localExtensions, [], []);
const actual = merge(localExtensions, remoteExtensions, localExtensions, [], [], []);
assert.deepStrictEqual(actual.local.added, []);
assert.deepStrictEqual(actual.local.removed, []);
@ -745,7 +745,7 @@ suite('ExtensionsMerge', () => {
{ identifier: { id: 'a', uuid: 'a' }, version: '1.0.0', installed: true, preRelease: false },
];
const actual = merge(localExtensions, remoteExtensions, localExtensions, [], []);
const actual = merge(localExtensions, remoteExtensions, localExtensions, [], [], []);
assert.deepStrictEqual(actual.local.added, []);
assert.deepStrictEqual(actual.local.removed, []);
@ -761,7 +761,7 @@ suite('ExtensionsMerge', () => {
{ identifier: { id: 'a', uuid: 'a' }, version: '1.0.0', installed: true },
];
const actual = merge(localExtensions, remoteExtensions, remoteExtensions, [], []);
const actual = merge(localExtensions, remoteExtensions, remoteExtensions, [], [], []);
assert.deepStrictEqual(actual.local.added, []);
assert.deepStrictEqual(actual.local.removed, []);
@ -777,7 +777,7 @@ suite('ExtensionsMerge', () => {
{ identifier: { id: 'a', uuid: 'a' }, version: '1.0.0', installed: true, preRelease: true },
];
const actual = merge(localExtensions, remoteExtensions, remoteExtensions, [], []);
const actual = merge(localExtensions, remoteExtensions, remoteExtensions, [], [], []);
assert.deepStrictEqual(actual.local.added, []);
assert.deepStrictEqual(actual.local.removed, []);
@ -793,7 +793,7 @@ suite('ExtensionsMerge', () => {
{ identifier: { id: 'a', uuid: 'a' }, version: '1.0.0', installed: true, preRelease: true },
];
const actual = merge(localExtensions, remoteExtensions, remoteExtensions, [], []);
const actual = merge(localExtensions, remoteExtensions, remoteExtensions, [], [], []);
assert.deepStrictEqual(actual.local.added, []);
assert.deepStrictEqual(actual.local.removed, []);
@ -809,7 +809,7 @@ suite('ExtensionsMerge', () => {
{ identifier: { id: 'a', uuid: 'a' }, version: '1.0.0', installed: true, preRelease: true },
];
const actual = merge(localExtensions, remoteExtensions, remoteExtensions, [], []);
const actual = merge(localExtensions, remoteExtensions, remoteExtensions, [], [], []);
assert.deepStrictEqual(actual.local.added, []);
assert.deepStrictEqual(actual.local.removed, []);
@ -828,7 +828,7 @@ suite('ExtensionsMerge', () => {
{ identifier: { id: 'a', uuid: 'a' }, version: '1.0.0', installed: true, preRelease: true, disabled: true },
];
const actual = merge(localExtensions, remoteExtensions, baseExtensions, [], []);
const actual = merge(localExtensions, remoteExtensions, baseExtensions, [], [], []);
assert.deepStrictEqual(actual.local.added, []);
assert.deepStrictEqual(actual.local.removed, []);
@ -844,7 +844,7 @@ suite('ExtensionsMerge', () => {
{ identifier: { id: 'a', uuid: 'a' }, version: '1.1.0', installed: true, preRelease: false },
];
const actual = merge(localExtensions, remoteExtensions, remoteExtensions, [], []);
const actual = merge(localExtensions, remoteExtensions, remoteExtensions, [], [], []);
assert.deepStrictEqual(actual.local.added, []);
assert.deepStrictEqual(actual.local.removed, []);
@ -860,7 +860,7 @@ suite('ExtensionsMerge', () => {
{ identifier: { id: 'a', uuid: 'a' }, version: '1.1.0', installed: true, preRelease: false },
];
const actual = merge(localExtensions, remoteExtensions, remoteExtensions, [], []);
const actual = merge(localExtensions, remoteExtensions, remoteExtensions, [], [], []);
assert.deepStrictEqual(actual.local.added, []);
assert.deepStrictEqual(actual.local.removed, []);
@ -879,7 +879,7 @@ suite('ExtensionsMerge', () => {
{ identifier: { id: 'a', uuid: 'a' }, version: '1.1.0', installed: true, preRelease: false, disabled: true },
];
const actual = merge(localExtensions, remoteExtensions, baseExtensions, [], []);
const actual = merge(localExtensions, remoteExtensions, baseExtensions, [], [], []);
assert.deepStrictEqual(actual.local.added, []);
assert.deepStrictEqual(actual.local.removed, []);
@ -887,4 +887,146 @@ suite('ExtensionsMerge', () => {
assert.deepStrictEqual(actual.remote, null);
});
test('merge: base has builtin extension, local does not have extension, remote has extension installed', () => {
const localExtensions: ISyncExtensionWithVersion[] = [];
const baseExtensions: ISyncExtensionWithVersion[] = [
{ identifier: { id: 'a', uuid: 'a' }, version: '1.1.0', installed: false, preRelease: false },
];
const remoteExtensions: ISyncExtensionWithVersion[] = [
{ identifier: { id: 'a', uuid: 'a' }, version: '1.1.0', installed: true, preRelease: false },
];
const actual = merge(localExtensions, remoteExtensions, baseExtensions, [], [], []);
assert.deepStrictEqual(actual.local.added, [{ identifier: { id: 'a', uuid: 'a' }, version: '1.1.0', installed: true, preRelease: false }]);
assert.deepStrictEqual(actual.local.removed, []);
assert.deepStrictEqual(actual.local.updated, []);
assert.deepStrictEqual(actual.remote, null);
});
test('merge: base has installed extension, local has installed extension, remote has extension builtin', () => {
const localExtensions: ISyncExtensionWithVersion[] = [
{ identifier: { id: 'a', uuid: 'a' }, version: '1.0.0', installed: true },
];
const baseExtensions: ISyncExtensionWithVersion[] = [
{ identifier: { id: 'a', uuid: 'a' }, version: '1.0.0', installed: true },
];
const remoteExtensions: ISyncExtensionWithVersion[] = [
{ identifier: { id: 'a', uuid: 'a' }, version: '1.0.0', installed: false },
];
const actual = merge(localExtensions, remoteExtensions, baseExtensions, [], [], []);
assert.deepStrictEqual(actual.local.added, []);
assert.deepStrictEqual(actual.local.removed, [{ id: 'a', uuid: 'a' }]);
assert.deepStrictEqual(actual.local.updated, []);
assert.deepStrictEqual(actual.remote, null);
});
test('merge: base has installed extension, local has builtin extension, remote does not has extension', () => {
const localExtensions: ISyncExtensionWithVersion[] = [
{ identifier: { id: 'a', uuid: 'a' }, version: '1.0.0', installed: false },
];
const baseExtensions: ISyncExtensionWithVersion[] = [
{ identifier: { id: 'a', uuid: 'a' }, version: '1.0.0', installed: true },
];
const remoteExtensions: ISyncExtensionWithVersion[] = [];
const actual = merge(localExtensions, remoteExtensions, baseExtensions, [], [], []);
assert.deepStrictEqual(actual.local.added, []);
assert.deepStrictEqual(actual.local.removed, []);
assert.deepStrictEqual(actual.local.updated, []);
assert.deepStrictEqual(actual.remote?.all, [{ identifier: { id: 'a', uuid: 'a' }, version: '1.0.0', preRelease: false }]);
});
test('merge: base has builtin extension, local has installed extension, remote has builtin extension with updated state', () => {
const localExtensions: ISyncExtensionWithVersion[] = [
{ identifier: { id: 'a', uuid: 'a' }, version: '1.0.0', installed: true },
];
const baseExtensions: ISyncExtensionWithVersion[] = [
{ identifier: { id: 'a', uuid: 'a' }, version: '1.0.0', installed: false },
];
const remoteExtensions: ISyncExtensionWithVersion[] = [
{ identifier: { id: 'a', uuid: 'a' }, version: '1.0.0', installed: false, state: { 'a': 1 } },
];
const actual = merge(localExtensions, remoteExtensions, baseExtensions, [], [], [{ id: 'a', uuid: 'a' }]);
assert.deepStrictEqual(actual.local.added, []);
assert.deepStrictEqual(actual.local.removed, []);
assert.deepStrictEqual(actual.local.updated, [{ identifier: { id: 'a', uuid: 'a' }, version: '1.0.0', preRelease: false, installed: true, state: { 'a': 1 } }]);
assert.deepStrictEqual(actual.remote?.all, [{ identifier: { id: 'a', uuid: 'a' }, version: '1.0.0', preRelease: false, installed: true, state: { 'a': 1 } }]);
});
test('merge: base has installed extension, last time synced as builtin extension, local has installed extension, remote has builtin extension with updated state', () => {
const localExtensions: ISyncExtensionWithVersion[] = [
{ identifier: { id: 'a', uuid: 'a' }, version: '1.0.0', installed: true },
];
const baseExtensions: ISyncExtensionWithVersion[] = [
{ identifier: { id: 'a', uuid: 'a' }, version: '1.0.0', installed: true },
];
const remoteExtensions: ISyncExtensionWithVersion[] = [
{ identifier: { id: 'a', uuid: 'a' }, version: '1.0.0', installed: false, state: { 'a': 1 } },
];
const actual = merge(localExtensions, remoteExtensions, baseExtensions, [], [], [{ id: 'a', uuid: 'a' }]);
assert.deepStrictEqual(actual.local.added, []);
assert.deepStrictEqual(actual.local.removed, []);
assert.deepStrictEqual(actual.local.updated, [{ identifier: { id: 'a', uuid: 'a' }, version: '1.0.0', preRelease: false, installed: true, state: { 'a': 1 } }]);
assert.deepStrictEqual(actual.remote?.all, [{ identifier: { id: 'a', uuid: 'a' }, version: '1.0.0', preRelease: false, installed: true, state: { 'a': 1 } }]);
});
test('merge: base has builtin extension, local does not have extension, remote has builtin extension', () => {
const localExtensions: ISyncExtensionWithVersion[] = [];
const baseExtensions: ISyncExtensionWithVersion[] = [
{ identifier: { id: 'a', uuid: 'a' }, version: '1.1.0', installed: false, preRelease: false },
];
const remoteExtensions: ISyncExtensionWithVersion[] = [
{ identifier: { id: 'a', uuid: 'a' }, version: '1.1.0', installed: false, preRelease: false },
];
const actual = merge(localExtensions, remoteExtensions, baseExtensions, [], [], []);
assert.deepStrictEqual(actual.local.added, []);
assert.deepStrictEqual(actual.local.removed, []);
assert.deepStrictEqual(actual.local.updated, []);
assert.deepStrictEqual(actual.remote, null);
});
test('merge: base has installed extension, last synced as builtin, local does not have extension, remote has installed extension', () => {
const localExtensions: ISyncExtensionWithVersion[] = [];
const baseExtensions: ISyncExtensionWithVersion[] = [
{ identifier: { id: 'a', uuid: 'a' }, version: '1.1.0', installed: true, preRelease: false },
];
const remoteExtensions: ISyncExtensionWithVersion[] = [
{ identifier: { id: 'a', uuid: 'a' }, version: '1.1.0', installed: true, preRelease: false },
];
const actual = merge(localExtensions, remoteExtensions, baseExtensions, [], [], [{ id: 'a', uuid: 'a' }]);
assert.deepStrictEqual(actual.local.added, []);
assert.deepStrictEqual(actual.local.removed, []);
assert.deepStrictEqual(actual.local.updated, []);
assert.deepStrictEqual(actual.remote, null);
});
test('merge: base has builtin extension, last synced as builtin, local does not have extension, remote has installed extension', () => {
const localExtensions: ISyncExtensionWithVersion[] = [];
const baseExtensions: ISyncExtensionWithVersion[] = [
{ identifier: { id: 'a', uuid: 'a' }, version: '1.1.0', installed: false, preRelease: false },
];
const remoteExtensions: ISyncExtensionWithVersion[] = [
{ identifier: { id: 'a', uuid: 'a' }, version: '1.1.0', installed: true, preRelease: false },
];
const actual = merge(localExtensions, remoteExtensions, baseExtensions, [], [], [{ id: 'a', uuid: 'a' }]);
assert.deepStrictEqual(actual.local.added, [{ identifier: { id: 'a', uuid: 'a' }, version: '1.1.0', installed: true, preRelease: false }]);
assert.deepStrictEqual(actual.local.removed, []);
assert.deepStrictEqual(actual.local.updated, []);
assert.deepStrictEqual(actual.remote, null);
});
});