提交 8102ed5b 编写于 作者: S Sandeep Somavarapu

fix #12957

上级 3974c1e3
......@@ -98,6 +98,7 @@ export interface IExtensionManifest {
icon?: string;
categories?: string[];
activationEvents?: string[];
extensionDependencies: string[];
contributes?: IExtensionContributions;
}
......@@ -211,13 +212,18 @@ export interface DidInstallExtensionEvent {
error?: Error;
}
export interface DidUninstallExtensionEvent {
id: string;
error?: Error;
}
export interface IExtensionManagementService {
_serviceBrand: any;
onInstallExtension: Event<InstallExtensionEvent>;
onDidInstallExtension: Event<DidInstallExtensionEvent>;
onUninstallExtension: Event<string>;
onDidUninstallExtension: Event<string>;
onDidUninstallExtension: Event<DidUninstallExtensionEvent>;
install(zipPath: string): TPromise<void>;
installFromGallery(extension: IGalleryExtension, promptToInstallDependencies?: boolean): TPromise<void>;
......
......@@ -7,7 +7,7 @@
import { TPromise } from 'vs/base/common/winjs.base';
import { IChannel, eventToCall, eventFromCall } from 'vs/base/parts/ipc/common/ipc';
import { IExtensionManagementService, ILocalExtension, InstallExtensionEvent, DidInstallExtensionEvent, IGalleryExtension, LocalExtensionType } from './extensionManagement';
import { IExtensionManagementService, ILocalExtension, InstallExtensionEvent, DidInstallExtensionEvent, IGalleryExtension, LocalExtensionType, DidUninstallExtensionEvent } from './extensionManagement';
import Event, { buffer } from 'vs/base/common/event';
export interface IExtensionManagementChannel extends IChannel {
......@@ -27,7 +27,7 @@ export class ExtensionManagementChannel implements IExtensionManagementChannel {
onInstallExtension: Event<InstallExtensionEvent>;
onDidInstallExtension: Event<DidInstallExtensionEvent>;
onUninstallExtension: Event<string>;
onDidUninstallExtension: Event<string>;
onDidUninstallExtension: Event<DidUninstallExtensionEvent>;
constructor(private service: IExtensionManagementService) {
this.onInstallExtension = buffer(service.onInstallExtension, true);
......@@ -65,8 +65,8 @@ export class ExtensionManagementChannelClient implements IExtensionManagementSer
private _onUninstallExtension = eventFromCall<string>(this.channel, 'event:onUninstallExtension');
get onUninstallExtension(): Event<string> { return this._onUninstallExtension; }
private _onDidUninstallExtension = eventFromCall<string>(this.channel, 'event:onDidUninstallExtension');
get onDidUninstallExtension(): Event<string> { return this._onDidUninstallExtension; }
private _onDidUninstallExtension = eventFromCall<DidUninstallExtensionEvent>(this.channel, 'event:onDidUninstallExtension');
get onDidUninstallExtension(): Event<DidUninstallExtensionEvent> { return this._onDidUninstallExtension; }
install(zipPath: string): TPromise<void> {
return this.channel.call('install', zipPath);
......
......@@ -17,7 +17,7 @@ import { Promise, TPromise } from 'vs/base/common/winjs.base';
import {
IExtensionManagementService, IExtensionGalleryService, ILocalExtension,
IGalleryExtension, IExtensionIdentity, IExtensionManifest, IGalleryMetadata,
InstallExtensionEvent, DidInstallExtensionEvent, LocalExtensionType
InstallExtensionEvent, DidInstallExtensionEvent, DidUninstallExtensionEvent, LocalExtensionType
} from 'vs/platform/extensionManagement/common/extensionManagement';
import { localizeManifest } from '../common/extensionNls';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
......@@ -104,8 +104,8 @@ export class ExtensionManagementService implements IExtensionManagementService {
private _onUninstallExtension = new Emitter<string>();
onUninstallExtension: Event<string> = this._onUninstallExtension.event;
private _onDidUninstallExtension = new Emitter<string>();
onDidUninstallExtension: Event<string> = this._onDidUninstallExtension.event;
private _onDidUninstallExtension = new Emitter<DidUninstallExtensionEvent>();
onDidUninstallExtension: Event<DidUninstallExtensionEvent> = this._onDidUninstallExtension.event;
constructor(
@IEnvironmentService private environmentService: IEnvironmentService,
......@@ -315,23 +315,75 @@ export class ExtensionManagementService implements IExtensionManagementService {
return this.scanUserExtensions().then<void>(installed => {
const promises = installed
.filter(e => e.manifest.publisher === extension.manifest.publisher && e.manifest.name === extension.manifest.name)
.map(({ id }) => this.uninstallExtension(id));
.map(e => this.checkForDependenciesAndUninstall(e, installed));
return TPromise.join(promises);
});
});
}
private uninstallExtension(id: string): TPromise<void> {
const extensionPath = path.join(this.extensionsPath, id);
private checkForDependenciesAndUninstall(extension: ILocalExtension, installed: ILocalExtension[]): TPromise<void> {
return this.preUninstallExtension(extension.id)
.then(() => this.getDependenciesToUninstall(extension, installed)
.then(dependencies => dependencies.length ? this.promptAndUninstall(extension, dependencies) : this.uninstallExtension(extension.id)))
.then(() => this.postUninstallExtension(extension.id),
error => {
this.postUninstallExtension(extension.id, error);
return TPromise.wrapError(error);
});
}
private promptAndUninstall(extension: ILocalExtension, dependencies: ILocalExtension[]): TPromise<void> {
const message = nls.localize('uninstallDependeciesConfirmation', "Would you like to uninstall '{0}' only or its dependencies also?", extension.manifest.displayName);
const options = [
nls.localize('uninstallOnly', "Only"),
nls.localize('uninstallAll', "All"),
nls.localize('cancel', "Cancel")
];
return this.choiceService.choose(Severity.Info, message, options)
.then<void>(value => {
if (value === 0) {
return this.doUninstall(extension.id);
}
if (value === 1) {
return TPromise.join(dependencies.map(d => this.doUninstall(d.id)));
}
return TPromise.wrapError(errors.canceled());
}, error => TPromise.wrapError(errors.canceled()));
}
private getDependenciesToUninstall(extension: ILocalExtension, installed: ILocalExtension[]): TPromise<ILocalExtension[]> {
if (extension.manifest.extensionDependencies && extension.manifest.extensionDependencies.length) {
return TPromise.wrap(installed.filter(i => extension.manifest.extensionDependencies.indexOf(`${i.manifest.publisher}.${i.manifest.name}`) !== -1));
}
return TPromise.wrap([]);
}
private doUninstall(id: string): TPromise<void> {
return this.preUninstallExtension(id)
.then(() => this.uninstallExtension(id))
.then(() => this.postUninstallExtension(id),
error => {
this.postUninstallExtension(id, error);
return TPromise.wrapError(error);
});
}
private preUninstallExtension(id: string): TPromise<void> {
const extensionPath = path.join(this.extensionsPath, id);
return pfs.exists(extensionPath)
.then(exists => exists ? null : Promise.wrapError(new Error(nls.localize('notExists', "Could not find extension"))))
.then(() => this._onUninstallExtension.fire(id))
.then(() => this.setObsolete(id))
.then(() => this._onUninstallExtension.fire(id));
}
private uninstallExtension(id: string): TPromise<void> {
const extensionPath = path.join(this.extensionsPath, id);
return this.setObsolete(id)
.then(() => pfs.rimraf(extensionPath))
.then(() => this.unsetObsolete(id))
.then(() => this._onDidUninstallExtension.fire(id));
.then(() => this.unsetObsolete(id));
}
private postUninstallExtension(id: string, error?: any): TPromise<void> {
return this._onDidUninstallExtension.fire({ id, error });
}
getInstalled(type: LocalExtensionType = null): TPromise<ILocalExtension[]> {
......
......@@ -21,6 +21,7 @@ export enum ExtensionState {
Installed,
Enabled,
Disabled,
Uninstalling,
Uninstalled
}
......
......@@ -86,6 +86,12 @@ export class InstallAction extends Action {
export class UninstallAction extends Action {
private static UninstallLabel = localize('uninstallAction', "Uninstall");
private static UninstallingLabel = localize('Uninstalling', "Uninstalling");
private static UninstallClass = 'extension-action uninstall';
private static UnInstallingClass = 'extension-action uninstall uninstalling';
private disposables: IDisposable[] = [];
private _extension: IExtension;
get extension(): IExtension { return this._extension; }
......@@ -96,7 +102,7 @@ export class UninstallAction extends Action {
@IMessageService private messageService: IMessageService,
@IInstantiationService private instantiationService: IInstantiationService
) {
super('extensions.uninstall', localize('uninstall', "Uninstall"), 'extension-action uninstall', false);
super('extensions.uninstall', UninstallAction.UninstallLabel, UninstallAction.UninstallClass, false);
this.disposables.push(this.extensionsWorkbenchService.onChange(() => this.update()));
this.update();
......@@ -110,6 +116,14 @@ export class UninstallAction extends Action {
const state = this.extension.state;
if (state === ExtensionState.Uninstalling) {
this.label = UninstallAction.UninstallingLabel;
this.class = UninstallAction.UnInstallingClass;
} else {
this.label = UninstallAction.UninstallLabel;
this.class = UninstallAction.UninstallClass;
}
if (ExtensionState.Installed === state) {
this.enabled = true;
return;
......@@ -181,6 +195,10 @@ export class CombinedInstallAction extends Action {
this.enabled = false;
this.label = this.installAction.label;
this.class = this.installAction.class;
} else if (this.extension.state === ExtensionState.Uninstalling) {
this.enabled = false;
this.label = this.uninstallAction.label;
this.class = this.uninstallAction.class;
} else {
this.enabled = false;
this.label = this.installAction.label;
......@@ -510,7 +528,8 @@ export class ReloadAction extends Action {
return;
}
this.enabled = this.extension.reload || /* Following is needed due to extension is stale */this.extension.state === ExtensionState.Installed;
const state = this.extension.state;
this.enabled = state !== ExtensionState.Installing && state !== ExtensionState.Uninstalling && (this.extension.reload || /* Following is needed due to extension is stale */this.extension.state === ExtensionState.Installed);
this.class = this.enabled ? ReloadAction.EnabledClass : ReloadAction.DisabledClass;
}
......
......@@ -20,7 +20,7 @@ import { IPager, mapPager, singlePagePager } from 'vs/base/common/paging';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import {
IExtensionManagementService, IExtensionGalleryService, ILocalExtension, IGalleryExtension, IQueryOptions, IExtensionManifest,
InstallExtensionEvent, DidInstallExtensionEvent, LocalExtensionType
InstallExtensionEvent, DidInstallExtensionEvent, LocalExtensionType, DidUninstallExtensionEvent
} from 'vs/platform/extensionManagement/common/extensionManagement';
import { getGalleryExtensionTelemetryData, getLocalExtensionTelemetryData } from 'vs/platform/extensionManagement/common/extensionTelemetry';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
......@@ -568,11 +568,10 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService {
}
private onUninstallExtension(id: string): void {
const previousLength = this.installed.length;
const extension = this.installed.filter(e => e.local.id === id)[0];
this.installed = this.installed.filter(e => e.local.id !== id);
if (previousLength === this.installed.length) {
const newLength = this.installed.filter(e => e.local.id !== id).length;
// TODO: @Joao why is this?
if (newLength === this.installed.length) {
return;
}
......@@ -584,17 +583,22 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService {
this._onChange.fire();
}
private onDidUninstallExtension(id: string): void {
private onDidUninstallExtension({id, error}: DidUninstallExtensionEvent): void {
if (!error) {
this.installed = this.installed.filter(e => e.local.id !== id);
}
const uninstalling = this.uninstalling.filter(e => e.id === id)[0];
this.uninstalling = this.uninstalling.filter(e => e.id !== id);
if (!uninstalling) {
return;
}
this.unInstalled.push(uninstalling.extension);
uninstalling.extension.needsReload = true;
this.reportTelemetry(uninstalling, true);
if (!error) {
this.unInstalled.push(uninstalling.extension);
uninstalling.extension.needsReload = true;
this.reportTelemetry(uninstalling, true);
}
this._onChange.fire();
}
......@@ -603,6 +607,10 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService {
return ExtensionState.Installing;
}
if (extension.gallery && this.uninstalling.some(e => e.extension.gallery.id === extension.gallery.id)) {
return ExtensionState.Uninstalling;
}
const disabledExtensions = this.extensionsRuntimeService.getDisabledExtensions();
const local = this.installed.filter(e => e === extension || (e.gallery && extension.gallery && e.gallery.id === extension.gallery.id))[0];
......
......@@ -84,6 +84,7 @@
.monaco-action-bar .action-item.disabled .action-label.extension-action.install:not(.installing),
.monaco-action-bar .action-item.disabled .action-label.extension-action.uninstall:not(.uninstalling),
.monaco-action-bar .action-item.disabled .action-label.extension-action.update,
.monaco-action-bar .action-item.disabled .action-label.extension-action.enable,
.monaco-action-bar .action-item.disabled .action-label.extension-action.disable,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册