CLI update extension review fixes

pull/199893/head
samhanic 2023-12-06 13:54:02 +01:00
parent 3ff7d4545b
commit c210448601
4 changed files with 19 additions and 35 deletions

View File

@ -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)'

View File

@ -100,7 +100,7 @@ export const OPTIONS: OptionDescriptions<Required<NativeParsedArgs>> = {
'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.") },

View File

@ -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<Map<string, IGalleryExtension>> {
private async getGalleryExtensions(extensions: CLIInstallExtensionInfo[]): Promise<Map<string, IGalleryExtension>> {
const galleryExtensions = new Map<string, IGalleryExtension>();
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<IExtensionManifest | null> {
private async installFromGallery({ id, version, installOptions }: CLIInstallExtensionInfo, galleryExtension: IGalleryExtension, installed: ILocalExtension[]): Promise<IExtensionManifest | null> {
const manifest = await this.extensionGalleryService.getManifest(galleryExtension, CancellationToken.None);
if (manifest && !this.validateExtensionKind(manifest)) {
return null;

View File

@ -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();
}