sussudio
Version:
An unofficial VS Code Internal API
554 lines (553 loc) • 35 kB
JavaScript
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
return function (target, key) { decorator(target, key, paramIndex); }
};
import { Promises } from "../../../base/common/async.mjs";
import { CancellationToken } from "../../../base/common/cancellation.mjs";
import { getErrorMessage } from "../../../base/common/errors.mjs";
import { Event } from "../../../base/common/event.mjs";
import { toFormattedString } from "../../../base/common/jsonFormatter.mjs";
import { DisposableStore } from "../../../base/common/lifecycle.mjs";
import { compare } from "../../../base/common/strings.mjs";
import { IConfigurationService } from "../../configuration/common/configuration.mjs";
import { IEnvironmentService } from "../../environment/common/environment.mjs";
import { GlobalExtensionEnablementService } from "../../extensionManagement/common/extensionEnablementService.mjs";
import { IExtensionGalleryService, IExtensionManagementService, ExtensionManagementError, ExtensionManagementErrorCode, DISABLED_EXTENSIONS_STORAGE_PATH } from "../../extensionManagement/common/extensionManagement.mjs";
import { areSameExtensions } from "../../extensionManagement/common/extensionManagementUtil.mjs";
import { ExtensionStorageService, IExtensionStorageService } from "../../extensionManagement/common/extensionStorage.mjs";
import { IFileService } from "../../files/common/files.mjs";
import { IInstantiationService } from "../../instantiation/common/instantiation.mjs";
import { ServiceCollection } from "../../instantiation/common/serviceCollection.mjs";
import { ILogService } from "../../log/common/log.mjs";
import { IStorageService } from "../../storage/common/storage.mjs";
import { ITelemetryService } from "../../telemetry/common/telemetry.mjs";
import { IUriIdentityService } from "../../uriIdentity/common/uriIdentity.mjs";
import { IUserDataProfilesService } from "../../userDataProfile/common/userDataProfile.mjs";
import { AbstractInitializer, AbstractSynchroniser, getSyncResourceLogLabel } from "./abstractSynchronizer.mjs";
import { merge } from "./extensionsMerge.mjs";
import { IIgnoredExtensionsManagementService } from "./ignoredExtensions.mjs";
import { IUserDataSyncBackupStoreService, IUserDataSyncLogService, IUserDataSyncEnablementService, IUserDataSyncStoreService, USER_DATA_SYNC_SCHEME, EXTENSIONS_SYNC_CONTEXT_KEY } from "./userDataSync.mjs";
import { IUserDataProfileStorageService } from "../../userDataProfile/common/userDataProfileStorageService.mjs";
async function parseAndMigrateExtensions(syncData, extensionManagementService) {
const extensions = JSON.parse(syncData.content);
if (syncData.version === 1
|| syncData.version === 2) {
const builtinExtensions = (await extensionManagementService.getInstalled(0 /* ExtensionType.System */)).filter(e => e.isBuiltin);
for (const extension of extensions) {
// #region Migration from v1 (enabled -> disabled)
if (syncData.version === 1) {
if (extension.enabled === false) {
extension.disabled = true;
}
delete extension.enabled;
}
// #endregion
// #region Migration from v2 (set installed property on extension)
if (syncData.version === 2) {
if (builtinExtensions.every(installed => !areSameExtensions(installed.identifier, extension.identifier))) {
extension.installed = true;
}
}
// #endregion
}
}
return extensions;
}
export function parseExtensions(syncData) {
return JSON.parse(syncData.content);
}
export function stringify(extensions, format) {
extensions.sort((e1, e2) => {
if (!e1.identifier.uuid && e2.identifier.uuid) {
return -1;
}
if (e1.identifier.uuid && !e2.identifier.uuid) {
return 1;
}
return compare(e1.identifier.id, e2.identifier.id);
});
return format ? toFormattedString(extensions, {}) : JSON.stringify(extensions);
}
let ExtensionsSynchroniser = class ExtensionsSynchroniser extends AbstractSynchroniser {
extensionManagementService;
ignoredExtensionsManagementService;
instantiationService;
/*
Version 3 - Introduce installed property to skip installing built in extensions
protected readonly version: number = 3;
*/
/* Version 4: Change settings from `sync.${setting}` to `settingsSync.{setting}` */
/* Version 5: Introduce extension state */
version = 5;
previewResource = this.extUri.joinPath(this.syncPreviewFolder, 'extensions.json');
baseResource = this.previewResource.with({ scheme: USER_DATA_SYNC_SCHEME, authority: 'base' });
localResource = this.previewResource.with({ scheme: USER_DATA_SYNC_SCHEME, authority: 'local' });
remoteResource = this.previewResource.with({ scheme: USER_DATA_SYNC_SCHEME, authority: 'remote' });
acceptedResource = this.previewResource.with({ scheme: USER_DATA_SYNC_SCHEME, authority: 'accepted' });
localExtensionsProvider;
constructor(
// profileLocation changes for default profile
profile, collection, environmentService, fileService, storageService, userDataSyncStoreService, userDataSyncBackupStoreService, extensionManagementService, ignoredExtensionsManagementService, logService, configurationService, userDataSyncEnablementService, telemetryService, extensionStorageService, uriIdentityService, userDataProfileStorageService, instantiationService) {
super({ syncResource: "extensions" /* SyncResource.Extensions */, profile }, collection, fileService, environmentService, storageService, userDataSyncStoreService, userDataSyncBackupStoreService, userDataSyncEnablementService, telemetryService, logService, configurationService, uriIdentityService);
this.extensionManagementService = extensionManagementService;
this.ignoredExtensionsManagementService = ignoredExtensionsManagementService;
this.instantiationService = instantiationService;
this.localExtensionsProvider = this.instantiationService.createInstance(LocalExtensionsProvider);
this._register(Event.any(Event.filter(this.extensionManagementService.onDidInstallExtensions, (e => e.some(({ local }) => !!local))), Event.filter(this.extensionManagementService.onDidUninstallExtension, (e => !e.error)), Event.filter(userDataProfileStorageService.onDidChange, e => e.valueChanges.some(({ profile, changes }) => this.syncResource.profile.id === profile.id && changes.some(change => change.key === DISABLED_EXTENSIONS_STORAGE_PATH))), extensionStorageService.onDidChangeExtensionStorageToSync)(() => this.triggerLocalChange()));
}
async generateSyncPreview(remoteUserData, lastSyncUserData) {
const remoteExtensions = remoteUserData.syncData ? await parseAndMigrateExtensions(remoteUserData.syncData, this.extensionManagementService) : null;
const skippedExtensions = lastSyncUserData?.skippedExtensions || [];
const builtinExtensions = lastSyncUserData?.builtinExtensions || [];
const lastSyncExtensions = lastSyncUserData?.syncData ? await parseAndMigrateExtensions(lastSyncUserData.syncData, this.extensionManagementService) : null;
const { localExtensions, ignoredExtensions } = await this.localExtensionsProvider.getLocalExtensions(this.syncResource.profile);
if (remoteExtensions) {
this.logService.trace(`${this.syncResourceLogLabel}: Merging remote extensions with local extensions...`);
}
else {
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, builtinExtensions);
const previewResult = {
local, remote,
content: this.getPreviewContent(localExtensions, local.added, local.updated, local.removed),
localChange: local.added.length > 0 || local.removed.length > 0 || local.updated.length > 0 ? 2 /* Change.Modified */ : 0 /* Change.None */,
remoteChange: remote !== null ? 2 /* Change.Modified */ : 0 /* Change.None */,
};
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,
localChange: previewResult.localChange,
remoteChange: previewResult.remoteChange,
acceptedResource: this.acceptedResource,
}];
}
async hasRemoteChanged(lastSyncUserData) {
const lastSyncExtensions = lastSyncUserData.syncData ? await parseAndMigrateExtensions(lastSyncUserData.syncData, this.extensionManagementService) : null;
const { localExtensions, ignoredExtensions } = await this.localExtensionsProvider.getLocalExtensions(this.syncResource.profile);
const { remote } = merge(localExtensions, lastSyncExtensions, lastSyncExtensions, lastSyncUserData.skippedExtensions || [], ignoredExtensions, lastSyncUserData.builtinExtensions || []);
return remote !== null;
}
getPreviewContent(localExtensions, added, updated, removed) {
const preview = [...added, ...updated];
const idsOrUUIDs = new Set();
const addIdentifier = (identifier) => {
idsOrUUIDs.add(identifier.id.toLowerCase());
if (identifier.uuid) {
idsOrUUIDs.add(identifier.uuid);
}
};
preview.forEach(({ identifier }) => addIdentifier(identifier));
removed.forEach(addIdentifier);
for (const localExtension of localExtensions) {
if (idsOrUUIDs.has(localExtension.identifier.id.toLowerCase()) || (localExtension.identifier.uuid && idsOrUUIDs.has(localExtension.identifier.uuid))) {
// skip
continue;
}
preview.push(localExtension);
}
return this.stringify(preview, false);
}
async getMergeResult(resourcePreview, token) {
return { ...resourcePreview.previewResult, hasConflicts: false };
}
async getAcceptResult(resourcePreview, resource, content, token) {
/* Accept local resource */
if (this.extUri.isEqual(resource, this.localResource)) {
return this.acceptLocal(resourcePreview);
}
/* Accept remote resource */
if (this.extUri.isEqual(resource, this.remoteResource)) {
return this.acceptRemote(resourcePreview);
}
/* Accept preview resource */
if (this.extUri.isEqual(resource, this.previewResource)) {
return resourcePreview.previewResult;
}
throw new Error(`Invalid Resource: ${resource.toString()}`);
}
async acceptLocal(resourcePreview) {
const installedExtensions = await this.extensionManagementService.getInstalled(undefined, this.syncResource.profile.extensionsResource);
const ignoredExtensions = this.ignoredExtensionsManagementService.getIgnoredExtensions(installedExtensions);
const mergeResult = merge(resourcePreview.localExtensions, null, null, resourcePreview.skippedExtensions, ignoredExtensions, resourcePreview.builtinExtensions);
const { local, remote } = mergeResult;
return {
content: resourcePreview.localContent,
local,
remote,
localChange: local.added.length > 0 || local.removed.length > 0 || local.updated.length > 0 ? 2 /* Change.Modified */ : 0 /* Change.None */,
remoteChange: remote !== null ? 2 /* Change.Modified */ : 0 /* Change.None */,
};
}
async acceptRemote(resourcePreview) {
const installedExtensions = await this.extensionManagementService.getInstalled(undefined, this.syncResource.profile.extensionsResource);
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, resourcePreview.builtinExtensions);
const { local, remote } = mergeResult;
return {
content: resourcePreview.remoteContent,
local,
remote,
localChange: local.added.length > 0 || local.removed.length > 0 || local.updated.length > 0 ? 2 /* Change.Modified */ : 0 /* Change.None */,
remoteChange: remote !== null ? 2 /* Change.Modified */ : 0 /* Change.None */,
};
}
else {
return {
content: resourcePreview.remoteContent,
local: { added: [], removed: [], updated: [] },
remote: null,
localChange: 0 /* Change.None */,
remoteChange: 0 /* Change.None */,
};
}
}
async applyResult(remoteUserData, lastSyncUserData, resourcePreviews, force) {
let { skippedExtensions, localExtensions } = resourcePreviews[0][0];
const { local, remote, localChange, remoteChange } = resourcePreviews[0][1];
if (localChange === 0 /* Change.None */ && remoteChange === 0 /* Change.None */) {
this.logService.info(`${this.syncResourceLogLabel}: No changes found during synchronizing extensions.`);
}
if (localChange !== 0 /* Change.None */) {
await this.backupLocal(JSON.stringify(localExtensions));
skippedExtensions = await this.localExtensionsProvider.updateLocalExtensions(local.added, local.removed, local.updated, skippedExtensions, this.syncResource.profile);
}
if (remote) {
// update remote
this.logService.trace(`${this.syncResourceLogLabel}: Updating remote extensions...`);
const content = JSON.stringify(remote.all);
remoteUserData = await this.updateRemoteUserData(content, force ? null : remoteUserData.ref);
this.logService.info(`${this.syncResourceLogLabel}: Updated remote extensions.${remote.added.length ? ` Added: ${JSON.stringify(remote.added.map(e => e.identifier.id))}.` : ''}${remote.updated.length ? ` Updated: ${JSON.stringify(remote.updated.map(e => e.identifier.id))}.` : ''}${remote.removed.length ? ` Removed: ${JSON.stringify(remote.removed.map(e => e.identifier.id))}.` : ''}`);
}
if (lastSyncUserData?.ref !== remoteUserData.ref) {
// update last sync
this.logService.trace(`${this.syncResourceLogLabel}: Updating last synchronized extensions...`);
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))}.` : ''}`);
}
}
async resolveContent(uri) {
if (this.extUri.isEqual(this.remoteResource, uri)
|| this.extUri.isEqual(this.baseResource, uri)
|| this.extUri.isEqual(this.localResource, uri)
|| this.extUri.isEqual(this.acceptedResource, uri)) {
const content = await this.resolvePreviewContent(uri);
return content ? this.stringify(JSON.parse(content), true) : content;
}
return null;
}
stringify(extensions, format) {
return stringify(extensions, format);
}
async hasLocalData() {
try {
const { localExtensions } = await this.localExtensionsProvider.getLocalExtensions(this.syncResource.profile);
if (localExtensions.some(e => e.installed || e.disabled)) {
return true;
}
}
catch (error) {
/* ignore error */
}
return false;
}
};
ExtensionsSynchroniser = __decorate([
__param(2, IEnvironmentService),
__param(3, IFileService),
__param(4, IStorageService),
__param(5, IUserDataSyncStoreService),
__param(6, IUserDataSyncBackupStoreService),
__param(7, IExtensionManagementService),
__param(8, IIgnoredExtensionsManagementService),
__param(9, IUserDataSyncLogService),
__param(10, IConfigurationService),
__param(11, IUserDataSyncEnablementService),
__param(12, ITelemetryService),
__param(13, IExtensionStorageService),
__param(14, IUriIdentityService),
__param(15, IUserDataProfileStorageService),
__param(16, IInstantiationService)
], ExtensionsSynchroniser);
export { ExtensionsSynchroniser };
let LocalExtensionsProvider = class LocalExtensionsProvider {
extensionManagementService;
userDataProfileStorageService;
extensionGalleryService;
ignoredExtensionsManagementService;
instantiationService;
logService;
constructor(extensionManagementService, userDataProfileStorageService, extensionGalleryService, ignoredExtensionsManagementService, instantiationService, logService) {
this.extensionManagementService = extensionManagementService;
this.userDataProfileStorageService = userDataProfileStorageService;
this.extensionGalleryService = extensionGalleryService;
this.ignoredExtensionsManagementService = ignoredExtensionsManagementService;
this.instantiationService = instantiationService;
this.logService = logService;
}
async getLocalExtensions(profile) {
const installedExtensions = await this.extensionManagementService.getInstalled(undefined, profile.extensionsResource);
const ignoredExtensions = this.ignoredExtensionsManagementService.getIgnoredExtensions(installedExtensions);
const localExtensions = await this.withProfileScopedServices(profile, async (extensionEnablementService, extensionStorageService) => {
const disabledExtensions = extensionEnablementService.getDisabledExtensions();
return installedExtensions
.map(extension => {
const { identifier, isBuiltin, manifest, preRelease } = extension;
const syncExntesion = { identifier, preRelease, version: manifest.version };
if (disabledExtensions.some(disabledExtension => areSameExtensions(disabledExtension, identifier))) {
syncExntesion.disabled = true;
}
if (!isBuiltin) {
syncExntesion.installed = true;
}
try {
const keys = extensionStorageService.getKeysForSync({ id: identifier.id, version: manifest.version });
if (keys) {
const extensionStorageState = extensionStorageService.getExtensionState(extension, true) || {};
syncExntesion.state = Object.keys(extensionStorageState).reduce((state, key) => {
if (keys.includes(key)) {
state[key] = extensionStorageState[key];
}
return state;
}, {});
}
}
catch (error) {
this.logService.info(`${getSyncResourceLogLabel("extensions" /* SyncResource.Extensions */, profile)}: Error while parsing extension state`, getErrorMessage(error));
}
return syncExntesion;
});
});
return { localExtensions, ignoredExtensions };
}
async updateLocalExtensions(added, removed, updated, skippedExtensions, profile) {
const syncResourceLogLabel = getSyncResourceLogLabel("extensions" /* SyncResource.Extensions */, profile);
const extensionsToInstall = [];
const removeFromSkipped = [];
const addToSkipped = [];
const installedExtensions = await this.extensionManagementService.getInstalled(undefined, profile.extensionsResource);
// 1. Sync extensions state first so that the storage is flushed and updated in all opened windows
if (added.length || updated.length) {
await this.withProfileScopedServices(profile, async (extensionEnablementService, extensionStorageService) => {
await Promises.settled([...added, ...updated].map(async (e) => {
const installedExtension = installedExtensions.find(installed => areSameExtensions(installed.identifier, e.identifier));
// Builtin Extension Sync: Enablement & State
if (installedExtension && installedExtension.isBuiltin) {
if (e.state && installedExtension.manifest.version === e.version) {
this.updateExtensionState(e.state, installedExtension, installedExtension.manifest.version, extensionStorageService);
}
const isDisabled = extensionEnablementService.getDisabledExtensions().some(disabledExtension => areSameExtensions(disabledExtension, e.identifier));
if (isDisabled !== !!e.disabled) {
if (e.disabled) {
this.logService.trace(`${syncResourceLogLabel}: Disabling extension...`, e.identifier.id);
await extensionEnablementService.disableExtension(e.identifier);
this.logService.info(`${syncResourceLogLabel}: Disabled extension`, e.identifier.id);
}
else {
this.logService.trace(`${syncResourceLogLabel}: Enabling extension...`, e.identifier.id);
await extensionEnablementService.enableExtension(e.identifier);
this.logService.info(`${syncResourceLogLabel}: Enabled extension`, e.identifier.id);
}
}
removeFromSkipped.push(e.identifier);
return;
}
// User Extension Sync: Install/Update, Enablement & State
const extension = (await this.extensionGalleryService.getExtensions([{ ...e.identifier, preRelease: e.preRelease }], CancellationToken.None))[0];
/* Update extension state only if
* extension is installed and version is same as synced version or
* extension is not installed and installable
*/
if (e.state &&
(installedExtension ? installedExtension.manifest.version === e.version /* Installed and has same version */
: !!extension /* Installable */)) {
this.updateExtensionState(e.state, installedExtension || extension, installedExtension?.manifest.version, extensionStorageService);
}
if (extension) {
try {
const isDisabled = extensionEnablementService.getDisabledExtensions().some(disabledExtension => areSameExtensions(disabledExtension, e.identifier));
if (isDisabled !== !!e.disabled) {
if (e.disabled) {
this.logService.trace(`${syncResourceLogLabel}: Disabling extension...`, e.identifier.id, extension.version);
await extensionEnablementService.disableExtension(extension.identifier);
this.logService.info(`${syncResourceLogLabel}: Disabled extension`, e.identifier.id, extension.version);
}
else {
this.logService.trace(`${syncResourceLogLabel}: Enabling extension...`, e.identifier.id, extension.version);
await extensionEnablementService.enableExtension(extension.identifier);
this.logService.info(`${syncResourceLogLabel}: Enabled extension`, e.identifier.id, extension.version);
}
}
if (!installedExtension // Install if the extension does not exist
|| installedExtension.preRelease !== e.preRelease // Install if the extension pre-release preference has changed
) {
if (await this.extensionManagementService.canInstall(extension)) {
extensionsToInstall.push([e, extension]);
}
else {
this.logService.info(`${syncResourceLogLabel}: Skipped synchronizing extension because it cannot be installed.`, extension.displayName || extension.identifier.id);
addToSkipped.push(e);
}
}
}
catch (error) {
addToSkipped.push(e);
this.logService.error(error);
this.logService.info(`${syncResourceLogLabel}: Skipped synchronizing extension`, extension.displayName || extension.identifier.id);
}
}
else {
addToSkipped.push(e);
this.logService.info(`${syncResourceLogLabel}: Skipped synchronizing extension because the extension is not found.`, e.identifier.id);
}
}));
});
}
// 2. Next uninstall the removed extensions
if (removed.length) {
const extensionsToRemove = installedExtensions.filter(({ identifier, isBuiltin }) => !isBuiltin && removed.some(r => areSameExtensions(identifier, r)));
await Promises.settled(extensionsToRemove.map(async (extensionToRemove) => {
this.logService.trace(`${syncResourceLogLabel}: Uninstalling local extension...`, extensionToRemove.identifier.id);
await this.extensionManagementService.uninstall(extensionToRemove, { donotIncludePack: true, donotCheckDependents: true, profileLocation: profile.extensionsResource });
this.logService.info(`${syncResourceLogLabel}: Uninstalled local extension.`, extensionToRemove.identifier.id);
removeFromSkipped.push(extensionToRemove.identifier);
}));
}
// 3. Install extensions at the end
for (const [e, extension] of extensionsToInstall) {
try {
this.logService.trace(`${syncResourceLogLabel}: Installing extension...`, extension.identifier.id, extension.version);
await this.extensionManagementService.installFromGallery(extension, { isMachineScoped: false /* set isMachineScoped value to prevent install and sync dialog in web */, donotIncludePackAndDependencies: true, installPreReleaseVersion: e.preRelease, profileLocation: profile.extensionsResource, context: { [EXTENSIONS_SYNC_CONTEXT_KEY]: true } });
this.logService.info(`${syncResourceLogLabel}: Installed extension.`, extension.identifier.id, extension.version);
removeFromSkipped.push(extension.identifier);
}
catch (error) {
addToSkipped.push(e);
if (error instanceof ExtensionManagementError && [ExtensionManagementErrorCode.Incompatible, ExtensionManagementErrorCode.IncompatiblePreRelease, ExtensionManagementErrorCode.IncompatibleTargetPlatform].includes(error.code)) {
this.logService.info(`${syncResourceLogLabel}: Skipped synchronizing extension because the compatible extension is not found.`, extension.displayName || extension.identifier.id);
}
else {
this.logService.error(error);
this.logService.info(`${syncResourceLogLabel}: Skipped synchronizing extension`, extension.displayName || extension.identifier.id);
}
}
}
const newSkippedExtensions = [];
for (const skippedExtension of skippedExtensions) {
if (!removeFromSkipped.some(e => areSameExtensions(e, skippedExtension.identifier))) {
newSkippedExtensions.push(skippedExtension);
}
}
for (const skippedExtension of addToSkipped) {
if (!newSkippedExtensions.some(e => areSameExtensions(e.identifier, skippedExtension.identifier))) {
newSkippedExtensions.push(skippedExtension);
}
}
return newSkippedExtensions;
}
updateExtensionState(state, extension, version, extensionStorageService) {
const extensionState = extensionStorageService.getExtensionState(extension, true) || {};
const keys = version ? extensionStorageService.getKeysForSync({ id: extension.identifier.id, version }) : undefined;
if (keys) {
keys.forEach(key => { extensionState[key] = state[key]; });
}
else {
Object.keys(state).forEach(key => extensionState[key] = state[key]);
}
extensionStorageService.setExtensionState(extension, extensionState, true);
}
async withProfileScopedServices(profile, fn) {
return this.userDataProfileStorageService.withProfileScopedStorageService(profile, async (storageService) => {
const disposables = new DisposableStore();
const instantiationService = this.instantiationService.createChild(new ServiceCollection([IStorageService, storageService]));
const extensionEnablementService = disposables.add(instantiationService.createInstance(GlobalExtensionEnablementService));
const extensionStorageService = disposables.add(instantiationService.createInstance(ExtensionStorageService));
try {
return await fn(extensionEnablementService, extensionStorageService);
}
finally {
disposables.dispose();
}
});
}
};
LocalExtensionsProvider = __decorate([
__param(0, IExtensionManagementService),
__param(1, IUserDataProfileStorageService),
__param(2, IExtensionGalleryService),
__param(3, IIgnoredExtensionsManagementService),
__param(4, IInstantiationService),
__param(5, IUserDataSyncLogService)
], LocalExtensionsProvider);
export { LocalExtensionsProvider };
let AbstractExtensionsInitializer = class AbstractExtensionsInitializer extends AbstractInitializer {
extensionManagementService;
ignoredExtensionsManagementService;
constructor(extensionManagementService, ignoredExtensionsManagementService, fileService, userDataProfilesService, environmentService, logService, storageService, uriIdentityService) {
super("extensions" /* SyncResource.Extensions */, userDataProfilesService, environmentService, logService, fileService, storageService, uriIdentityService);
this.extensionManagementService = extensionManagementService;
this.ignoredExtensionsManagementService = ignoredExtensionsManagementService;
}
async parseExtensions(remoteUserData) {
return remoteUserData.syncData ? await parseAndMigrateExtensions(remoteUserData.syncData, this.extensionManagementService) : null;
}
generatePreview(remoteExtensions, localExtensions) {
const installedExtensions = [];
const newExtensions = [];
const disabledExtensions = [];
for (const extension of remoteExtensions) {
if (this.ignoredExtensionsManagementService.hasToNeverSyncExtension(extension.identifier.id)) {
// Skip extension ignored to sync
continue;
}
const installedExtension = localExtensions.find(i => areSameExtensions(i.identifier, extension.identifier));
if (installedExtension) {
installedExtensions.push(installedExtension);
if (extension.disabled) {
disabledExtensions.push(extension.identifier);
}
}
else if (extension.installed) {
newExtensions.push({ ...extension.identifier, preRelease: !!extension.preRelease });
if (extension.disabled) {
disabledExtensions.push(extension.identifier);
}
}
}
return { installedExtensions, newExtensions, disabledExtensions, remoteExtensions };
}
};
AbstractExtensionsInitializer = __decorate([
__param(0, IExtensionManagementService),
__param(1, IIgnoredExtensionsManagementService),
__param(2, IFileService),
__param(3, IUserDataProfilesService),
__param(4, IEnvironmentService),
__param(5, ILogService),
__param(6, IStorageService),
__param(7, IUriIdentityService)
], AbstractExtensionsInitializer);
export { AbstractExtensionsInitializer };