提交 ed6c5c52 编写于 作者: S Sandeep Somavarapu

Implement microsoft/vscode-remote-release/issues/157

上级 105f8438
...@@ -44,6 +44,7 @@ import { ExtensionDependencyChecker } from 'vs/workbench/contrib/extensions/brow ...@@ -44,6 +44,7 @@ import { ExtensionDependencyChecker } from 'vs/workbench/contrib/extensions/brow
import { CancellationToken } from 'vs/base/common/cancellation'; import { CancellationToken } from 'vs/base/common/cancellation';
import { ExtensionType } from 'vs/platform/extensions/common/extensions'; import { ExtensionType } from 'vs/platform/extensions/common/extensions';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
import { RemoteExtensionsInstaller } from 'vs/workbench/contrib/extensions/browser/remoteExtensionsInstaller';
// Singletons // Singletons
registerSingleton(IExtensionsWorkbenchService, ExtensionsWorkbenchService); registerSingleton(IExtensionsWorkbenchService, ExtensionsWorkbenchService);
...@@ -372,3 +373,4 @@ workbenchRegistry.registerWorkbenchContribution(KeymapExtensions, LifecyclePhase ...@@ -372,3 +373,4 @@ workbenchRegistry.registerWorkbenchContribution(KeymapExtensions, LifecyclePhase
workbenchRegistry.registerWorkbenchContribution(ExtensionsViewletViewsContribution, LifecyclePhase.Starting); workbenchRegistry.registerWorkbenchContribution(ExtensionsViewletViewsContribution, LifecyclePhase.Starting);
workbenchRegistry.registerWorkbenchContribution(ExtensionActivationProgress, LifecyclePhase.Eventually); workbenchRegistry.registerWorkbenchContribution(ExtensionActivationProgress, LifecyclePhase.Eventually);
workbenchRegistry.registerWorkbenchContribution(ExtensionDependencyChecker, LifecyclePhase.Eventually); workbenchRegistry.registerWorkbenchContribution(ExtensionDependencyChecker, LifecyclePhase.Eventually);
workbenchRegistry.registerWorkbenchContribution(RemoteExtensionsInstaller, LifecyclePhase.Eventually);
...@@ -61,6 +61,7 @@ import { ITextFileService } from 'vs/workbench/services/textfile/common/textfile ...@@ -61,6 +61,7 @@ import { ITextFileService } from 'vs/workbench/services/textfile/common/textfile
import { IProductService } from 'vs/platform/product/common/product'; import { IProductService } from 'vs/platform/product/common/product';
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
import { IFileDialogService } from 'vs/platform/dialogs/common/dialogs'; import { IFileDialogService } from 'vs/platform/dialogs/common/dialogs';
import { IProgressService, ProgressLocation } from 'vs/platform/progress/common/progress';
export function toExtensionDescription(local: ILocalExtension): IExtensionDescription { export function toExtensionDescription(local: ILocalExtension): IExtensionDescription {
return { return {
...@@ -324,7 +325,6 @@ export class InstallInOtherServerAction extends ExtensionAction { ...@@ -324,7 +325,6 @@ export class InstallInOtherServerAction extends ExtensionAction {
&& (this.extension.enablementState === EnablementState.DisabledByExtensionKind || isLanguagePackExtension(this.extension.local.manifest)) && (this.extension.enablementState === EnablementState.DisabledByExtensionKind || isLanguagePackExtension(this.extension.local.manifest))
// Not installed in other server and can install in other server // Not installed in other server and can install in other server
&& !this.extensionsWorkbenchService.installed.some(e => areSameExtensions(e.identifier, this.extension.identifier) && e.server === this.server) && !this.extensionsWorkbenchService.installed.some(e => areSameExtensions(e.identifier, this.extension.identifier) && e.server === this.server)
&& this.extensionsWorkbenchService.canInstall(this.extension)
) { ) {
this.enabled = true; this.enabled = true;
this.updateLabel(); this.updateLabel();
...@@ -338,8 +338,14 @@ export class InstallInOtherServerAction extends ExtensionAction { ...@@ -338,8 +338,14 @@ export class InstallInOtherServerAction extends ExtensionAction {
this.update(); this.update();
this.extensionsWorkbenchService.open(this.extension); this.extensionsWorkbenchService.open(this.extension);
alert(localize('installExtensionStart', "Installing extension {0} started. An editor is now open with more details on this extension", this.extension.displayName)); alert(localize('installExtensionStart', "Installing extension {0} started. An editor is now open with more details on this extension", this.extension.displayName));
if (this.extension.gallery) { try {
await this.server.extensionManagementService.installFromGallery(this.extension.gallery); if (this.extension.gallery) {
await this.server.extensionManagementService.installFromGallery(this.extension.gallery);
} else {
const vsix = await this.extension.server!.extensionManagementService.zip(this.extension.local!);
await this.server.extensionManagementService.install(vsix);
}
} finally {
this.installing = false; this.installing = false;
this.update(); this.update();
} }
...@@ -3017,6 +3023,111 @@ export class InstallSpecificVersionOfExtensionAction extends Action { ...@@ -3017,6 +3023,111 @@ export class InstallSpecificVersionOfExtensionAction extends Action {
} }
} }
interface IExtensionPickItem extends IQuickPickItem {
extension?: IExtension;
}
export class InstallLocalExtensionsOnRemoteAction extends Action {
constructor(
@IExtensionsWorkbenchService private readonly extensionsWorkbenchService: IExtensionsWorkbenchService,
@IExtensionManagementServerService private readonly extensionManagementServerService: IExtensionManagementServerService,
@IExtensionGalleryService private readonly extensionGalleryService: IExtensionGalleryService,
@IQuickInputService private readonly quickInputService: IQuickInputService,
@INotificationService private readonly notificationService: INotificationService,
@IWindowService private readonly windowService: IWindowService,
@IProgressService private readonly progressService: IProgressService
) {
super('workbench.extensions.actions.installLocalExtensionsOnRemote');
this.enabled = !!this.extensionManagementServerService.localExtensionManagementServer && !!this.extensionManagementServerService.remoteExtensionManagementServer;
}
async run(): Promise<void> {
if (this.enabled) {
await this.selectAndInstallLocalExtensions();
}
}
private async getLocalExtensionsToInstall(): Promise<IExtension[]> {
const localExtensions = await this.extensionsWorkbenchService.queryLocal(this.extensionManagementServerService.localExtensionManagementServer!);
const remoteExtensions = await this.extensionsWorkbenchService.queryLocal(this.extensionManagementServerService.remoteExtensionManagementServer!);
const remoteExtensionsIds: Set<string> = new Set<string>();
const remoteExtensionsUUIDs: Set<string> = new Set<string>();
for (const extension of remoteExtensions) {
remoteExtensionsIds.add(extension.identifier.id.toLowerCase());
if (extension.identifier.uuid) {
remoteExtensionsUUIDs.add(extension.identifier.uuid);
}
}
const localExtensionsToInstall: IExtension[] = [];
for (const localExtension of localExtensions) {
if (localExtension.type === ExtensionType.User
&& (isLanguagePackExtension(localExtension.local!.manifest) || localExtension.enablementState === EnablementState.DisabledByExtensionKind)) {
if (!remoteExtensionsIds.has(localExtension.identifier.id.toLowerCase()) || (localExtension.identifier.uuid && !remoteExtensionsUUIDs.has(localExtension.identifier.uuid))) {
localExtensionsToInstall.push(localExtension);
}
}
}
return localExtensionsToInstall;
}
private async selectAndInstallLocalExtensions(): Promise<void> {
const result = await this.quickInputService.pick<IExtensionPickItem>(
this.getLocalExtensionsToInstall()
.then(extensions => {
if (extensions.length) {
extensions = extensions.sort((e1, e2) => e1.displayName.localeCompare(e2.displayName));
return extensions.map<IExtensionPickItem>(extension => ({ extension, label: extension.displayName, description: extension.version }));
}
return [{ label: localize('no local extensions', "There are no extensions to install.") }];
}),
{
canPickMany: true,
placeHolder: localize('select extensions to install', "Select extensions to install")
}
);
if (result) {
const localExtensionsToInstall = result.filter(r => !!r.extension).map(r => r.extension!);
if (localExtensionsToInstall.length) {
this.progressService.withProgress(
{
location: ProgressLocation.Notification,
title: localize('installing extensions', "Installing Extensions...")
},
() => this.installLocalExtensions(localExtensionsToInstall));
}
}
}
private async installLocalExtensions(localExtensionsToInstall: IExtension[]): Promise<void> {
const galleryExtensions: IGalleryExtension[] = [];
const vsixs: URI[] = [];
await Promise.all(localExtensionsToInstall.map(async extension => {
if (this.extensionGalleryService.isEnabled()) {
const gallery = await this.extensionGalleryService.getCompatibleExtension(extension.identifier, extension.version);
if (gallery) {
galleryExtensions.push(gallery);
return;
}
}
const vsix = await this.extensionManagementServerService.localExtensionManagementServer!.extensionManagementService.zip(extension.local!);
vsixs.push(vsix);
}));
await Promise.all(galleryExtensions.map(gallery => this.extensionManagementServerService.remoteExtensionManagementServer!.extensionManagementService.installFromGallery(gallery)));
await Promise.all(vsixs.map(vsix => this.extensionManagementServerService.remoteExtensionManagementServer!.extensionManagementService.install(vsix)));
this.notificationService.notify({
severity: Severity.Info,
message: localize('finished installing', "Completed installing the extensions. Please reload the window now."),
actions: {
primary: [new Action('realod', localize('reload', "Realod Window"), '', true,
() => this.windowService.reloadWindow())]
}
});
}
}
CommandsRegistry.registerCommand('workbench.extensions.action.showExtensionsForLanguage', function (accessor: ServicesAccessor, fileExtension: string) { CommandsRegistry.registerCommand('workbench.extensions.action.showExtensionsForLanguage', function (accessor: ServicesAccessor, fileExtension: string) {
const viewletService = accessor.get(IViewletService); const viewletService = accessor.get(IViewletService);
......
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
import { MenuRegistry, MenuId } from 'vs/platform/actions/common/actions';
import { localize } from 'vs/nls';
import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
import { IExtensionManagementServerService } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
import { ILabelService } from 'vs/platform/label/common/label';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { InstallLocalExtensionsOnRemoteAction } from 'vs/workbench/contrib/extensions/browser/extensionsActions';
export class RemoteExtensionsInstaller extends Disposable implements IWorkbenchContribution {
constructor(
@IExtensionManagementServerService private readonly extensionManagementServerService: IExtensionManagementServerService,
@ILabelService labelService: ILabelService,
@IInstantiationService instantiationService: IInstantiationService
) {
super();
if (this.extensionManagementServerService.localExtensionManagementServer && this.extensionManagementServerService.remoteExtensionManagementServer) {
CommandsRegistry.registerCommand('workbench.extensions.installLocalExtensions', () => instantiationService.createInstance(InstallLocalExtensionsOnRemoteAction).run());
let disposable = Disposable.None;
const appendMenuItem = () => {
disposable.dispose();
disposable = MenuRegistry.appendMenuItem(MenuId.CommandPalette, {
command: {
id: 'workbench.extensions.installLocalExtensions',
category: localize('extensions', "Extensions"),
title: localize('istall local extensions', "Install Local Extensions on {0}", this.extensionManagementServerService.remoteExtensionManagementServer!.label)
}
});
};
appendMenuItem();
this._register(labelService.onDidChangeFormatters(e => appendMenuItem()));
this._register(toDisposable(() => disposable.dispose()));
}
}
}
\ No newline at end of file
...@@ -130,7 +130,11 @@ export class ExtensionManagementService extends Disposable implements IExtension ...@@ -130,7 +130,11 @@ export class ExtensionManagementService extends Disposable implements IExtension
} }
zip(extension: ILocalExtension): Promise<URI> { zip(extension: ILocalExtension): Promise<URI> {
throw new Error('Not Supported'); const server = this.getServer(extension);
if (server) {
return server.extensionManagementService.zip(extension);
}
return Promise.reject(`Invalid location ${extension.location.toString()}`);
} }
unzip(zipLocation: URI, type: ExtensionType): Promise<IExtensionIdentifier> { unzip(zipLocation: URI, type: ExtensionType): Promise<IExtensionIdentifier> {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册