mirror of
https://github.com/Microsoft/vscode
synced 2024-08-28 05:19:39 +00:00
Merge pull request #115302 from microsoft/sandy081/remoteCLI
Remote CLI: Only manage remote extensions
This commit is contained in:
commit
c8a90a4826
|
@ -17,7 +17,6 @@ import { Schemas } from 'vs/base/common/network';
|
|||
import { ILocalizationsService } from 'vs/platform/localizations/common/localizations';
|
||||
|
||||
const notFound = (id: string) => localize('notFound', "Extension '{0}' not found.", id);
|
||||
const notInstalled = (id: string) => localize('notInstalled', "Extension '{0}' is not installed.", id);
|
||||
const useId = localize('useId', "Make sure you use the full extension ID, including the publisher, e.g.: {0}", 'ms-dotnettools.csharp');
|
||||
|
||||
|
||||
|
@ -52,6 +51,9 @@ export class ExtensionManagementCLIService implements IExtensionManagementCLISer
|
|||
@ILocalizationsService private readonly localizationsService: ILocalizationsService
|
||||
) { }
|
||||
|
||||
protected get location(): string | undefined {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
public async listExtensions(showVersions: boolean, category?: string, output: CLIOutput = console): Promise<void> {
|
||||
let extensions = await this.extensionManagementService.getInstalled(ExtensionType.User);
|
||||
|
@ -75,6 +77,10 @@ export class ExtensionManagementCLIService implements IExtensionManagementCLISer
|
|||
});
|
||||
return;
|
||||
}
|
||||
if (this.location) {
|
||||
output.log(localize('listFromLocation', "Extensions installed on {0}:", this.location));
|
||||
}
|
||||
|
||||
extensions = extensions.sort((e1, e2) => e1.identifier.id.localeCompare(e2.identifier.id));
|
||||
let lastId: string | undefined = undefined;
|
||||
for (let extension of extensions) {
|
||||
|
@ -89,7 +95,7 @@ export class ExtensionManagementCLIService implements IExtensionManagementCLISer
|
|||
const failed: string[] = [];
|
||||
const installedExtensionsManifests: IExtensionManifest[] = [];
|
||||
if (extensions.length) {
|
||||
output.log(localize('installingExtensions', "Installing extensions..."));
|
||||
output.log(this.location ? localize('installingExtensionsOnLocation', "Installing extensions on {0}...", this.location) : localize('installingExtensions', "Installing extensions..."));
|
||||
}
|
||||
|
||||
const installed = await this.extensionManagementService.getInstalled(ExtensionType.User);
|
||||
|
@ -176,7 +182,11 @@ export class ExtensionManagementCLIService implements IExtensionManagementCLISer
|
|||
private async installVSIX(vsix: URI, force: boolean, output: CLIOutput): Promise<IExtensionManifest | null> {
|
||||
|
||||
const manifest = await this.extensionManagementService.getManifest(vsix);
|
||||
const valid = await this.validate(manifest, force, output);
|
||||
if (!manifest) {
|
||||
throw new Error('Invalid vsix');
|
||||
}
|
||||
|
||||
const valid = await this.validateVSIX(manifest, force, output);
|
||||
if (valid) {
|
||||
try {
|
||||
await this.extensionManagementService.install(vsix);
|
||||
|
@ -217,6 +227,10 @@ export class ExtensionManagementCLIService implements IExtensionManagementCLISer
|
|||
|
||||
private async installFromGallery({ id, version, installOptions }: InstallExtensionInfo, galleryExtension: IGalleryExtension, installed: ILocalExtension[], force: boolean, output: CLIOutput): Promise<IExtensionManifest | null> {
|
||||
const manifest = await this.extensionGalleryService.getManifest(galleryExtension, CancellationToken.None);
|
||||
if (manifest && !this.validateExtensionKind(manifest, output)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const installedExtension = installed.find(e => areSameExtensions(e.identifier, galleryExtension.identifier));
|
||||
if (installedExtension) {
|
||||
if (galleryExtension.version === installedExtension.manifest.version) {
|
||||
|
@ -232,6 +246,7 @@ export class ExtensionManagementCLIService implements IExtensionManagementCLISer
|
|||
} else {
|
||||
output.log(localize('installing', "Installing extension '{0}' v{1}...", id, galleryExtension.version));
|
||||
}
|
||||
|
||||
await this.extensionManagementService.installFromGallery(galleryExtension, installOptions);
|
||||
output.log(localize('successInstall', "Extension '{0}' v{1} was successfully installed.", id, galleryExtension.version));
|
||||
return manifest;
|
||||
|
@ -245,11 +260,11 @@ export class ExtensionManagementCLIService implements IExtensionManagementCLISer
|
|||
}
|
||||
}
|
||||
|
||||
private async validate(manifest: IExtensionManifest, force: boolean, output: CLIOutput): Promise<boolean> {
|
||||
if (!manifest) {
|
||||
throw new Error('Invalid vsix');
|
||||
}
|
||||
protected validateExtensionKind(_manifest: IExtensionManifest, output: CLIOutput): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
private async validateVSIX(manifest: IExtensionManifest, force: boolean, output: CLIOutput): Promise<boolean> {
|
||||
const extensionIdentifier = { id: getGalleryExtensionId(manifest.publisher, manifest.name) };
|
||||
const installedExtensions = await this.extensionManagementService.getInstalled(ExtensionType.User);
|
||||
const newer = installedExtensions.find(local => areSameExtensions(extensionIdentifier, local.identifier) && gt(local.manifest.version, manifest.version));
|
||||
|
@ -259,7 +274,7 @@ export class ExtensionManagementCLIService implements IExtensionManagementCLISer
|
|||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return this.validateExtensionKind(manifest, output);
|
||||
}
|
||||
|
||||
public async uninstallExtensions(extensions: (string | URI)[], force: boolean, output: CLIOutput = console): Promise<void> {
|
||||
|
@ -277,7 +292,7 @@ export class ExtensionManagementCLIService implements IExtensionManagementCLISer
|
|||
const installed = await this.extensionManagementService.getInstalled();
|
||||
const extensionsToUninstall = installed.filter(e => areSameExtensions(e.identifier, { id }));
|
||||
if (!extensionsToUninstall.length) {
|
||||
throw new Error(`${notInstalled(id)}\n${useId}`);
|
||||
throw new Error(`${this.notInstalled(id)}\n${useId}`);
|
||||
}
|
||||
if (extensionsToUninstall.some(e => e.type === ExtensionType.System)) {
|
||||
output.log(localize('builtin', "Extension '{0}' is a Built-in extension and cannot be uninstalled", id));
|
||||
|
@ -293,7 +308,12 @@ export class ExtensionManagementCLIService implements IExtensionManagementCLISer
|
|||
uninstalledExtensions.push(extensionToUninstall);
|
||||
}
|
||||
|
||||
output.log(localize('successUninstall', "Extension '{0}' was successfully uninstalled!", id));
|
||||
if (this.location) {
|
||||
output.log(localize('successUninstallFromLocation', "Extension '{0}' was successfully uninstalled from {1}!", id, this.location));
|
||||
} else {
|
||||
output.log(localize('successUninstall', "Extension '{0}' was successfully uninstalled!", id));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (uninstalledExtensions.some(e => isLanguagePackExtension(e.manifest))) {
|
||||
|
@ -319,4 +339,9 @@ export class ExtensionManagementCLIService implements IExtensionManagementCLISer
|
|||
private updateLocalizationsCache(): Promise<boolean> {
|
||||
return this.localizationsService.update();
|
||||
}
|
||||
|
||||
private notInstalled(id: string) {
|
||||
return this.location ? localize('notInstalleddOnLocation', "Extension '{0}' is not installed on {1}.", id, this.location) : localize('notInstalled', "Extension '{0}' is not installed.", id);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,15 +3,28 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { isString } from 'vs/base/common/types';
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { localize } from 'vs/nls';
|
||||
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
|
||||
import { IExtensionManagementCLIService } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { CLIOutput, IExtensionGalleryService, IExtensionManagementService } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
import { ExtensionManagementCLIService } from 'vs/platform/extensionManagement/common/extensionManagementCLIService';
|
||||
import { getExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
|
||||
import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
|
||||
import { ILabelService } from 'vs/platform/label/common/label';
|
||||
import { ILocalizationsService } from 'vs/platform/localizations/common/localizations';
|
||||
import { IOpenerService } from 'vs/platform/opener/common/opener';
|
||||
import { IProductService } from 'vs/platform/product/common/productService';
|
||||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
import { IExtensionManagementServerService } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
|
||||
import { canExecuteOnWorkspace } from 'vs/workbench/services/extensions/common/extensionsUtil';
|
||||
import { IExtensionManifest } from 'vs/workbench/workbench.web.api';
|
||||
|
||||
|
||||
// this class contains the command that the CLI server is reying on
|
||||
// this class contains the commands that the CLI server is reying on
|
||||
|
||||
CommandsRegistry.registerCommand('_remoteCLI.openExternal', function (accessor: ServicesAccessor, uri: UriComponents, options: { allowTunneling?: boolean }) {
|
||||
// TODO: discuss martin, ben where to put this
|
||||
|
@ -28,7 +41,14 @@ interface ManageExtensionsArgs {
|
|||
|
||||
CommandsRegistry.registerCommand('_remoteCLI.manageExtensions', async function (accessor: ServicesAccessor, args: ManageExtensionsArgs) {
|
||||
|
||||
const cliService = accessor.get(IExtensionManagementCLIService);
|
||||
const instantiationService = accessor.get(IInstantiationService);
|
||||
const extensionManagementServerService = accessor.get(IExtensionManagementServerService);
|
||||
const remoteExtensionManagementService = extensionManagementServerService.remoteExtensionManagementServer?.extensionManagementService;
|
||||
if (!remoteExtensionManagementService) {
|
||||
return;
|
||||
}
|
||||
|
||||
const cliService = instantiationService.createChild(new ServiceCollection([IExtensionManagementService, remoteExtensionManagementService])).createInstance(RemoteExtensionCLIManagementService);
|
||||
|
||||
const lines: string[] = [];
|
||||
const output = { log: lines.push.bind(lines), error: lines.push.bind(lines) };
|
||||
|
@ -55,3 +75,34 @@ CommandsRegistry.registerCommand('_remoteCLI.manageExtensions', async function (
|
|||
return lines.join('\n');
|
||||
});
|
||||
|
||||
class RemoteExtensionCLIManagementService extends ExtensionManagementCLIService {
|
||||
|
||||
private _location: string | undefined;
|
||||
|
||||
constructor(
|
||||
@IExtensionManagementService extensionManagementService: IExtensionManagementService,
|
||||
@IProductService private readonly productService: IProductService,
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService,
|
||||
@IExtensionGalleryService extensionGalleryService: IExtensionGalleryService,
|
||||
@ILocalizationsService localizationsService: ILocalizationsService,
|
||||
@ILabelService labelService: ILabelService,
|
||||
@IWorkbenchEnvironmentService envService: IWorkbenchEnvironmentService
|
||||
) {
|
||||
super(extensionManagementService, extensionGalleryService, localizationsService);
|
||||
|
||||
const remoteAuthority = envService.remoteAuthority;
|
||||
this._location = remoteAuthority ? labelService.getHostLabel(Schemas.vscodeRemote, remoteAuthority) : undefined;
|
||||
}
|
||||
|
||||
protected get location(): string | undefined {
|
||||
return this._location;
|
||||
}
|
||||
|
||||
protected validateExtensionKind(manifest: IExtensionManifest, output: CLIOutput): boolean {
|
||||
if (!canExecuteOnWorkspace(manifest, this.productService, this.configurationService)) {
|
||||
output.log(localize('cannot be installed', "Cannot install '{0}' because this extension has defined that it cannot run on the remote server.", getExtensionId(manifest.publisher, manifest.name)));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -93,9 +93,8 @@ import 'vs/workbench/services/outline/browser/outlineService';
|
|||
|
||||
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
import { ExtensionGalleryService } from 'vs/platform/extensionManagement/common/extensionGalleryService';
|
||||
import { ExtensionManagementCLIService } from 'vs/platform/extensionManagement/common/extensionManagementCLIService';
|
||||
import { GlobalExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionEnablementService';
|
||||
import { IExtensionGalleryService, IExtensionManagementCLIService, IGlobalExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
import { IExtensionGalleryService, IGlobalExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
import { ContextViewService } from 'vs/platform/contextview/browser/contextViewService';
|
||||
import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { IListService, ListService } from 'vs/platform/list/browser/listService';
|
||||
|
@ -127,7 +126,6 @@ registerSingleton(IIgnoredExtensionsManagementService, IgnoredExtensionsManageme
|
|||
registerSingleton(IGlobalExtensionEnablementService, GlobalExtensionEnablementService);
|
||||
registerSingleton(IExtensionsStorageSyncService, ExtensionsStorageSyncService);
|
||||
registerSingleton(IExtensionGalleryService, ExtensionGalleryService, true);
|
||||
registerSingleton(IExtensionManagementCLIService, ExtensionManagementCLIService);
|
||||
registerSingleton(IContextViewService, ContextViewService, true);
|
||||
registerSingleton(IListService, ListService, true);
|
||||
registerSingleton(IEditorWorkerService, EditorWorkerServiceImpl);
|
||||
|
|
Loading…
Reference in a new issue