Skip to content

add --download-extensions-locally #244181

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions cli/src/commands/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,7 @@ pub enum ExtensionSubcommand {
Uninstall(UninstallExtensionArgs),
/// Update the installed extensions.
Update,
DownloadExtensionsLocally,
}

impl ExtensionSubcommand {
Expand Down Expand Up @@ -302,6 +303,9 @@ impl ExtensionSubcommand {
ExtensionSubcommand::Update => {
target.push("--update-extensions".to_string());
}
ExtensionSubcommand::DownloadExtensionsLocally => {
target.push("--download-extensions-locally".to_string());
}
}
}
}
Expand Down
4 changes: 4 additions & 0 deletions cli/src/tunnels/code_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ pub struct CodeServerArgs {
pub install_extensions: Vec<String>,
pub uninstall_extensions: Vec<String>,
pub update_extensions: bool,
pub download_extensions_locally: bool,
pub list_extensions: bool,
pub show_versions: bool,
pub category: Option<String>,
Expand Down Expand Up @@ -138,6 +139,9 @@ impl CodeServerArgs {
if self.update_extensions {
args.push(String::from("--update-extensions"));
}
if self.download_extensions_locally {
args.push(String::from("--download-extensions-locally"));
}
if self.list_extensions {
args.push(String::from("--list-extensions"));
if self.show_versions {
Expand Down
4 changes: 2 additions & 2 deletions src/server-main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ perf.mark('code/server/start');
// Do a quick parse to determine if a server or the cli needs to be started
const parsedArgs = minimist(process.argv.slice(2), {
boolean: ['start-server', 'list-extensions', 'print-ip-address', 'help', 'version', 'accept-server-license-terms', 'update-extensions'],
string: ['install-extension', 'install-builtin-extension', 'uninstall-extension', 'locate-extension', 'socket-path', 'host', 'port', 'compatibility'],
string: ['install-extension', 'install-builtin-extension', 'uninstall-extension', 'locate-extension', 'socket-path', 'host', 'port', 'compatibility', 'download-extensions-locally'],
alias: { help: 'h', version: 'v' }
});
['host', 'port', 'accept-server-license-terms'].forEach(e => {
Expand All @@ -41,7 +41,7 @@ const parsedArgs = minimist(process.argv.slice(2), {
});

const extensionLookupArgs = ['list-extensions', 'locate-extension'];
const extensionInstallArgs = ['install-extension', 'install-builtin-extension', 'uninstall-extension', 'update-extensions'];
const extensionInstallArgs = ['install-extension', 'install-builtin-extension', 'uninstall-extension', 'update-extensions', 'download-extensions-locally'];

const shouldSpawnCli = parsedArgs.help || parsedArgs.version || extensionLookupArgs.some(a => !!parsedArgs[a]) || (extensionInstallArgs.some(a => !!parsedArgs[a]) && !parsedArgs['start-server']);

Expand Down
1 change: 1 addition & 0 deletions src/vs/platform/environment/common/argv.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ export interface NativeParsedArgs {
'pre-release'?: boolean;
'install-builtin-extension'?: string[]; // undefined or array of 1 or more
'uninstall-extension'?: string[]; // undefined or array of 1 or more
'download-extensions-locally'?: boolean;
'update-extensions'?: boolean;
'do-not-include-pack-dependencies'?: boolean;
'locate-extension'?: string[]; // undefined or array of 1 or more
Expand Down
1 change: 1 addition & 0 deletions src/vs/platform/environment/node/argv.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,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.") },
'download-extensions-locally': { type: 'boolean', cat: 'e', description: localize('downloadExtensionsLocally', "When enabled extensions are downloaded locally and then installed on remote") },
'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.") },

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -540,7 +540,7 @@ export class ExtensionManagementError extends Error {
}

export interface InstallExtensionSummary {
failed: {
installLocally: {
id: string;
installOptions: InstallOptions;
}[];
Expand Down
34 changes: 22 additions & 12 deletions src/vs/server/node/remoteExtensionsScanner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ export class RemoteExtensionsScannerService implements IRemoteExtensionsScannerS

readonly _serviceBrand: undefined;

private readonly _whenBuiltinExtensionsReady = Promise.resolve<InstallExtensionSummary>({ failed: [] });
private readonly _whenExtensionsReady = Promise.resolve<InstallExtensionSummary>({ failed: [] });
private readonly _whenBuiltinExtensionsReady = Promise.resolve<InstallExtensionSummary>({ installLocally: [] });
private readonly _whenExtensionsReady = Promise.resolve<InstallExtensionSummary>({ installLocally: [] });

constructor(
private readonly _extensionManagementCLI: ExtensionManagementCLI,
Expand All @@ -51,30 +51,40 @@ export class RemoteExtensionsScannerService implements IRemoteExtensionsScannerS
.then(() => {
performance.mark('code/server/didInstallBuiltinExtensions');
_logService.trace('Finished installing builtin extensions');
return { failed: [] };
return { installLocally: [] };
}, error => {
_logService.error(error);
return { failed: [] };
return { installLocally: [] };
});
}

const extensionsToInstall = environmentService.args['install-extension'];
if (extensionsToInstall) {
_logService.trace('Installing extensions passed via args...');
const installOptions: InstallOptions = {
isMachineScoped: !!environmentService.args['do-not-sync'],
installPreReleaseVersion: !!environmentService.args['pre-release'],
isApplicationScoped: true // extensions installed during server startup are available to all profiles
};

if (!!environmentService.args['download-extensions-locally']) {
_logService.trace('Installing extensions later...');
this._whenExtensionsReady = this._whenBuiltinExtensionsReady
.then(async () => {
return { installLocally: extensionsToInstall.map(id => ({ id, installOptions })) };
});
return;
}

_logService.trace('Installing extensions passed via args...');
this._whenExtensionsReady = this._whenBuiltinExtensionsReady
.then(() => _extensionManagementCLI.installExtensions(this._asExtensionIdOrVSIX(extensionsToInstall), [], installOptions, !!environmentService.args['force']))
.then(async () => {
_logService.trace('Finished installing extensions');
return { failed: [] };
return { installLocally: [] };
}, async error => {
_logService.error(error);

const failed: {
const installLocally: {
id: string;
installOptions: InstallOptions;
}[] = [];
Expand All @@ -83,18 +93,18 @@ export class RemoteExtensionsScannerService implements IRemoteExtensionsScannerS
for (const id of this._asExtensionIdOrVSIX(extensionsToInstall)) {
if (typeof id === 'string') {
if (!alreadyInstalled.some(e => areSameExtensions(e.identifier, { id }))) {
failed.push({ id, installOptions });
installLocally.push({ id, installOptions });
}
}
}

if (!failed.length) {
if (!installLocally.length) {
_logService.trace(`No extensions to report as failed`);
return { failed: [] };
return { installLocally: [] };
}

_logService.info(`Relaying the following extensions to install later: ${failed.map(f => f.id).join(', ')}`);
return { failed };
_logService.info(`Relaying the following extensions to install later: ${installLocally.map(f => f.id).join(', ')}`);
return { installLocally };
});
}
}
Expand Down
7 changes: 6 additions & 1 deletion src/vs/server/node/server.cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ const isSupportedForPipe = (optionId: keyof RemoteParsedArgs) => {
case 'uninstall-extension':
case 'update-extensions':
case 'list-extensions':
case 'download-extensions-locally':
case 'force':
case 'do-not-include-pack-dependencies':
case 'show-versions':
Expand Down Expand Up @@ -228,7 +229,7 @@ export async function main(desc: ProductDescription, args: string[]): Promise<vo
}

if (cliCommand) {
if (parsedArgs['install-extension'] !== undefined || parsedArgs['uninstall-extension'] !== undefined || parsedArgs['list-extensions'] || parsedArgs['update-extensions']) {
if (parsedArgs['install-extension'] !== undefined || parsedArgs['uninstall-extension'] !== undefined || parsedArgs['list-extensions'] || parsedArgs['update-extensions'] || parsedArgs['download-extensions-locally']) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

test

const cmdLine: string[] = [];
parsedArgs['install-extension']?.forEach(id => cmdLine.push('--install-extension', id));
parsedArgs['uninstall-extension']?.forEach(id => cmdLine.push('--uninstall-extension', id));
Expand All @@ -242,6 +243,10 @@ export async function main(desc: ProductDescription, args: string[]): Promise<vo
cmdLine.push('--update-extensions');
}

if (parsedArgs['download-extensions-locally']) {
cmdLine.push('--download-extensions-locally');
}

const childProcess = cp.fork(FileAccess.asFileUri('server-main').fsPath, cmdLine, { stdio: 'inherit' });
childProcess.on('error', err => console.log(err));
return;
Expand Down
3 changes: 2 additions & 1 deletion src/vs/server/node/serverEnvironmentService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export const serverOptions: OptionDescriptions<Required<ServerParsedArgs>> = {
'uninstall-extension': OPTIONS['uninstall-extension'],
'list-extensions': OPTIONS['list-extensions'],
'locate-extension': OPTIONS['locate-extension'],

'download-extensions-locally': OPTIONS['download-extensions-locally'],
'show-versions': OPTIONS['show-versions'],
'category': OPTIONS['category'],
'force': OPTIONS['force'],
Expand Down Expand Up @@ -189,6 +189,7 @@ export interface ServerParsedArgs {
'update-extensions'?: boolean;
'uninstall-extension'?: string[];
'list-extensions'?: boolean;
'download-extensions-locally'?: boolean;
'locate-extension'?: string[];
'show-versions'?: boolean;
'category'?: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@ export class InstallRemoteExtensionsContribution implements IWorkbenchContributi
return;
}

const { failed } = await this.remoteExtensionsScannerService.whenExtensionsReady();
if (failed.length === 0) {
const { installLocally } = await this.remoteExtensionsScannerService.whenExtensionsReady();
if (installLocally.length === 0) {
this.logService.trace('No extensions relayed from server');
return;
}
Expand All @@ -95,10 +95,10 @@ export class InstallRemoteExtensionsContribution implements IWorkbenchContributi
return;
}

this.logService.info(`Installing '${failed.length}' extensions relayed from server`);
const galleryExtensions = await this.extensionGalleryService.getExtensions(failed.map(({ id }) => ({ id })), CancellationToken.None);
this.logService.info(`Installing '${installLocally.length}' extensions relayed from server`);
const galleryExtensions = await this.extensionGalleryService.getExtensions(installLocally.map(({ id }) => ({ id })), CancellationToken.None);
const installExtensionInfo: InstallExtensionInfo[] = [];
for (const { id, installOptions } of failed) {
for (const { id, installOptions } of installLocally) {
const extension = galleryExtensions.find(e => areSameExtensions(e.identifier, { id }));
if (extension) {
installExtensionInfo.push({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration)
properties: {
'remote.downloadExtensionsLocally': {
type: 'boolean',
markdownDescription: nls.localize('remote.downloadExtensionsLocally', "When enabled extensions are downloaded locally and installed on remote."),
markdownDescription: nls.localize('remote.downloadExtensionsLocally', "When enabled extensions are downloaded locally and then installed on remote."),
default: false
},
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class RemoteExtensionsScannerService implements IRemoteExtensionsScannerService
whenExtensionsReady(): Promise<InstallExtensionSummary> {
return this.withChannel(
channel => channel.call<InstallExtensionSummary>('whenExtensionsReady'),
{ failed: [] }
{ installLocally: [] }
);
}

Expand Down
2 changes: 1 addition & 1 deletion src/vs/workbench/test/browser/workbenchTestServices.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2171,7 +2171,7 @@ export class TestRemoteAgentService implements IRemoteAgentService {

export class TestRemoteExtensionsScannerService implements IRemoteExtensionsScannerService {
declare readonly _serviceBrand: undefined;
async whenExtensionsReady(): Promise<InstallExtensionSummary> { return { failed: [] }; }
async whenExtensionsReady(): Promise<InstallExtensionSummary> { return { installLocally: [] }; }
scanExtensions(): Promise<IExtensionDescription[]> { throw new Error('Method not implemented.'); }
}

Expand Down
Loading