* fix #232043

* fix compilation error

* fix compilation

* fix compilation

* fix compilation

* fix compilation

* fix compilation
This commit is contained in:
Sandeep Somavarapu 2024-11-12 14:09:05 +01:00 коммит произвёл GitHub
Родитель 9a129c0139
Коммит e9d6c6afc0
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
10 изменённых файлов: 97 добавлений и 4 удалений

Просмотреть файл

@ -7,7 +7,7 @@ use std::collections::HashMap;
use cli::commands::args::{ use cli::commands::args::{
CliCore, Commands, DesktopCodeOptions, ExtensionArgs, ExtensionSubcommand, CliCore, Commands, DesktopCodeOptions, ExtensionArgs, ExtensionSubcommand,
InstallExtensionArgs, ListExtensionArgs, UninstallExtensionArgs, InstallExtensionArgs, ListExtensionArgs, UninstallExtensionArgs, DownloadExtensionArgs,
}; };
/// Tries to parse the argv using the legacy CLI interface, looking for its /// Tries to parse the argv using the legacy CLI interface, looking for its
@ -64,6 +64,7 @@ pub fn try_parse_legacy(
// Now translate them to subcommands. // Now translate them to subcommands.
// --list-extensions -> ext list // --list-extensions -> ext list
// --update-extensions -> update // --update-extensions -> update
// --download-extension -> ext download <id>
// --install-extension=id -> ext install <id> // --install-extension=id -> ext install <id>
// --uninstall-extension=id -> ext uninstall <id> // --uninstall-extension=id -> ext uninstall <id>
// --status -> status // --status -> status
@ -79,6 +80,17 @@ pub fn try_parse_legacy(
})), })),
..Default::default() ..Default::default()
}) })
} else if let Some(exts) = args.get("download-extension") {
Some(CliCore {
subcommand: Some(Commands::Extension(ExtensionArgs {
subcommand: ExtensionSubcommand::Download(DownloadExtensionArgs {
id: exts.to_vec(),
location: get_first_arg_value("location"),
}),
desktop_code_options,
})),
..Default::default()
})
} else if let Some(exts) = args.remove("install-extension") { } else if let Some(exts) = args.remove("install-extension") {
Some(CliCore { Some(CliCore {
subcommand: Some(Commands::Extension(ExtensionArgs { subcommand: Some(Commands::Extension(ExtensionArgs {

Просмотреть файл

@ -272,6 +272,8 @@ pub enum ExtensionSubcommand {
Uninstall(UninstallExtensionArgs), Uninstall(UninstallExtensionArgs),
/// Update the installed extensions. /// Update the installed extensions.
Update, Update,
/// Download an extension.
Download(DownloadExtensionArgs),
} }
impl ExtensionSubcommand { impl ExtensionSubcommand {
@ -305,6 +307,16 @@ impl ExtensionSubcommand {
ExtensionSubcommand::Update => { ExtensionSubcommand::Update => {
target.push("--update-extensions".to_string()); target.push("--update-extensions".to_string());
} }
ExtensionSubcommand::Download(args) => {
for id in args.id.iter() {
target.push(format!("--download-extension={id}"));
}
if let Some(location) = &args.location {
if !location.is_empty() {
target.push(format!("--location={location}"));
}
}
}
} }
} }
} }
@ -347,6 +359,21 @@ pub struct UninstallExtensionArgs {
pub id: Vec<String>, pub id: Vec<String>,
} }
#[derive(Args, Debug, Clone)]
pub struct DownloadExtensionArgs {
/// Id of the extension to download. The identifier of an
/// extension is '${publisher}.${name}'. Should provide '--location' to specify the location to download the VSIX.
/// To download a specific version provide '@${version}'.
/// For example: 'vscode.csharp@1.2.3'.
#[clap(name = "ext-id")]
pub id: Vec<String>,
/// Specify the location to download the VSIX.
#[clap(long, value_name = "location")]
pub location: Option<String>,
}
#[derive(Args, Debug, Clone)] #[derive(Args, Debug, Clone)]
pub struct VersionArgs { pub struct VersionArgs {
#[clap(subcommand)] #[clap(subcommand)]

Просмотреть файл

@ -49,7 +49,7 @@ _@@APPNAME@@()
--list-extensions --show-versions --install-extension --list-extensions --show-versions --install-extension
--uninstall-extension --enable-proposed-api --verbose --log -s --uninstall-extension --enable-proposed-api --verbose --log -s
--status -p --performance --prof-startup --disable-extensions --status -p --performance --prof-startup --disable-extensions
--disable-extension --inspect-extensions --update-extensions --disable-extension --inspect-extensions --update-extensions --download-extension
--inspect-brk-extensions --disable-gpu' -- "$cur") ) --inspect-brk-extensions --disable-gpu' -- "$cur") )
[[ $COMPREPLY == *= ]] && compopt -o nospace [[ $COMPREPLY == *= ]] && compopt -o nospace
return return

Просмотреть файл

@ -20,8 +20,9 @@ arguments=(
'--category[filters installed extension list by category, when using --list-extensions]' '--category[filters installed extension list by category, when using --list-extensions]'
'--show-versions[show versions of installed extensions, when using --list-extensions]' '--show-versions[show versions of installed extensions, when using --list-extensions]'
'--install-extension[install an extension]:id or path:_files -g "*.vsix(-.)"' '--install-extension[install an extension]:id or path:_files -g "*.vsix(-.)"'
'--uninstall-extension[uninstall an extension]:id or path:_files -g "*.vsix(-.)"' '--uninstall-extension[uninstall an extension]:id'
'--update-extensions[update the installed extensions]' '--update-extensions[update the installed extensions]'
'--download-extension[download an extension]:id'
'--enable-proposed-api[enables proposed API features for extensions]::extension id: ' '--enable-proposed-api[enables proposed API features for extensions]::extension id: '
'--verbose[print verbose output (implies --wait)]' '--verbose[print verbose output (implies --wait)]'
'--log[log level to use]:level [info]:(critical error warn info debug trace off)' '--log[log level to use]:level [info]:(critical error warn info debug trace off)'

Просмотреть файл

@ -33,6 +33,7 @@ function shouldSpawnCliProcess(argv: NativeParsedArgs): boolean {
return !!argv['install-source'] return !!argv['install-source']
|| !!argv['list-extensions'] || !!argv['list-extensions']
|| !!argv['install-extension'] || !!argv['install-extension']
|| !!argv['download-extension']
|| !!argv['uninstall-extension'] || !!argv['uninstall-extension']
|| !!argv['update-extensions'] || !!argv['update-extensions']
|| !!argv['locate-extension'] || !!argv['locate-extension']

Просмотреть файл

@ -282,6 +282,14 @@ class CliMain extends Disposable {
return instantiationService.createInstance(ExtensionManagementCLI, new ConsoleLogger(LogLevel.Info, false)).listExtensions(!!this.argv['show-versions'], this.argv['category'], profileLocation); return instantiationService.createInstance(ExtensionManagementCLI, new ConsoleLogger(LogLevel.Info, false)).listExtensions(!!this.argv['show-versions'], this.argv['category'], profileLocation);
} }
// Download Extensions
else if (this.argv['download-extension']) {
if (!this.argv['location']) {
throw new Error('The location argument is required to download an extension.');
}
return instantiationService.createInstance(ExtensionManagementCLI, new ConsoleLogger(LogLevel.Info, false)).downloadExtensions(this.argv['download-extension'], URI.parse(this.argv['location']));
}
// Install Extension // Install Extension
else if (this.argv['install-extension'] || this.argv['install-builtin-extension']) { else if (this.argv['install-extension'] || this.argv['install-builtin-extension']) {
const installOptions: InstallOptions = { isMachineScoped: !!this.argv['do-not-sync'], installPreReleaseVersion: !!this.argv['pre-release'], profileLocation }; const installOptions: InstallOptions = { isMachineScoped: !!this.argv['do-not-sync'], installPreReleaseVersion: !!this.argv['pre-release'], profileLocation };

Просмотреть файл

@ -75,6 +75,8 @@ export interface NativeParsedArgs {
'disable-extensions'?: boolean; 'disable-extensions'?: boolean;
'disable-extension'?: string[]; // undefined or array of 1 or more 'disable-extension'?: string[]; // undefined or array of 1 or more
'list-extensions'?: boolean; 'list-extensions'?: boolean;
'download-extension'?: string[];
'location'?: string;
'show-versions'?: boolean; 'show-versions'?: boolean;
'category'?: string; 'category'?: string;
'install-extension'?: string[]; // undefined or array of 1 or more 'install-extension'?: string[]; // undefined or array of 1 or more

Просмотреть файл

@ -97,6 +97,7 @@ export const OPTIONS: OptionDescriptions<Required<NativeParsedArgs>> = {
'list-extensions': { type: 'boolean', cat: 'e', description: localize('listExtensions', "List the installed extensions.") }, 'list-extensions': { type: 'boolean', cat: 'e', description: localize('listExtensions', "List the installed extensions.") },
'show-versions': { type: 'boolean', cat: 'e', description: localize('showVersions', "Show versions of installed extensions, when using --list-extensions.") }, 'show-versions': { type: 'boolean', cat: 'e', description: localize('showVersions', "Show versions of installed extensions, when using --list-extensions.") },
'category': { type: 'string', allowEmptyValue: true, cat: 'e', description: localize('category', "Filters installed extensions by provided category, when using --list-extensions."), args: 'category' }, 'category': { type: 'string', allowEmptyValue: true, cat: 'e', description: localize('category', "Filters installed extensions by provided category, when using --list-extensions."), args: 'category' },
'download-extension': { type: 'string[]', cat: 'e', args: 'ext-id', description: localize('downloadExtension', "Downloads the extension VSIX that can be installable. The argument is an identifier of an extension that is '${publisher}.${name}'. To download a specific version provide '@${version}'. For example: 'vscode.csharp@1.2.3'. Should provide '--location' to specify the location to download the VSIX.") },
'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'.") }, '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") }, '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.") }, 'uninstall-extension': { type: 'string[]', cat: 'e', args: 'ext-id', description: localize('uninstallExtension', "Uninstalls an extension.") },
@ -163,6 +164,7 @@ export const OPTIONS: OptionDescriptions<Required<NativeParsedArgs>> = {
'file-chmod': { type: 'boolean' }, 'file-chmod': { type: 'boolean' },
'install-builtin-extension': { type: 'string[]' }, 'install-builtin-extension': { type: 'string[]' },
'force': { type: 'boolean' }, 'force': { type: 'boolean' },
'location': { type: 'string' },
'do-not-sync': { type: 'boolean' }, 'do-not-sync': { type: 'boolean' },
'trace': { type: 'boolean' }, 'trace': { type: 'boolean' },
'trace-category-filter': { type: 'string' }, 'trace-category-filter': { type: 'string' },

Просмотреть файл

@ -14,6 +14,7 @@ import { EXTENSION_IDENTIFIER_REGEX, IExtensionGalleryService, IExtensionInfo, I
import { areSameExtensions, getExtensionId, getGalleryExtensionId, getIdAndVersion } from './extensionManagementUtil.js'; import { areSameExtensions, getExtensionId, getGalleryExtensionId, getIdAndVersion } from './extensionManagementUtil.js';
import { ExtensionType, EXTENSION_CATEGORIES, IExtensionManifest } from '../../extensions/common/extensions.js'; import { ExtensionType, EXTENSION_CATEGORIES, IExtensionManifest } from '../../extensions/common/extensions.js';
import { ILogger } from '../../log/common/log.js'; import { ILogger } from '../../log/common/log.js';
import { IUriIdentityService } from '../../uriIdentity/common/uriIdentity.js';
const notFound = (id: string) => localize('notFound', "Extension '{0}' not found.", id); const notFound = (id: string) => localize('notFound', "Extension '{0}' not found.", id);
@ -28,6 +29,7 @@ export class ExtensionManagementCLI {
protected readonly logger: ILogger, protected readonly logger: ILogger,
@IExtensionManagementService private readonly extensionManagementService: IExtensionManagementService, @IExtensionManagementService private readonly extensionManagementService: IExtensionManagementService,
@IExtensionGalleryService private readonly extensionGalleryService: IExtensionGalleryService, @IExtensionGalleryService private readonly extensionGalleryService: IExtensionGalleryService,
@IUriIdentityService private readonly uriIdentityService: IUriIdentityService,
) { } ) { }
protected get location(): string | undefined { protected get location(): string | undefined {
@ -70,6 +72,42 @@ export class ExtensionManagementCLI {
} }
} }
public async downloadExtensions(extensions: string[], target: URI): Promise<void> {
if (!extensions.length) {
return;
}
this.logger.info(localize('downloadingExtensions', "Downloading extensions..."));
const extensionsInfo: IExtensionInfo[] = [];
for (const extension of extensions) {
const [id, version] = getIdAndVersion(extension);
extensionsInfo.push({ id, version: version !== 'prerelease' ? version : undefined, preRelease: version === 'prerelease' });
}
try {
const galleryExtensions = await this.extensionGalleryService.getExtensions(extensionsInfo, CancellationToken.None);
const targetPlatform = await this.extensionManagementService.getTargetPlatform();
await Promise.allSettled(extensionsInfo.map(async extensionInfo => {
const galleryExtension = galleryExtensions.find(e => areSameExtensions(e.identifier, { id: extensionInfo.id }));
if (!galleryExtension) {
this.logger.error(`${notFound(extensionInfo.id)}\n${useId}`);
return;
}
const compatible = await this.extensionGalleryService.getCompatibleExtension(galleryExtension, !!extensionInfo.hasPreRelease, targetPlatform);
try {
await this.extensionGalleryService.download(compatible ?? galleryExtension, this.uriIdentityService.extUri.joinPath(target, `${galleryExtension.identifier.id}-${galleryExtension.version}.vsix`), InstallOperation.None);
this.logger.info(localize('successDownload', "Extension '{0}' was successfully downloaded.", extensionInfo.id));
} catch (error) {
this.logger.error(localize('error while downloading extension', "Error while downloading extension '{0}': {1}", extensionInfo.id, getErrorMessage(error)));
}
}));
} catch (error) {
this.logger.error(localize('error while downloading extensions', "Error while downloading extensions: {0}", getErrorMessage(error)));
throw error;
}
}
public async installExtensions(extensions: (string | URI)[], builtinExtensions: (string | URI)[], installOptions: InstallOptions, force: boolean): Promise<void> { public async installExtensions(extensions: (string | URI)[], builtinExtensions: (string | URI)[], installOptions: InstallOptions, force: boolean): Promise<void> {
const failed: string[] = []; const failed: string[] = [];

Просмотреть файл

@ -18,6 +18,7 @@ import { ServiceCollection } from '../../../platform/instantiation/common/servic
import { ILabelService } from '../../../platform/label/common/label.js'; import { ILabelService } from '../../../platform/label/common/label.js';
import { AbstractMessageLogger, ILogger, LogLevel } from '../../../platform/log/common/log.js'; import { AbstractMessageLogger, ILogger, LogLevel } from '../../../platform/log/common/log.js';
import { IOpenerService } from '../../../platform/opener/common/opener.js'; import { IOpenerService } from '../../../platform/opener/common/opener.js';
import { IUriIdentityService } from '../../../platform/uriIdentity/common/uriIdentity.js';
import { IOpenWindowOptions, IWindowOpenable } from '../../../platform/window/common/window.js'; import { IOpenWindowOptions, IWindowOpenable } from '../../../platform/window/common/window.js';
import { IWorkbenchEnvironmentService } from '../../services/environment/common/environmentService.js'; import { IWorkbenchEnvironmentService } from '../../services/environment/common/environmentService.js';
import { IExtensionManagementServerService } from '../../services/extensionManagement/common/extensionManagement.js'; import { IExtensionManagementServerService } from '../../services/extensionManagement/common/extensionManagement.js';
@ -103,11 +104,12 @@ class RemoteExtensionManagementCLI extends ExtensionManagementCLI {
logger: ILogger, logger: ILogger,
@IExtensionManagementService extensionManagementService: IExtensionManagementService, @IExtensionManagementService extensionManagementService: IExtensionManagementService,
@IExtensionGalleryService extensionGalleryService: IExtensionGalleryService, @IExtensionGalleryService extensionGalleryService: IExtensionGalleryService,
@IUriIdentityService uriIdentityService: IUriIdentityService,
@ILabelService labelService: ILabelService, @ILabelService labelService: ILabelService,
@IWorkbenchEnvironmentService envService: IWorkbenchEnvironmentService, @IWorkbenchEnvironmentService envService: IWorkbenchEnvironmentService,
@IExtensionManifestPropertiesService private readonly _extensionManifestPropertiesService: IExtensionManifestPropertiesService, @IExtensionManifestPropertiesService private readonly _extensionManifestPropertiesService: IExtensionManifestPropertiesService,
) { ) {
super(logger, extensionManagementService, extensionGalleryService); super(logger, extensionManagementService, extensionGalleryService, uriIdentityService);
const remoteAuthority = envService.remoteAuthority; const remoteAuthority = envService.remoteAuthority;
this._location = remoteAuthority ? labelService.getHostLabel(Schemas.vscodeRemote, remoteAuthority) : undefined; this._location = remoteAuthority ? labelService.getHostLabel(Schemas.vscodeRemote, remoteAuthority) : undefined;