From c2104486017f839e19cc9b157dff754a6c8943bb Mon Sep 17 00:00:00 2001 From: samhanic <55490861+samhanic@users.noreply.github.com> Date: Wed, 6 Dec 2023 13:54:02 +0100 Subject: [PATCH] CLI update extension review fixes --- resources/completions/zsh/_code | 2 +- src/vs/platform/environment/node/argv.ts | 2 +- .../common/extensionManagementCLI.ts | 48 +++++++------------ .../node/remoteExtensionHostAgentCli.ts | 2 +- 4 files changed, 19 insertions(+), 35 deletions(-) diff --git a/resources/completions/zsh/_code b/resources/completions/zsh/_code index 46a0e019680..eafa37c81c7 100644 --- a/resources/completions/zsh/_code +++ b/resources/completions/zsh/_code @@ -21,7 +21,7 @@ arguments=( '--show-versions[show versions of installed extensions, when using --list-extensions]' '--install-extension[install an extension]:id or path:_files -g "*.vsix(-.)"' '--uninstall-extension[uninstall an extension]:id or path:_files -g "*.vsix(-.)"' - '--update-extensions[update the marketplace-installed extensions]' + '--update-extensions[update the installed extensions]' '--enable-proposed-api[enables proposed API features for extensions]::extension id: ' '--verbose[print verbose output (implies --wait)]' '--log[log level to use]:level [info]:(critical error warn info debug trace off)' diff --git a/src/vs/platform/environment/node/argv.ts b/src/vs/platform/environment/node/argv.ts index 8ffc1c4a775..691dd284960 100644 --- a/src/vs/platform/environment/node/argv.ts +++ b/src/vs/platform/environment/node/argv.ts @@ -100,7 +100,7 @@ export const OPTIONS: OptionDescriptions> = { 'install-extension': { type: 'string[]', cat: 'e', args: 'ext-id | path', description: localize('installExtension', "Installs or updates an extension. The argument is either an extension id or a path to a VSIX. The identifier of an extension is '${publisher}.${name}'. Use '--force' argument to update to latest version. To install a specific version provide '@${version}'. For example: 'vscode.csharp@1.2.3'.") }, 'pre-release': { type: 'boolean', cat: 'e', description: localize('install prerelease', "Installs the pre-release version of the extension, when using --install-extension") }, 'uninstall-extension': { type: 'string[]', cat: 'e', args: 'ext-id', description: localize('uninstallExtension', "Uninstalls an extension.") }, - 'update-extensions': { type: 'boolean', cat: 'e', description: localize('updateExtensions', "Update the marketplace-installed extensions.") }, + 'update-extensions': { type: 'boolean', cat: 'e', description: localize('updateExtensions', "Update the installed extensions.") }, 'enable-proposed-api': { type: 'string[]', allowEmptyValue: true, cat: 'e', args: 'ext-id', description: localize('experimentalApis', "Enables proposed API features for extensions. Can receive one or more extension IDs to enable individually.") }, 'version': { type: 'boolean', cat: 't', alias: 'v', description: localize('version', "Print version.") }, diff --git a/src/vs/platform/extensionManagement/common/extensionManagementCLI.ts b/src/vs/platform/extensionManagement/common/extensionManagementCLI.ts index e41b3a2e3d9..6a29ab91f67 100644 --- a/src/vs/platform/extensionManagement/common/extensionManagementCLI.ts +++ b/src/vs/platform/extensionManagement/common/extensionManagementCLI.ts @@ -10,7 +10,7 @@ import { basename } from 'vs/base/common/resources'; import { gt } from 'vs/base/common/semver/semver'; import { URI } from 'vs/base/common/uri'; import { localize } from 'vs/nls'; -import { EXTENSION_IDENTIFIER_REGEX, IExtensionGalleryService, IExtensionInfo, IExtensionManagementService, IGalleryExtension, ILocalExtension, InstallOptions } from 'vs/platform/extensionManagement/common/extensionManagement'; +import { EXTENSION_IDENTIFIER_REGEX, IExtensionGalleryService, IExtensionInfo, IExtensionManagementService, IGalleryExtension, ILocalExtension, InstallOptions, InstallExtensionInfo, InstallOperation } from 'vs/platform/extensionManagement/common/extensionManagement'; import { areSameExtensions, getGalleryExtensionId, getIdAndVersion } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; import { ExtensionType, EXTENSION_CATEGORIES, IExtensionManifest } from 'vs/platform/extensions/common/extensions'; import { ILogger } from 'vs/platform/log/common/log'; @@ -29,7 +29,7 @@ function getId(manifest: IExtensionManifest, withVersion?: boolean): string { } type InstallVSIXInfo = { vsix: URI; installOptions: InstallOptions }; -type InstallExtensionInfo = { id: string; version?: string; installOptions: InstallOptions }; +type CLIInstallExtensionInfo = { id: string; version?: string; installOptions: InstallOptions }; export class ExtensionManagementCLI { @@ -89,7 +89,7 @@ export class ExtensionManagementCLI { } const installVSIXInfos: InstallVSIXInfo[] = []; - let installExtensionInfos: InstallExtensionInfo[] = []; + let installExtensionInfos: CLIInstallExtensionInfo[] = []; const addInstallExtensionInfo = (id: string, version: string | undefined, isBuiltin: boolean) => { installExtensionInfos.push({ id, version: version !== 'prerelease' ? version : undefined, installOptions: { ...installOptions, isBuiltin, installPreReleaseVersion: version === 'prerelease' || installOptions.installPreReleaseVersion } }); }; @@ -178,45 +178,29 @@ export class ExtensionManagementCLI { const installedExtensionsQuery: IExtensionInfo[] = []; for (const extension of installedExtensions) { if (!!extension.identifier.uuid) { // No need to check new version for an unpublished extension - installedExtensionsQuery.push({ - id: `${extension.manifest.publisher}.${extension.manifest.name}`, - preRelease: extension.isPreReleaseVersion - }); + installedExtensionsQuery.push({ ...extension.identifier, preRelease: extension.preRelease }); } } - this.logger.info(localize('updateExtensionsQuery', "Update extensions: querying version for {0} extensions", installedExtensionsQuery.length)); + this.logger.trace(localize('updateExtensionsQuery', "Fetching latest versions for {0} extensions", installedExtensionsQuery.length)); const availableVersions = await this.extensionGalleryService.getExtensions(installedExtensionsQuery, { compatible: true }, CancellationToken.None); - const newVersionAvailable: [IGalleryExtension, boolean, string][] = []; + const extensionsToUpdate: InstallExtensionInfo[] = []; for (const newVersion of availableVersions) { for (const oldVersion of installedExtensions) { if (areSameExtensions(oldVersion.identifier, newVersion.identifier) && gt(newVersion.version, oldVersion.manifest.version)) { - newVersionAvailable.push([newVersion, oldVersion.isPreReleaseVersion, oldVersion.manifest.version]); + extensionsToUpdate.push({ + extension: newVersion, + options: { operation: InstallOperation.Update, installPreReleaseVersion: oldVersion.isPreReleaseVersion } + }); } } } - if (newVersionAvailable.length) { - this.logger.info(localize('updateExtensionsNewVersionsAvailable', "Update extensions: {0} extensions have new version available", newVersionAvailable.length)); - const failed: string[] = []; - await Promise.all(newVersionAvailable.map(async extensionInfo => { - try { - if (extensionInfo[1]) { - this.logger.info(localize('updateExtensionsPrereleaseVersion', "Updating extension '{0}' from prerelease version {1} to version {2}", extensionInfo[0].identifier.id, extensionInfo[2], extensionInfo[0].version)); - } - else { - this.logger.info(localize('updateExtensionsStandardVersion', "Updating extension '{0}' from version {1} to version {2}", extensionInfo[0].identifier.id, extensionInfo[2], extensionInfo[0].version)); - } - await this.extensionManagementService.installFromGallery(extensionInfo[0]); - } catch (err) { - this.logger.error(err.message || err.stack || err); - failed.push(extensionInfo[0].identifier.id); - } - })); - if (failed.length) { - throw new Error(localize('installation failed', "Failed Installing Extensions: {0}", failed.join(', '))); - } + if (extensionsToUpdate.length) { + this.logger.info(localize('updateExtensionsNewVersionsAvailable', "Updating extensions: {0}", extensionsToUpdate.map(ext => ext.extension.identifier.id).join(', '))); + await this.extensionManagementService.installGalleryExtensions(extensionsToUpdate); + this.logger.info(localize('updateExtensionsDone', "Updated {0} extensions", extensionsToUpdate.length)); } else { this.logger.info(localize('updateExtensionsNoExtensions', "No extension to update")); @@ -248,7 +232,7 @@ export class ExtensionManagementCLI { return null; } - private async getGalleryExtensions(extensions: InstallExtensionInfo[]): Promise> { + private async getGalleryExtensions(extensions: CLIInstallExtensionInfo[]): Promise> { const galleryExtensions = new Map(); const preRelease = extensions.some(e => e.installOptions.installPreReleaseVersion); const targetPlatform = await this.extensionManagementService.getTargetPlatform(); @@ -267,7 +251,7 @@ export class ExtensionManagementCLI { return galleryExtensions; } - private async installFromGallery({ id, version, installOptions }: InstallExtensionInfo, galleryExtension: IGalleryExtension, installed: ILocalExtension[]): Promise { + private async installFromGallery({ id, version, installOptions }: CLIInstallExtensionInfo, galleryExtension: IGalleryExtension, installed: ILocalExtension[]): Promise { const manifest = await this.extensionGalleryService.getManifest(galleryExtension, CancellationToken.None); if (manifest && !this.validateExtensionKind(manifest)) { return null; diff --git a/src/vs/server/node/remoteExtensionHostAgentCli.ts b/src/vs/server/node/remoteExtensionHostAgentCli.ts index 6960a2d4424..b489ca72bcb 100644 --- a/src/vs/server/node/remoteExtensionHostAgentCli.ts +++ b/src/vs/server/node/remoteExtensionHostAgentCli.ts @@ -159,7 +159,7 @@ class CliMain extends Disposable { return extensionManagementCLI.uninstallExtensions(this.asExtensionIdOrVSIX(this.args['uninstall-extension']), !!this.args['force']); } - // Update the marketplace-installed extensions + // Update the installed extensions else if (this.args['update-extensions']) { return extensionManagementCLI.updateExtensions(); }