diff --git a/src/vs/platform/extensionManagement/common/extensionManagement.ts b/src/vs/platform/extensionManagement/common/extensionManagement.ts index e325573c7577a55d6695846cd477a0420ac99c2e..7e852d256ad7448373717544add0cf1b13b884d0 100644 --- a/src/vs/platform/extensionManagement/common/extensionManagement.ts +++ b/src/vs/platform/extensionManagement/common/extensionManagement.ts @@ -142,6 +142,7 @@ export interface IGalleryMetadata { id: string; publisherId: string; publisherDisplayName: string; + dependenciesInstalled: boolean; } export enum LocalExtensionType { diff --git a/src/vs/platform/extensionManagement/node/extensionManagementService.ts b/src/vs/platform/extensionManagement/node/extensionManagementService.ts index a428cf0b5451cc363a11dd8f33fd0e82a6fd2ca8..de991b8797a11172addb2a91256de03a531a5b2a 100644 --- a/src/vs/platform/extensionManagement/node/extensionManagementService.ts +++ b/src/vs/platform/extensionManagement/node/extensionManagementService.ts @@ -146,7 +146,8 @@ export class ExtensionManagementService implements IExtensionManagementService { return TPromise.wrapError(new Error(nls.localize('restartCode', "Please restart Code before reinstalling {0}.", extension.displayName || extension.name))); } this._onInstallExtension.fire({ id, gallery: extension }); - return this.installCompatibleVersion(extension, true) + return this.getLocalExtension(extension) + .then(local => this.installCompatibleVersion(extension, local ? local.metadata && local.metadata.dependenciesInstalled : true, !local)) .then( local => this._onDidInstallExtension.fire({ id, local, gallery: extension }), error => { @@ -157,34 +158,44 @@ export class ExtensionManagementService implements IExtensionManagementService { }); } - private installCompatibleVersion(extension: IGalleryExtension, checkDependecies: boolean): TPromise { + private installCompatibleVersion(extension: IGalleryExtension, installDependencies: boolean, promptToInstallDependencies: boolean): TPromise { return this.galleryService.loadCompatibleVersion(extension) - .then(compatibleVersion => this.getDependenciesToInstall(extension, checkDependecies) + .then(compatibleVersion => this.getDependenciesToInstall(extension, installDependencies) .then(dependencies => { if (!dependencies.length) { - return this.downloadAndInstall(compatibleVersion); + return this.downloadAndInstall(compatibleVersion, installDependencies && !!compatibleVersion.properties.dependencies.length); + } + if (promptToInstallDependencies) { + const message = nls.localize('installDependecies', "Would you also like to install dependencies of {0}?", extension.displayName); + const options = [ + nls.localize('installWithDependenices', "Yes"), + nls.localize('installWithoutDependenices', "No"), + nls.localize('cancel', "Cancel") + ]; + return this.choiceService.choose(Severity.Info, message, options) + .then(value => { + switch (value) { + case 0: + return this.installWithDependencies(compatibleVersion); + case 1: + return this.downloadAndInstall(compatibleVersion, false); + default: + return TPromise.wrapError(errors.canceled()); + } + }, error => TPromise.wrapError(errors.canceled())); + } else { + return this.installWithDependencies(compatibleVersion); } - const message = nls.localize('installDependecies', "Would you also like to install dependencies of {0}?", extension.displayName); - const options = [ - nls.localize('installWithDependenices', "Yes"), - nls.localize('installWithoutDependenices', "No"), - nls.localize('cancel', "Cancel") - ]; - return this.choiceService.choose(Severity.Info, message, options) - .then(value => { - switch (value) { - case 0: - return this.installWithDependencies(compatibleVersion); - case 1: - return this.downloadAndInstall(compatibleVersion); - default: - return TPromise.wrapError(errors.canceled()); - } - }, error => TPromise.wrapError(errors.canceled())); }) ); } + private getLocalExtension(extension: IGalleryExtension): TPromise { + const extensionName = `${extension.publisher}.${extension.name}`; + return this.getInstalled().then(installed => installed.filter(local => `${local.manifest.publisher}.${local.manifest.name}` === extensionName)) + .then(local => local.length ? local[0] : null); + } + private getDependenciesToInstall(extension: IGalleryExtension, checkDependecies: boolean): TPromise { if (!checkDependecies) { return TPromise.wrap([]); @@ -219,9 +230,9 @@ export class ExtensionManagementService implements IExtensionManagementService { const id = getExtensionId(dependency, dependency.version); this._onInstallExtension.fire({ id, gallery: dependency }); } - return this.downloadAndInstall(extension) + return this.downloadAndInstall(extension, true) .then(localExtension => { - return TPromise.join(dependecies.map((dep) => this.installCompatibleVersion(dep, false))) + return TPromise.join(dependecies.map((dep) => this.installCompatibleVersion(dep, false, false))) .then(installedLocalExtensions => { for (const installedLocalExtension of installedLocalExtensions) { const gallery = this.getGalleryExtensionForLocalExtension(dependecies, installedLocalExtension); @@ -271,12 +282,13 @@ export class ExtensionManagementService implements IExtensionManagementService { return filtered.length ? filtered[0] : null; } - private downloadAndInstall(extension: IGalleryExtension): TPromise { + private downloadAndInstall(extension: IGalleryExtension, dependenciesInstalled: boolean): TPromise { const id = getExtensionId(extension, extension.version); const metadata = { id: extension.id, publisherId: extension.publisherId, - publisherDisplayName: extension.publisherDisplayName + publisherDisplayName: extension.publisherDisplayName, + dependenciesInstalled: dependenciesInstalled }; return this.galleryService.download(extension) .then(zipPath => validate(zipPath).then(() => zipPath))