#15756 support pre-release while installing through cli and commands

This commit is contained in:
Sandeep Somavarapu 2021-11-25 19:55:21 +01:00
parent dd19b1d50b
commit ab394ee788
No known key found for this signature in database
GPG key ID: 1FED25EC4646638B
13 changed files with 36 additions and 20 deletions

View file

@ -22,7 +22,7 @@ import { NativeParsedArgs } from 'vs/platform/environment/common/argv';
import { INativeEnvironmentService } from 'vs/platform/environment/common/environment';
import { NativeEnvironmentService } from 'vs/platform/environment/node/environmentService';
import { ExtensionGalleryServiceWithNoStorageService } from 'vs/platform/extensionManagement/common/extensionGalleryService';
import { IExtensionGalleryService, IExtensionManagementCLIService, IExtensionManagementService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { IExtensionGalleryService, IExtensionManagementCLIService, IExtensionManagementService, InstallOptions } from 'vs/platform/extensionManagement/common/extensionManagement';
import { ExtensionManagementCLIService } from 'vs/platform/extensionManagement/common/extensionManagementCLIService';
import { ExtensionManagementService } from 'vs/platform/extensionManagement/node/extensionManagementService';
import { IFileService } from 'vs/platform/files/common/files';
@ -217,7 +217,8 @@ class CliMain extends Disposable {
// Install Extension
else if (this.argv['install-extension'] || this.argv['install-builtin-extension']) {
return extensionManagementCLIService.installExtensions(this.asExtensionIdOrVSIX(this.argv['install-extension'] || []), this.argv['install-builtin-extension'] || [], !!this.argv['do-not-sync'], !!this.argv['force']);
const installOptions: InstallOptions = { isMachineScoped: !!this.argv['do-not-sync'], installPreReleaseVersion: !!this.argv['pre-release'] };
return extensionManagementCLIService.installExtensions(this.asExtensionIdOrVSIX(this.argv['install-extension'] || []), this.argv['install-builtin-extension'] || [], installOptions, !!this.argv['force']);
}
// Uninstall Extension

View file

@ -58,6 +58,7 @@ export interface NativeParsedArgs {
'show-versions'?: boolean;
'category'?: string;
'install-extension'?: string[]; // undefined or array of 1 or more
'pre-release'?: boolean;
'install-builtin-extension'?: string[]; // undefined or array of 1 or more
'uninstall-extension'?: string[]; // undefined or array of 1 or more
'locate-extension'?: string[]; // undefined or array of 1 or more

View file

@ -56,6 +56,7 @@ export const OPTIONS: OptionDescriptions<Required<NativeParsedArgs>> = {
'show-versions': { type: 'boolean', cat: 'e', description: localize('showVersions', "Show versions of installed extensions, when using --list-extensions.") },
'category': { type: 'string', cat: 'e', description: localize('category', "Filters installed extensions by provided category, when using --list-extensions."), args: 'category' },
'install-extension': { type: 'string[]', cat: 'e', args: 'extension-id[@version] | path-to-vsix', description: localize('installExtension', "Installs or updates the extension. The identifier of an extension is always `${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: 'extension-id', description: localize('uninstallExtension', "Uninstalls an extension.") },
'enable-proposed-api': { type: 'string[]', cat: 'e', args: 'extension-id', description: localize('experimentalApis', "Enables proposed API features for extensions. Can receive one or more extension IDs to enable individually.") },

View file

@ -482,7 +482,7 @@ export interface IExtensionManagementCLIService {
readonly _serviceBrand: undefined;
listExtensions(showVersions: boolean, category?: string, output?: CLIOutput): Promise<void>;
installExtensions(extensions: (string | URI)[], builtinExtensionIds: string[], isMachineScoped: boolean, force: boolean, output?: CLIOutput): Promise<void>;
installExtensions(extensions: (string | URI)[], builtinExtensionIds: string[], installOptions: InstallOptions, force: boolean, output?: CLIOutput): Promise<void>;
uninstallExtensions(extensions: (string | URI)[], force: boolean, output?: CLIOutput): Promise<void>;
locateExtension(extensions: string[], output?: CLIOutput): Promise<void>;
}

View file

@ -89,7 +89,7 @@ export class ExtensionManagementCLIService implements IExtensionManagementCLISer
}
}
public async installExtensions(extensions: (string | URI)[], builtinExtensionIds: string[], isMachineScoped: boolean, force: boolean, output: CLIOutput = console): Promise<void> {
public async installExtensions(extensions: (string | URI)[], builtinExtensionIds: string[], installOptions: InstallOptions, force: boolean, output: CLIOutput = console): Promise<void> {
const failed: string[] = [];
const installedExtensionsManifests: IExtensionManifest[] = [];
if (extensions.length) {
@ -119,21 +119,21 @@ export class ExtensionManagementCLIService implements IExtensionManagementCLISer
} else {
const [id, version] = getIdAndVersion(extension);
if (checkIfNotInstalled(id, version)) {
installExtensionInfos.push({ id, version, installOptions: { isBuiltin: false, isMachineScoped } });
installExtensionInfos.push({ id, version, installOptions: { ...installOptions, isBuiltin: false } });
}
}
}
for (const extension of builtinExtensionIds) {
const [id, version] = getIdAndVersion(extension);
if (checkIfNotInstalled(id, version)) {
installExtensionInfos.push({ id, version, installOptions: { isBuiltin: true, isMachineScoped: false } });
installExtensionInfos.push({ id, version, installOptions: { ...installOptions, isBuiltin: true } });
}
}
if (vsixs.length) {
await Promise.all(vsixs.map(async vsix => {
try {
const manifest = await this.installVSIX(vsix, { isBuiltin: false, isMachineScoped }, force, output);
const manifest = await this.installVSIX(vsix, { ...installOptions, isBuiltin: false }, force, output);
if (manifest) {
installedExtensionsManifests.push(manifest);
}
@ -200,7 +200,7 @@ export class ExtensionManagementCLIService implements IExtensionManagementCLISer
private async getGalleryExtensions(extensions: InstallExtensionInfo[]): Promise<Map<string, IGalleryExtension>> {
const galleryExtensions = new Map<string, IGalleryExtension>();
const result = await this.extensionGalleryService.getExtensions(extensions, CancellationToken.None);
const result = await this.extensionGalleryService.getExtensions(extensions, extensions.some(e => e.installOptions.installPreReleaseVersion), CancellationToken.None);
for (const extension of result) {
galleryExtensions.set(extension.identifier.id.toLowerCase(), extension);
}

View file

@ -416,7 +416,7 @@ export class ExtensionsSynchroniser extends AbstractSynchroniser implements IUse
) {
if (await this.extensionManagementService.canInstall(extension)) {
this.logService.trace(`${this.syncResourceLogLabel}: Installing extension...`, e.identifier.id, extension.version);
await this.extensionManagementService.installFromGallery(extension, { isMachineScoped: false, donotIncludePackAndDependencies: true, installPreReleaseVersion: e.preRelease } /* pass options to prevent install and sync dialog in web */);
await this.extensionManagementService.installFromGallery(extension, { isMachineScoped: false, donotIncludePackAndDependencies: true, installPreReleaseVersion: e.preRelease } /* set isMachineScoped value to prevent install and sync dialog in web */);
this.logService.info(`${this.syncResourceLogLabel}: Installed extension.`, e.identifier.id, extension.version);
removeFromSkipped.push(extension.identifier);
} else {

View file

@ -27,7 +27,7 @@ import { ProcessItem } from 'vs/base/common/processes';
import { ILog, Translations } from 'vs/workbench/services/extensions/common/extensionPoints';
import { ITelemetryAppender } from 'vs/platform/telemetry/common/telemetryUtils';
import { IBuiltInExtension } from 'vs/base/common/product';
import { IExtensionManagementCLIService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { IExtensionManagementCLIService, InstallOptions } from 'vs/platform/extensionManagement/common/extensionManagement';
import { cwd } from 'vs/base/common/process';
import { IRemoteTelemetryService } from 'vs/server/remoteTelemetryService';
import { Promises } from 'vs/base/node/pfs';
@ -77,7 +77,8 @@ export class RemoteAgentEnvironmentChannel implements IServerChannel {
};
if (environmentService.args['install-builtin-extension']) {
this.whenExtensionsReady = extensionManagementCLIService.installExtensions([], environmentService.args['install-builtin-extension'], !!environmentService.args['do-not-sync'], !!environmentService.args['force'])
const installOptions: InstallOptions = { isMachineScoped: !!environmentService.args['do-not-sync'], installPreReleaseVersion: !!environmentService.args['pre-release'] };
this.whenExtensionsReady = extensionManagementCLIService.installExtensions([], environmentService.args['install-builtin-extension'], installOptions, !!environmentService.args['force'])
.then(null, error => {
logService.error(error);
});
@ -89,7 +90,7 @@ export class RemoteAgentEnvironmentChannel implements IServerChannel {
if (extensionsToInstall) {
const idsOrVSIX = extensionsToInstall.map(input => /\.vsix$/i.test(input) ? URI.file(isAbsolute(input) ? input : join(cwd(), input)) : input);
this.whenExtensionsReady
.then(() => extensionManagementCLIService.installExtensions(idsOrVSIX, [], !!environmentService.args['do-not-sync'], !!environmentService.args['force']))
.then(() => extensionManagementCLIService.installExtensions(idsOrVSIX, [], { isMachineScoped: !!environmentService.args['do-not-sync'], installPreReleaseVersion: !!environmentService.args['pre-release'] }, !!environmentService.args['force']))
.then(null, error => {
logService.error(error);
});

View file

@ -12,7 +12,7 @@ import { IRequestService } from 'vs/platform/request/common/request';
import { RequestService } from 'vs/platform/request/node/requestService';
import { NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IExtensionGalleryService, IExtensionManagementCLIService, IExtensionManagementService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { IExtensionGalleryService, IExtensionManagementCLIService, IExtensionManagementService, InstallOptions } from 'vs/platform/extensionManagement/common/extensionManagement';
import { ExtensionGalleryServiceWithNoStorageService } from 'vs/platform/extensionManagement/common/extensionGalleryService';
import { ExtensionManagementService } from 'vs/platform/extensionManagement/node/extensionManagementService';
import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';
@ -114,7 +114,8 @@ class CliMain extends Disposable {
// Install Extension
else if (this.args['install-extension'] || this.args['install-builtin-extension']) {
return extensionManagementCLIService.installExtensions(this.asExtensionIdOrVSIX(this.args['install-extension'] || []), this.args['install-builtin-extension'] || [], !!this.args['do-not-sync'], !!this.args['force']);
const installOptions: InstallOptions = { isMachineScoped: !!this.args['do-not-sync'], installPreReleaseVersion: !!this.args['pre-release'] };
return extensionManagementCLIService.installExtensions(this.asExtensionIdOrVSIX(this.args['install-extension'] || []), this.args['install-builtin-extension'] || [], installOptions, !!this.args['force']);
}
// Uninstall Extension

View file

@ -120,6 +120,7 @@ export interface ServerParsedArgs {
force?: boolean; // used by install-extension
'do-not-sync'?: boolean; // used by install-extension
'pre-release'?: boolean; // used by install-extension
'user-data-dir'?: string;
'builtin-extensions-dir'?: string;

View file

@ -71,7 +71,7 @@ CommandsRegistry.registerCommand('_remoteCLI.manageExtensions', async function (
const revive = (inputs: (string | UriComponents)[]) => inputs.map(input => isString(input) ? input : URI.revive(input));
if (Array.isArray(args.install) && args.install.length) {
try {
await cliService.installExtensions(revive(args.install), [], true, !!args.force, output);
await cliService.installExtensions(revive(args.install), [], { isMachineScoped: true }, !!args.force, output);
} catch (e) {
lines.push(e.message);
}

View file

@ -8,7 +8,7 @@ import { KeyMod, KeyCode } from 'vs/base/common/keyCodes';
import { Registry } from 'vs/platform/registry/common/platform';
import { MenuRegistry, MenuId, registerAction2, Action2, ISubmenuItem, IMenuItem, IAction2Options } from 'vs/platform/actions/common/actions';
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { ExtensionsLabel, ExtensionsLocalizedLabel, ExtensionsChannelId, IExtensionManagementService, IExtensionGalleryService, PreferencesLocalizedLabel, InstallOperation } from 'vs/platform/extensionManagement/common/extensionManagement';
import { ExtensionsLabel, ExtensionsLocalizedLabel, ExtensionsChannelId, IExtensionManagementService, IExtensionGalleryService, PreferencesLocalizedLabel, InstallOperation, InstallOptions } from 'vs/platform/extensionManagement/common/extensionManagement';
import { EnablementState, IExtensionManagementServerService, IWorkbenchExtensionEnablementService, IWorkbenchExtensionManagementService } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
import { IExtensionIgnoredRecommendationsService, IExtensionRecommendationsService } from 'vs/workbench/services/extensionRecommendations/common/extensionRecommendations';
import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions, IWorkbenchContribution } from 'vs/workbench/common/contributions';
@ -274,6 +274,11 @@ CommandsRegistry.registerCommand({
'description': localize('workbench.extensions.installExtension.option.installOnlyNewlyAddedFromExtensionPackVSIX', "When enabled, VS Code installs only newly added extensions from the extension pack VSIX. This option is considered only while installing a VSIX."),
default: false
},
'installPreReleaseVersion': {
'type': 'boolean',
'description': localize('workbench.extensions.installExtension.option.installPreReleaseVersion', "When enabled, VS Code installs the pre-release version of the extension if available."),
default: false
},
'donotSync': {
'type': 'boolean',
'description': localize('workbench.extensions.installExtension.option.donotSync', "When enabled, VS Code do not sync this extension when Settings Sync is on."),
@ -284,14 +289,18 @@ CommandsRegistry.registerCommand({
}
]
},
handler: async (accessor, arg: string | UriComponents, options?: { installOnlyNewlyAddedFromExtensionPackVSIX?: boolean, donotSync?: boolean }) => {
handler: async (accessor, arg: string | UriComponents, options?: { installOnlyNewlyAddedFromExtensionPackVSIX?: boolean, installPreReleaseVersion?: boolean, donotSync?: boolean }) => {
const extensionManagementService = accessor.get(IExtensionManagementService);
const extensionGalleryService = accessor.get(IExtensionGalleryService);
try {
if (typeof arg === 'string') {
const [extension] = await extensionGalleryService.getExtensions([{ id: arg }], CancellationToken.None);
if (extension) {
await extensionManagementService.installFromGallery(extension, options?.donotSync ? { isMachineScoped: true } : undefined);
const installOptions: InstallOptions = {
isMachineScoped: options?.donotSync ? true : undefined, /* do not allow syncing extensions automatically while installing through the command */
installPreReleaseVersion: options?.installPreReleaseVersion
};
await extensionManagementService.installFromGallery(extension, installOptions);
} else {
throw new Error(localize('notFound', "Extension '{0}' not found.", arg));
}

View file

@ -28,6 +28,7 @@ import { IWorkspaceTrustRequestService } from 'vs/platform/workspace/common/work
import { IExtensionManifestPropertiesService } from 'vs/workbench/services/extensions/common/extensionManifestPropertiesService';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { isUndefined } from 'vs/base/common/types';
export class ExtensionManagementService extends Disposable implements IWorkbenchExtensionManagementService {
@ -292,7 +293,7 @@ export class ExtensionManagementService extends Disposable implements IWorkbench
}
if (servers.length) {
if (!installOptions) {
if (!installOptions || isUndefined(installOptions.isMachineScoped)) {
const isMachineScoped = await this.hasToFlagExtensionsMachineScoped([gallery]);
installOptions = { isMachineScoped, isBuiltin: false };
}

View file

@ -395,7 +395,7 @@ class NewExtensionsInitializer implements IUserDataInitializer {
storeExtensionStorageState(galleryExtension.publisher, galleryExtension.name, extensionToSync.state, this.storageService);
}
this.logService.trace(`Installing extension...`, galleryExtension.identifier.id);
const local = await this.extensionManagementService.installFromGallery(galleryExtension, { isMachineScoped: false, donotIncludePackAndDependencies: true, installPreReleaseVersion: extensionToSync.preRelease } /* pass options to prevent install and sync dialog in web */);
const local = await this.extensionManagementService.installFromGallery(galleryExtension, { isMachineScoped: false, donotIncludePackAndDependencies: true, installPreReleaseVersion: extensionToSync.preRelease } /* set isMachineScoped to prevent install and sync dialog in web */);
if (!preview.disabledExtensions.some(identifier => areSameExtensions(identifier, galleryExtension.identifier))) {
newlyEnabledExtensions.push(local);
}