Skip to content

Commit 222af4b

Browse files
committed
1 parent 8e39622 commit 222af4b

5 files changed

Lines changed: 60 additions & 89 deletions

File tree

src/vs/platform/extensionManagement/common/extensionManagement.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,6 @@ export interface IExtensionGalleryService {
158158
getChangelog(extension: IGalleryExtension, token: CancellationToken): Promise<string>;
159159
getCoreTranslation(extension: IGalleryExtension, languageId: string): Promise<ITranslation | null>;
160160
getAllVersions(extension: IGalleryExtension, compatible: boolean): Promise<IGalleryExtensionVersion[]>;
161-
loadAllDependencies(dependencies: IExtensionIdentifier[], token: CancellationToken): Promise<IGalleryExtension[]>;
162161
getExtensionsReport(): Promise<IReportedExtension[]>;
163162
getCompatibleExtension(extension: IGalleryExtension): Promise<IGalleryExtension | null>;
164163
getCompatibleExtension(id: IExtensionIdentifier, version?: string): Promise<IGalleryExtension | null>;

src/vs/platform/extensionManagement/node/extensionGalleryService.ts

Lines changed: 0 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55

66
import { tmpdir } from 'os';
77
import * as path from 'vs/base/common/path';
8-
import { distinct } from 'vs/base/common/arrays';
98
import { getErrorMessage, isPromiseCanceledError, canceled } from 'vs/base/common/errors';
109
import { StatisticType, IGalleryExtension, IExtensionGalleryService, IGalleryExtensionAsset, IQueryOptions, SortBy, SortOrder, IExtensionIdentifier, IReportedExtension, InstallOperation, ITranslation, IGalleryExtensionVersion, IGalleryExtensionAssets, isIExtensionIdentifier } from 'vs/platform/extensionManagement/common/extensionManagement';
1110
import { getGalleryExtensionId, getGalleryExtensionTelemetryData, adoptToGalleryExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
@@ -595,10 +594,6 @@ export class ExtensionGalleryService implements IExtensionGalleryService {
595594
return Promise.resolve('');
596595
}
597596

598-
loadAllDependencies(extensions: IExtensionIdentifier[], token: CancellationToken): Promise<IGalleryExtension[]> {
599-
return this.getDependenciesRecursively(extensions.map(e => e.id), [], token);
600-
}
601-
602597
getAllVersions(extension: IGalleryExtension, compatible: boolean): Promise<IGalleryExtensionVersion[]> {
603598
let query = new Query()
604599
.withFlags(Flags.IncludeVersions, Flags.IncludeFiles, Flags.IncludeVersionProperties, Flags.ExcludeNonValidated)
@@ -627,59 +622,6 @@ export class ExtensionGalleryService implements IExtensionGalleryService {
627622
});
628623
}
629624

630-
631-
private loadDependencies(extensionNames: string[], token: CancellationToken): Promise<IGalleryExtension[]> {
632-
if (!extensionNames || extensionNames.length === 0) {
633-
return Promise.resolve([]);
634-
}
635-
636-
let query = new Query()
637-
.withFlags(Flags.IncludeLatestVersionOnly, Flags.IncludeAssetUri, Flags.IncludeStatistics, Flags.IncludeFiles, Flags.IncludeVersionProperties)
638-
.withPage(1, extensionNames.length)
639-
.withFilter(FilterType.Target, 'Microsoft.VisualStudio.Code')
640-
.withFilter(FilterType.ExcludeWithFlags, flagsToString(Flags.Unpublished))
641-
.withAssetTypes(AssetType.Icon, AssetType.License, AssetType.Details, AssetType.Manifest, AssetType.VSIX)
642-
.withFilter(FilterType.ExtensionName, ...extensionNames);
643-
644-
return this.queryGallery(query, token).then(result => {
645-
const dependencies: IGalleryExtension[] = [];
646-
const ids: string[] = [];
647-
648-
for (let index = 0; index < result.galleryExtensions.length; index++) {
649-
const rawExtension = result.galleryExtensions[index];
650-
if (ids.indexOf(rawExtension.extensionId) === -1) {
651-
dependencies.push(toExtension(rawExtension, rawExtension.versions[0], index, query, 'dependencies'));
652-
ids.push(rawExtension.extensionId);
653-
}
654-
}
655-
return dependencies;
656-
});
657-
}
658-
659-
private getDependenciesRecursively(toGet: string[], result: IGalleryExtension[], token: CancellationToken): Promise<IGalleryExtension[]> {
660-
if (!toGet || !toGet.length) {
661-
return Promise.resolve(result);
662-
}
663-
toGet = result.length ? toGet.filter(e => !ExtensionGalleryService.hasExtensionByName(result, e)) : toGet;
664-
if (!toGet.length) {
665-
return Promise.resolve(result);
666-
}
667-
668-
return this.loadDependencies(toGet, token)
669-
.then(loadedDependencies => {
670-
const dependenciesSet = new Set<string>();
671-
for (const dep of loadedDependencies) {
672-
if (dep.properties.dependencies) {
673-
dep.properties.dependencies.forEach(d => dependenciesSet.add(d));
674-
}
675-
}
676-
result = distinct(result.concat(loadedDependencies), d => d.identifier.uuid);
677-
const dependencies: string[] = [];
678-
dependenciesSet.forEach(d => !ExtensionGalleryService.hasExtensionByName(result, d) && dependencies.push(d));
679-
return this.getDependenciesRecursively(dependencies, result, token);
680-
});
681-
}
682-
683625
private getAsset(asset: IGalleryExtensionAsset, options: IRequestOptions = {}, token: CancellationToken = CancellationToken.None): Promise<IRequestContext> {
684626
return this.commonHeadersPromise.then(commonHeaders => {
685627
const baseOptions = { type: 'GET' };
@@ -798,15 +740,6 @@ export class ExtensionGalleryService implements IExtensionGalleryService {
798740
});
799741
}
800742

801-
private static hasExtensionByName(extensions: IGalleryExtension[], name: string): boolean {
802-
for (const extension of extensions) {
803-
if (`${extension.publisher}.${extension.name}` === name) {
804-
return true;
805-
}
806-
}
807-
return false;
808-
}
809-
810743
getExtensionsReport(): Promise<IReportedExtension[]> {
811744
if (!this.isEnabled()) {
812745
return Promise.reject(new Error('No extension gallery service configured.'));

src/vs/platform/extensions/node/extensionsUtil.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,24 @@ export function isUIExtension(manifest: IExtensionManifest, uiContributions: str
1616
case 'ui': return true;
1717
case 'workspace': return false;
1818
default: {
19+
// Tagged as UI extension in product
1920
if (isNonEmptyArray(product.uiExtensions) && product.uiExtensions.some(id => areSameExtensions({ id }, { id: extensionId }))) {
2021
return true;
2122
}
23+
// Not an UI extension if it has main
2224
if (manifest.main) {
2325
return false;
2426
}
27+
// Not an UI extension if it has dependencies or an extension pack
28+
if (isNonEmptyArray(manifest.extensionDependencies) || isNonEmptyArray(manifest.extensionPack)) {
29+
return false;
30+
}
2531
if (manifest.contributes) {
32+
// Not an UI extension if it has no ui contributions
2633
if (!uiContributions.length || Object.keys(manifest.contributes).some(contribution => uiContributions.indexOf(contribution) === -1)) {
2734
return false;
2835
}
2936
}
30-
// Default is UI Extension
3137
return true;
3238
}
3339
}

src/vs/workbench/browser/web.simpleservices.ts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -333,11 +333,6 @@ export class SimpleExtensionGalleryService implements IExtensionGalleryService {
333333
return Promise.resolve(undefined);
334334
}
335335

336-
loadAllDependencies(dependencies: IExtensionIdentifier[], token: CancellationToken): Promise<IGalleryExtension[]> {
337-
// @ts-ignore
338-
return Promise.resolve(undefined);
339-
}
340-
341336
getExtensionsReport(): Promise<IReportedExtension[]> {
342337
// @ts-ignore
343338
return Promise.resolve(undefined);

src/vs/workbench/services/extensions/node/multiExtensionManagement.ts

Lines changed: 53 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ import { areSameExtensions } from 'vs/platform/extensionManagement/common/extens
1818
import { localize } from 'vs/nls';
1919
import { isUIExtension } from 'vs/workbench/services/extensions/node/extensionsUtil';
2020
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
21+
import { isNonEmptyArray } from 'vs/base/common/arrays';
22+
import { values } from 'vs/base/common/map';
2123

2224
export class MultiExtensionManagementService extends Disposable implements IExtensionManagementService {
2325

@@ -145,7 +147,7 @@ export class MultiExtensionManagementService extends Disposable implements IExte
145147
// Install only on remote server
146148
const promise = this.extensionManagementServerService.remoteExtensionManagementServer.extensionManagementService.install(vsix);
147149
// Install UI Dependencies on local server
148-
await this.installUIDependencies(manifest);
150+
await this.installUIDependenciesAndPackedExtensions(manifest);
149151
return promise;
150152
}
151153
return this.extensionManagementServerService.localExtensionManagementServer.extensionManagementService.install(vsix);
@@ -165,8 +167,8 @@ export class MultiExtensionManagementService extends Disposable implements IExte
165167
}
166168
// Install only on remote server
167169
const promise = this.extensionManagementServerService.remoteExtensionManagementServer.extensionManagementService.installFromGallery(gallery);
168-
// Install UI Dependencies on local server
169-
await this.installUIDependencies(manifest);
170+
// Install UI dependencies and packed extensions on local server
171+
await this.installUIDependenciesAndPackedExtensions(manifest);
170172
return promise;
171173
} else {
172174
return Promise.reject(localize('Manifest is not found', "Installing Extension {0} failed: Manifest is not found.", gallery.displayName || gallery.name));
@@ -175,18 +177,11 @@ export class MultiExtensionManagementService extends Disposable implements IExte
175177
return this.extensionManagementServerService.localExtensionManagementServer.extensionManagementService.installFromGallery(gallery);
176178
}
177179

178-
private async installUIDependencies(manifest: IExtensionManifest): Promise<void> {
179-
if (manifest.extensionDependencies && manifest.extensionDependencies.length) {
180-
const dependencies = await this.extensionGalleryService.loadAllDependencies(manifest.extensionDependencies.map(id => ({ id })), CancellationToken.None);
181-
if (dependencies.length) {
182-
await Promise.all(dependencies.map(async d => {
183-
const manifest = await this.extensionGalleryService.getManifest(d, CancellationToken.None);
184-
if (manifest && isUIExtension(manifest, this.configurationService)) {
185-
await this.extensionManagementServerService.localExtensionManagementServer.extensionManagementService.installFromGallery(d);
186-
}
187-
}));
188-
}
189-
}
180+
private async installUIDependenciesAndPackedExtensions(manifest: IExtensionManifest): Promise<void> {
181+
const uiExtensions = await this.getAllUIDependenciesAndPackedExtensions(manifest, CancellationToken.None);
182+
const installed = await this.extensionManagementServerService.localExtensionManagementServer.extensionManagementService.getInstalled();
183+
const toInstall = uiExtensions.filter(e => installed.every(i => !areSameExtensions(i.identifier, e.identifier)));
184+
await Promise.all(toInstall.map(d => this.extensionManagementServerService.localExtensionManagementServer.extensionManagementService.installFromGallery(d)));
190185
}
191186

192187
getExtensionsReport(): Promise<IReportedExtension[]> {
@@ -196,6 +191,49 @@ export class MultiExtensionManagementService extends Disposable implements IExte
196191
private getServer(extension: ILocalExtension): IExtensionManagementServer | null {
197192
return this.extensionManagementServerService.getExtensionManagementServer(extension.location);
198193
}
194+
195+
private async getAllUIDependenciesAndPackedExtensions(manifest: IExtensionManifest, token: CancellationToken): Promise<IGalleryExtension[]> {
196+
const result = new Map<string, IGalleryExtension>();
197+
const extensions = [...(manifest.extensionPack || []), ...(manifest.extensionDependencies || [])];
198+
await this.getAllUIDependenciesAndPackedExtensionsRecursively(extensions, result, token);
199+
return values(result);
200+
}
201+
202+
private async getAllUIDependenciesAndPackedExtensionsRecursively(toGet: string[], result: Map<string, IGalleryExtension>, token: CancellationToken): Promise<void> {
203+
if (toGet.length === 0) {
204+
return Promise.resolve();
205+
}
206+
207+
const extensions = (await this.extensionGalleryService.query({ names: toGet, pageSize: toGet.length }, token)).firstPage;
208+
const manifests = await Promise.all(extensions.map(e => this.extensionGalleryService.getManifest(e, token)));
209+
const uiExtensionsManifests: IExtensionManifest[] = [];
210+
for (let idx = 0; idx < extensions.length; idx++) {
211+
const extension = extensions[idx];
212+
const manifest = manifests[idx];
213+
if (manifest && isUIExtension(manifest, this.configurationService)) {
214+
result.set(extension.identifier.id.toLowerCase(), extension);
215+
uiExtensionsManifests.push(manifest);
216+
}
217+
}
218+
toGet = [];
219+
for (const uiExtensionManifest of uiExtensionsManifests) {
220+
if (isNonEmptyArray(uiExtensionManifest.extensionDependencies)) {
221+
for (const id of uiExtensionManifest.extensionDependencies) {
222+
if (!result.has(id.toLowerCase())) {
223+
toGet.push(id);
224+
}
225+
}
226+
}
227+
if (isNonEmptyArray(uiExtensionManifest.extensionPack)) {
228+
for (const id of uiExtensionManifest.extensionPack) {
229+
if (!result.has(id.toLowerCase())) {
230+
toGet.push(id);
231+
}
232+
}
233+
}
234+
}
235+
return this.getAllUIDependenciesAndPackedExtensionsRecursively(toGet, result, token);
236+
}
199237
}
200238

201239
registerSingleton(IExtensionManagementService, MultiExtensionManagementService);

0 commit comments

Comments
 (0)