Path: blob/main/src/vs/platform/extensionManagement/common/unsupportedExtensionsMigration.ts
5251 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { CancellationToken } from '../../../base/common/cancellation.js';6import { EXTENSION_INSTALL_SKIP_PUBLISHER_TRUST_CONTEXT, IExtensionGalleryService, IExtensionManagementService, IGlobalExtensionEnablementService, InstallOperation } from './extensionManagement.js';7import { areSameExtensions, getExtensionId } from './extensionManagementUtil.js';8import { IExtensionStorageService } from './extensionStorage.js';9import { ExtensionType } from '../../extensions/common/extensions.js';10import { ILogService } from '../../log/common/log.js';11import * as semver from '../../../base/common/semver/semver.js';12import { IUserDataProfile } from '../../userDataProfile/common/userDataProfile.js';1314/**15* Migrates the installed unsupported nightly extension to a supported pre-release extension. It includes following:16* - Uninstall the Unsupported extension17* - Install (with optional storage migration) the Pre-release extension only if18* - the extension is not installed19* - or it is a release version and the unsupported extension is enabled.20*/21export async function migrateUnsupportedExtensions(profile: IUserDataProfile | undefined, extensionManagementService: IExtensionManagementService, galleryService: IExtensionGalleryService, extensionStorageService: IExtensionStorageService, extensionEnablementService: IGlobalExtensionEnablementService, logService: ILogService): Promise<void> {22try {23const extensionsControlManifest = await extensionManagementService.getExtensionsControlManifest();24if (!extensionsControlManifest.deprecated) {25return;26}27const installed = await extensionManagementService.getInstalled(ExtensionType.User, profile?.extensionsResource);28for (const [unsupportedExtensionId, deprecated] of Object.entries(extensionsControlManifest.deprecated)) {29if (!deprecated?.extension) {30continue;31}32const { id: preReleaseExtensionId, autoMigrate, preRelease } = deprecated.extension;33if (!autoMigrate) {34continue;35}36const unsupportedExtension = installed.find(i => areSameExtensions(i.identifier, { id: unsupportedExtensionId }));37// Unsupported Extension is not installed38if (!unsupportedExtension) {39continue;40}4142const gallery = (await galleryService.getExtensions([{ id: preReleaseExtensionId, preRelease }], { targetPlatform: await extensionManagementService.getTargetPlatform(), compatible: true }, CancellationToken.None))[0];43if (!gallery) {44logService.info(`Skipping migrating '${unsupportedExtension.identifier.id}' extension because, the comaptible target '${preReleaseExtensionId}' extension is not found`);45continue;46}4748try {49logService.info(`Migrating '${unsupportedExtension.identifier.id}' extension to '${preReleaseExtensionId}' extension...`);5051const isUnsupportedExtensionEnabled = !extensionEnablementService.getDisabledExtensions().some(e => areSameExtensions(e, unsupportedExtension.identifier));52await extensionManagementService.uninstall(unsupportedExtension, { profileLocation: profile?.extensionsResource });53logService.info(`Uninstalled the unsupported extension '${unsupportedExtension.identifier.id}'`);5455let preReleaseExtension = installed.find(i => areSameExtensions(i.identifier, { id: preReleaseExtensionId }));56if (!preReleaseExtension || (preReleaseExtension.isPreReleaseVersion !== !!preRelease && isUnsupportedExtensionEnabled)) {57preReleaseExtension = await extensionManagementService.installFromGallery(gallery, { installPreReleaseVersion: preRelease, isMachineScoped: unsupportedExtension.isMachineScoped, operation: InstallOperation.Migrate, profileLocation: profile?.extensionsResource, context: { [EXTENSION_INSTALL_SKIP_PUBLISHER_TRUST_CONTEXT]: true } });58logService.info(`Installed the pre-release extension '${preReleaseExtension.identifier.id}'`);59if (!autoMigrate.donotDisable && !isUnsupportedExtensionEnabled) {60await extensionEnablementService.disableExtension(preReleaseExtension.identifier);61logService.info(`Disabled the pre-release extension '${preReleaseExtension.identifier.id}' because the unsupported extension '${unsupportedExtension.identifier.id}' is disabled`);62}63if (autoMigrate.storage) {64extensionStorageService.addToMigrationList(getExtensionId(unsupportedExtension.manifest.publisher, unsupportedExtension.manifest.name), getExtensionId(preReleaseExtension.manifest.publisher, preReleaseExtension.manifest.name));65logService.info(`Added pre-release extension to the storage migration list`);66}67}68logService.info(`Migrated '${unsupportedExtension.identifier.id}' extension to '${preReleaseExtensionId}' extension.`);69} catch (error) {70logService.error(error);71}72}7374if (extensionsControlManifest.autoUpdate) {75for (const [extensionId, version] of Object.entries(extensionsControlManifest.autoUpdate)) {76try {77const extensionToAutoUpdate = installed.find(i => areSameExtensions(i.identifier, { id: extensionId }) && semver.lte(i.manifest.version, version));78if (!extensionToAutoUpdate) {79continue;80}8182const gallery = (await galleryService.getExtensions([{ id: extensionId, preRelease: extensionToAutoUpdate.preRelease }], { targetPlatform: await extensionManagementService.getTargetPlatform(), compatible: true }, CancellationToken.None))[0];83if (!gallery) {84logService.info(`Skipping updating '${extensionToAutoUpdate.identifier.id}' extension because, the compatible target '${extensionId}' extension is not found`);85continue;86}8788await extensionManagementService.installFromGallery(gallery, { installPreReleaseVersion: extensionToAutoUpdate.preRelease, isMachineScoped: extensionToAutoUpdate.isMachineScoped, operation: InstallOperation.Update, profileLocation: profile?.extensionsResource, context: { [EXTENSION_INSTALL_SKIP_PUBLISHER_TRUST_CONTEXT]: true } });89logService.info(`Autoupdated '${extensionToAutoUpdate.identifier.id}' extension to '${gallery.version}' extension.`);90} catch (error) {91logService.error(error);92}93}94}9596} catch (error) {97logService.error(error);98}99}100101102