diff --git a/src/vs/code/node/cliProcessMain.ts b/src/vs/code/node/cliProcessMain.ts index 50b202a6a64..17624961e5f 100644 --- a/src/vs/code/node/cliProcessMain.ts +++ b/src/vs/code/node/cliProcessMain.ts @@ -136,7 +136,7 @@ export class Main { const [id, version] = getIdAndVersion(extension); return this.extensionManagementService.getInstalled(ExtensionType.User) - .then(installed => this.extensionGalleryService.getExtension({ id }, version) + .then(installed => this.extensionGalleryService.getCompatibleExtension({ id }, version) .then(null, err => { if (err.responseText) { try { diff --git a/src/vs/platform/extensionManagement/common/extensionManagement.ts b/src/vs/platform/extensionManagement/common/extensionManagement.ts index 5607fad1477..49b9378bb91 100644 --- a/src/vs/platform/extensionManagement/common/extensionManagement.ts +++ b/src/vs/platform/extensionManagement/common/extensionManagement.ts @@ -156,11 +156,11 @@ export interface IExtensionGalleryService { getManifest(extension: IGalleryExtension, token: CancellationToken): Promise; getChangelog(extension: IGalleryExtension, token: CancellationToken): Promise; getCoreTranslation(extension: IGalleryExtension, languageId: string): Promise; - loadCompatibleVersion(extension: IGalleryExtension, fromVersion?: string): Promise; getAllVersions(extension: IGalleryExtension, compatible: boolean): Promise; loadAllDependencies(dependencies: IExtensionIdentifier[], token: CancellationToken): Promise; getExtensionsReport(): Promise; - getExtension(id: IExtensionIdentifier, version?: string): Promise; + getCompatibleExtension(extension: IGalleryExtension): Promise; + getCompatibleExtension(id: IExtensionIdentifier, version?: string): Promise; } export interface InstallExtensionEvent { diff --git a/src/vs/platform/extensionManagement/node/extensionGalleryService.ts b/src/vs/platform/extensionManagement/node/extensionGalleryService.ts index ef888757750..a72c577218f 100644 --- a/src/vs/platform/extensionManagement/node/extensionGalleryService.ts +++ b/src/vs/platform/extensionManagement/node/extensionGalleryService.ts @@ -7,7 +7,7 @@ import { tmpdir } from 'os'; import * as path from 'path'; import { distinct } from 'vs/base/common/arrays'; import { getErrorMessage, isPromiseCanceledError, canceled } from 'vs/base/common/errors'; -import { StatisticType, IGalleryExtension, IExtensionGalleryService, IGalleryExtensionAsset, IQueryOptions, SortBy, SortOrder, IExtensionIdentifier, IReportedExtension, InstallOperation, ITranslation, IGalleryExtensionVersion, IGalleryExtensionAssets } from 'vs/platform/extensionManagement/common/extensionManagement'; +import { StatisticType, IGalleryExtension, IExtensionGalleryService, IGalleryExtensionAsset, IQueryOptions, SortBy, SortOrder, IExtensionIdentifier, IReportedExtension, InstallOperation, ITranslation, IGalleryExtensionVersion, IGalleryExtensionAssets, isIExtensionIdentifier } from 'vs/platform/extensionManagement/common/extensionManagement'; import { getGalleryExtensionId, getGalleryExtensionTelemetryData, adoptToGalleryExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; import { assign, getOrDefault } from 'vs/base/common/objects'; import { IRequestService } from 'vs/platform/request/node/request'; @@ -351,12 +351,18 @@ export class ExtensionGalleryService implements IExtensionGalleryService { return !!this.extensionsGalleryUrl; } - getExtension({ id, uuid }: IExtensionIdentifier, version?: string): Promise { + getCompatibleExtension(arg1: IExtensionIdentifier | IGalleryExtension, version?: string): Promise { + const extension: IGalleryExtension | null = isIExtensionIdentifier(arg1) ? null : arg1; + if (extension && extension.properties.engine && isEngineValid(extension.properties.engine)) { + return Promise.resolve(extension); + } + const { id, uuid } = extension ? extension.identifier : arg1; let query = new Query() .withFlags(Flags.IncludeAssetUri, Flags.IncludeStatistics, Flags.IncludeFiles, Flags.IncludeVersionProperties, Flags.ExcludeNonValidated) .withPage(1, 1) .withFilter(FilterType.Target, 'Microsoft.VisualStudio.Code') - .withFilter(FilterType.ExcludeWithFlags, flagsToString(Flags.Unpublished)); + .withFilter(FilterType.ExcludeWithFlags, flagsToString(Flags.Unpublished)) + .withAssetTypes(AssetType.Manifest, AssetType.VSIX); if (uuid) { query = query.withFilter(FilterType.ExtensionId, uuid); @@ -364,16 +370,30 @@ export class ExtensionGalleryService implements IExtensionGalleryService { query = query.withFilter(FilterType.ExtensionName, id); } - return this.queryGallery(query, CancellationToken.None).then(({ galleryExtensions }) => { - if (galleryExtensions.length) { - const galleryExtension = galleryExtensions[0]; - const versionAsset = version ? galleryExtension.versions.filter(v => v.version === version)[0] : galleryExtension.versions[0]; - if (versionAsset) { - return toExtension(galleryExtension, versionAsset, 0, query); + return this.queryGallery(query, CancellationToken.None) + .then(({ galleryExtensions }) => { + const [rawExtension] = galleryExtensions; + if (!rawExtension || !rawExtension.versions.length) { + return null; } - } - return null; - }); + if (version) { + const versionAsset = rawExtension.versions.filter(v => v.version === version)[0]; + if (versionAsset) { + const extension = toExtension(rawExtension, versionAsset, 0, query); + if (extension.properties.engine && isEngineValid(extension.properties.engine)) { + return extension; + } + } + return null; + } + return this.getLastValidExtensionVersion(rawExtension, rawExtension.versions) + .then(rawVersion => { + if (rawVersion) { + return toExtension(rawExtension, rawVersion, 0, query); + } + return null; + }); + }); } query(options: IQueryOptions = {}): Promise> { @@ -604,59 +624,6 @@ export class ExtensionGalleryService implements IExtensionGalleryService { }); } - loadCompatibleVersion(extension: IGalleryExtension, fromVersion: string = extension.version): Promise { - if (extension.version === fromVersion && extension.properties.engine && isEngineValid(extension.properties.engine)) { - return Promise.resolve(extension); - } - const query = new Query() - .withFlags(Flags.IncludeVersions, Flags.IncludeFiles, Flags.IncludeVersionProperties, Flags.ExcludeNonValidated) - .withPage(1, 1) - .withFilter(FilterType.Target, 'Microsoft.VisualStudio.Code') - .withFilter(FilterType.ExcludeWithFlags, flagsToString(Flags.Unpublished)) - .withAssetTypes(AssetType.Manifest, AssetType.VSIX) - .withFilter(FilterType.ExtensionId, extension.identifier.uuid); - - return this.queryGallery(query, CancellationToken.None) - .then(({ galleryExtensions }) => { - const [rawExtension] = galleryExtensions; - - if (!rawExtension) { - return null; - } - - const versions: IRawGalleryExtensionVersion[] = this.getVersionsFrom(rawExtension.versions, fromVersion); - if (!versions.length) { - return null; - } - - return this.getLastValidExtensionVersion(rawExtension, versions) - .then(rawVersion => { - if (rawVersion) { - return toExtension(rawExtension, rawVersion, 0, query); - } - return null; - }); - }); - } - - private getVersionsFrom(versions: IRawGalleryExtensionVersion[], version: string): IRawGalleryExtensionVersion[] { - if (versions[0].version === version) { - return versions; - } - const result: IRawGalleryExtensionVersion[] = []; - let currentVersion: IRawGalleryExtensionVersion | null = null; - for (const v of versions) { - if (!currentVersion) { - if (v.version === version) { - currentVersion = v; - } - } - if (currentVersion) { - result.push(v); - } - } - return result; - } private loadDependencies(extensionNames: string[], token: CancellationToken): Promise { if (!extensionNames || extensionNames.length === 0) { diff --git a/src/vs/platform/extensionManagement/node/extensionManagementService.ts b/src/vs/platform/extensionManagement/node/extensionManagementService.ts index 04c2c55614d..48f35949f1d 100644 --- a/src/vs/platform/extensionManagement/node/extensionManagementService.ts +++ b/src/vs/platform/extensionManagement/node/extensionManagementService.ts @@ -333,7 +333,7 @@ export class ExtensionManagementService extends Disposable implements IExtension return Promise.reject(new ExtensionManagementError(nls.localize('malicious extension', "Can't install extension since it was reported to be problematic."), INSTALL_ERROR_MALICIOUS)); } - const compatibleExtension = await this.galleryService.loadCompatibleVersion(extension); + const compatibleExtension = await this.galleryService.getCompatibleExtension(extension); if (!compatibleExtension) { return Promise.reject(new ExtensionManagementError(nls.localize('notFoundCompatibleDependency', "Unable to install because, the extension '{0}' compatible with current version '{1}' of VS Code is not found.", extension.identifier.id, pkg.version), INSTALL_ERROR_INCOMPATIBLE)); diff --git a/src/vs/platform/extensions/common/extensions.ts b/src/vs/platform/extensions/common/extensions.ts index ec9209e929f..e00d3ed9d5f 100644 --- a/src/vs/platform/extensions/common/extensions.ts +++ b/src/vs/platform/extensions/common/extensions.ts @@ -129,6 +129,13 @@ export class ExtensionIdentifierWithVersion { } } +export function isIExtensionIdentifier(thing: any): thing is IExtensionIdentifier { + return thing + && typeof thing === 'object' + && typeof thing.id === 'string' + && (!thing.uuid || typeof thing.uuid === 'string'); +} + export interface IExtensionIdentifier { id: string; uuid?: string; diff --git a/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.ts b/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.ts index 4aee8a6eac0..58ed50763e3 100644 --- a/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.ts +++ b/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.ts @@ -507,7 +507,7 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService, // Loading the compatible version only there is an engine property // Otherwise falling back to old way so that we will not make many roundtrips if (gallery.properties.engine) { - this.galleryService.loadCompatibleVersion(gallery) + this.galleryService.getCompatibleExtension(gallery) .then(compatible => compatible ? this.syncLocalWithGalleryExtension(result!, compatible) : null); } else { this.syncLocalWithGalleryExtension(result, gallery); @@ -679,7 +679,7 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService, return Promise.reject(new Error('Missing gallery')); } - return this.galleryService.getExtension(extension.gallery.identifier, version) + return this.galleryService.getCompatibleExtension(extension.gallery.identifier, version) .then(gallery => { if (!gallery) { return undefined; diff --git a/src/vs/workbench/services/extensions/electron-browser/inactiveExtensionUrlHandler.ts b/src/vs/workbench/services/extensions/electron-browser/inactiveExtensionUrlHandler.ts index 0b63147da65..f8afb7bc4f5 100644 --- a/src/vs/workbench/services/extensions/electron-browser/inactiveExtensionUrlHandler.ts +++ b/src/vs/workbench/services/extensions/electron-browser/inactiveExtensionUrlHandler.ts @@ -190,7 +190,7 @@ export class ExtensionUrlHandler implements IExtensionUrlHandler, IURLHandler { // Extension is not installed else { - const galleryExtension = await this.galleryService.getExtension(extensionIdentifier); + const galleryExtension = await this.galleryService.getCompatibleExtension(extensionIdentifier); if (!galleryExtension) { return;