Skip to content

Commit

Permalink
send through InstallOptions
Browse files Browse the repository at this point in the history
  • Loading branch information
joshspicer committed Jan 29, 2025
1 parent d53102f commit 956cbd4
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 57 deletions.
3 changes: 2 additions & 1 deletion src/vs/platform/remote/common/remoteExtensionsScanner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
*--------------------------------------------------------------------------------------------*/

import { URI } from '../../../base/common/uri.js';
import { InstallOptions } from '../../extensionManagement/common/extensionManagement.js';
import { IExtensionDescription } from '../../extensions/common/extensions.js';
import { createDecorator } from '../../instantiation/common/instantiation.js';

Expand All @@ -17,6 +18,6 @@ export interface IRemoteExtensionsScannerService {
/**
* Returns a promise that resolves to an array of extension identifiers or URIs that failed to install
*/
whenExtensionsReady(): Promise<Array<string | URI>>;
whenExtensionsReady(): Promise<{ extensions: Array<string | URI>; installOptions: InstallOptions }>;
scanExtensions(): Promise<IExtensionDescription[]>;
}
33 changes: 15 additions & 18 deletions src/vs/server/node/remoteExtensionsScanner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ export class RemoteExtensionsScannerService implements IRemoteExtensionsScannerS

readonly _serviceBrand: undefined;

private readonly _whenBuiltinExtensionsReady = Promise.resolve<Array<string | URI>>([]);
private readonly _whenExtensionsReady = Promise.resolve<Array<string | URI>>([]);
private readonly _whenBuiltinExtensionsReady = Promise.resolve<{ extensions: Array<string | URI>; installOptions: InstallOptions }>({ extensions: [], installOptions: {} });
private readonly _whenExtensionsReady = Promise.resolve<{ extensions: Array<string | URI>; installOptions: InstallOptions }>({ extensions: [], installOptions: {} });

constructor(
private readonly _extensionManagementCLI: ExtensionManagementCLI,
Expand All @@ -49,36 +49,33 @@ export class RemoteExtensionsScannerService implements IRemoteExtensionsScannerS
.then(() => {
performance.mark('code/server/didInstallBuiltinExtensions');
_logService.trace('Finished installing builtin extensions');
return [];
return { extensions: [], installOptions: {} };
}, error => {
_logService.error(error);
if (error instanceof ExtensionInstallationError) {
_logService.error(`Failed installing builtin extensions`);
return error.failed;
}
return [];
return { extensions: [], installOptions: {} };
});
}

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
};
this._whenExtensionsReady = this._whenBuiltinExtensionsReady
.then(() => _extensionManagementCLI.installExtensions(this._asExtensionIdOrVSIX(extensionsToInstall), [], {
isMachineScoped: !!environmentService.args['do-not-sync'],
installPreReleaseVersion: !!environmentService.args['pre-release'],
isApplicationScoped: true // extensions installed during server startup are available to all profiles
}, !!environmentService.args['force']))
.then(() => _extensionManagementCLI.installExtensions(this._asExtensionIdOrVSIX(extensionsToInstall), [], installOptions, !!environmentService.args['force']))
.then(() => {
_logService.trace('Finished installing extensions');
return [];
return { extensions: [], installOptions: {} };
}, error => {
_logService.error(error);
if (error instanceof ExtensionInstallationError) {
_logService.error(`Failed installing extensions`);
return error.failed;
return { extensions: error.failed, installOptions: {} };
}
return [];
return { extensions: [], installOptions: {} };
});
}
}
Expand All @@ -87,7 +84,7 @@ export class RemoteExtensionsScannerService implements IRemoteExtensionsScannerS
return inputs.map(input => /\.vsix$/i.test(input) ? URI.file(isAbsolute(input) ? input : join(cwd(), input)) : input);
}

whenExtensionsReady(): Promise<Array<string | URI>> {
whenExtensionsReady(): Promise<{ extensions: Array<string | URI>; installOptions: InstallOptions }> {
return this._whenExtensionsReady;
}

Expand Down Expand Up @@ -320,7 +317,7 @@ export class RemoteExtensionsScannerChannel implements IServerChannel {
async call(context: any, command: string, args?: any): Promise<any> {
const uriTransformer = this.getUriTransformer(context);
switch (command) {
case 'whenExtensionsReady': return this.service.whenExtensionsReady();
case 'whenExtensionsReady': return this.service.whenExtensionsReady(); // TODO: Need to do some serialization stuff here?
case 'scanExtensions': {
const language = args[0];
const profileLocation = args[1] ? URI.revive(uriTransformer.transformIncoming(args[1])) : undefined;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,16 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { CancellationToken } from '../../../../base/common/cancellation.js';
import { Disposable } from '../../../../base/common/lifecycle.js';
import { localize } from '../../../../nls.js';
import { registerAction2 } from '../../../../platform/actions/common/actions.js';
import { IExtensionGalleryService, IExtensionManagementService } from '../../../../platform/extensionManagement/common/extensionManagement.js';
import { IExtensionRecommendationNotificationService } from '../../../../platform/extensionRecommendations/common/extensionRecommendations.js';
import { ExtensionRecommendationNotificationServiceChannel } from '../../../../platform/extensionRecommendations/common/extensionRecommendationsIpc.js';
import { SyncDescriptor } from '../../../../platform/instantiation/common/descriptors.js';
import { InstantiationType, registerSingleton } from '../../../../platform/instantiation/common/extensions.js';
import { IInstantiationService } from '../../../../platform/instantiation/common/instantiation.js';
import { ISharedProcessService } from '../../../../platform/ipc/electron-sandbox/services.js';
import { ILogService } from '../../../../platform/log/common/log.js';
import { Registry } from '../../../../platform/registry/common/platform.js';
import { IRemoteExtensionsScannerService } from '../../../../platform/remote/common/remoteExtensionsScanner.js';
import { EditorPaneDescriptor, IEditorPaneRegistry } from '../../../browser/editor.js';
import { IWorkbenchContribution, IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from '../../../common/contributions.js';
import { EditorExtensions, IEditorFactoryRegistry, IEditorSerializer } from '../../../common/editor.js';
Expand All @@ -27,6 +23,7 @@ import { DebugExtensionHostAction, DebugExtensionsContribution } from './debugEx
import { ExtensionHostProfileService } from './extensionProfileService.js';
import { CleanUpExtensionsFolderAction, OpenExtensionsFolderAction } from './extensionsActions.js';
import { ExtensionsAutoProfiler } from './extensionsAutoProfiler.js';
import { InstallFailedExtensions } from './installFailedExtensions.js';
import { RemoteExtensionsInitializerContribution } from './remoteExtensionsInit.js';
import { IExtensionHostProfileService, OpenExtensionHostProfileACtion, RuntimeExtensionsEditor, SaveExtensionHostProfileAction, StartExtensionHostProfileAction, StopExtensionHostProfileAction } from './runtimeExtensionsEditor.js';

Expand Down Expand Up @@ -71,41 +68,12 @@ class ExtensionsContributions extends Disposable implements IWorkbenchContributi
}
}

class InstallFailedExtensionsThroughWorkbenchContribution extends Disposable implements IWorkbenchContribution {
constructor(
@IRemoteExtensionsScannerService remoteExtensionsScannerService: IRemoteExtensionsScannerService,
@IExtensionGalleryService private readonly _extensionGalleryService: IExtensionGalleryService,
@IExtensionManagementService private readonly _extensionManagementService: IExtensionManagementService,
@ILogService logService: ILogService,
) {
super();

remoteExtensionsScannerService.whenExtensionsReady()
.then(async (failedFromRemote) => {
logService.debug('Failed from remote', failedFromRemote);

// TODO: We probably want to pass through other information from the remote, like pre-release status.
const registryExtensionIds =
failedFromRemote
.filter(ext => typeof ext === 'string')
.map(ext => ({ id: ext }));
const exts = await this._extensionGalleryService.getExtensions(registryExtensionIds, CancellationToken.None);
for (const ext of exts) {
await this._extensionManagementService.installFromGallery(ext);
}
// TODO: Handle VSIX URIs somehow?
}).catch(e => {
logService.error('Failed in InstallFailedExtensionsThroughWorkbenchContribution', e);
});
}
}

const workbenchRegistry = Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench);
workbenchRegistry.registerWorkbenchContribution(ExtensionsContributions, LifecyclePhase.Restored);
workbenchRegistry.registerWorkbenchContribution(ExtensionsAutoProfiler, LifecyclePhase.Eventually);
workbenchRegistry.registerWorkbenchContribution(RemoteExtensionsInitializerContribution, LifecyclePhase.Restored);
workbenchRegistry.registerWorkbenchContribution(DebugExtensionsContribution, LifecyclePhase.Restored);
workbenchRegistry.registerWorkbenchContribution(InstallFailedExtensionsThroughWorkbenchContribution, LifecyclePhase.Restored);
workbenchRegistry.registerWorkbenchContribution(InstallFailedExtensions, LifecyclePhase.Restored);

// Register Commands

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { CancellationToken } from '../../../../base/common/cancellation.js';
import { Disposable } from '../../../../base/common/lifecycle.js';
import { IExtensionGalleryService, IExtensionManagementService } from '../../../../platform/extensionManagement/common/extensionManagement.js';
import { ILogService } from '../../../../platform/log/common/log.js';
import { IRemoteExtensionsScannerService } from '../../../../platform/remote/common/remoteExtensionsScanner.js';
import { IWorkbenchContribution } from '../../../common/contributions.js';

export class InstallFailedExtensions extends Disposable implements IWorkbenchContribution {
constructor(
@IRemoteExtensionsScannerService remoteExtensionsScannerService: IRemoteExtensionsScannerService,
@IExtensionGalleryService private readonly _extensionGalleryService: IExtensionGalleryService,
@IExtensionManagementService private readonly _extensionManagementService: IExtensionManagementService,
@ILogService logService: ILogService
) {
super();

remoteExtensionsScannerService.whenExtensionsReady()
.then(async ({ extensions, installOptions }) => {
logService.debug('Failed from remote', extensions);

const registryExtensionIds = extensions
.filter(ext => typeof ext === 'string')
.map(ext => ({ id: ext }));

const exts = await this._extensionGalleryService.getExtensions(registryExtensionIds, CancellationToken.None);
for (const ext of exts) {
await this._extensionManagementService.installFromGallery(ext, installOptions);
}

}).catch(e => {
logService.error('Failed in InstallFailedExtensions', e);
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { InstantiationType, registerSingleton } from '../../../../platform/insta
import { IActiveLanguagePackService } from '../../localization/common/locale.js';
import { IWorkbenchExtensionManagementService } from '../../extensionManagement/common/extensionManagement.js';
import { Mutable } from '../../../../base/common/types.js';
import { InstallOptions } from '../../../../platform/extensionManagement/common/extensionManagement.js';

class RemoteExtensionsScannerService implements IRemoteExtensionsScannerService {

Expand All @@ -32,10 +33,10 @@ class RemoteExtensionsScannerService implements IRemoteExtensionsScannerService
@ILogService private readonly logService: ILogService,
) { }

whenExtensionsReady(): Promise<Array<string | URI>> {
whenExtensionsReady(): Promise<{ extensions: Array<string | URI>; installOptions: InstallOptions }> {
return this.withChannel(
channel => channel.call<Array<string | URI>>('whenExtensionsReady'),
[],
channel => channel.call<{ extensions: Array<string | URI>; installOptions: InstallOptions }>('whenExtensionsReady'),
{ extensions: [], installOptions: {} },
);
}

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 @@ -2166,7 +2166,7 @@ export class TestRemoteExtensionsScannerService implements IRemoteExtensionsScan
throw new Error('Method not implemented.');
}
declare readonly _serviceBrand: undefined;
async whenExtensionsReady(): Promise<Array<string | URI>> { return []; }
async whenExtensionsReady(): Promise<{ extensions: Array<string | URI>; installOptions: InstallOptions }> { return { extensions: [], installOptions: {} }; }
scanExtensions(): Promise<IExtensionDescription[]> { throw new Error('Method not implemented.'); }
}

Expand Down

0 comments on commit 956cbd4

Please sign in to comment.