UNPKG

@sussudio/platform

Version:

Internal APIs for VS Code's service injection the base services.

838 lines (837 loc) 31.9 kB
/*--------------------------------------------------------------------------------------------- * 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 '@sussudio/base/common/async.mjs'; import { CancellationToken } from '@sussudio/base/common/cancellation.mjs'; import { getErrorMessage } from '@sussudio/base/common/errors.mjs'; import { Event } from '@sussudio/base/common/event.mjs'; import { toFormattedString } from '@sussudio/base/common/jsonFormatter.mjs'; import { DisposableStore } from '@sussudio/base/common/lifecycle.mjs'; import { compare } from '@sussudio/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 };