Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/workbench/contrib/extensions/browser/extensionsDependencyChecker.ts
3296 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { IExtensionsWorkbenchService } from '../common/extensions.js';
7
import { IWorkbenchContribution } from '../../../common/contributions.js';
8
import { IExtensionService } from '../../../services/extensions/common/extensions.js';
9
import { CommandsRegistry } from '../../../../platform/commands/common/commands.js';
10
import { MenuRegistry, MenuId } from '../../../../platform/actions/common/actions.js';
11
import { localize } from '../../../../nls.js';
12
import { areSameExtensions } from '../../../../platform/extensionManagement/common/extensionManagementUtil.js';
13
import { INotificationService, Severity } from '../../../../platform/notification/common/notification.js';
14
import { Action } from '../../../../base/common/actions.js';
15
import { IHostService } from '../../../services/host/browser/host.js';
16
import { Disposable } from '../../../../base/common/lifecycle.js';
17
import { CancellationToken } from '../../../../base/common/cancellation.js';
18
import { Promises } from '../../../../base/common/async.js';
19
20
export class ExtensionDependencyChecker extends Disposable implements IWorkbenchContribution {
21
22
constructor(
23
@IExtensionService private readonly extensionService: IExtensionService,
24
@IExtensionsWorkbenchService private readonly extensionsWorkbenchService: IExtensionsWorkbenchService,
25
@INotificationService private readonly notificationService: INotificationService,
26
@IHostService private readonly hostService: IHostService
27
) {
28
super();
29
CommandsRegistry.registerCommand('workbench.extensions.installMissingDependencies', () => this.installMissingDependencies());
30
MenuRegistry.appendMenuItem(MenuId.CommandPalette, {
31
command: {
32
id: 'workbench.extensions.installMissingDependencies',
33
category: localize('extensions', "Extensions"),
34
title: localize('auto install missing deps', "Install Missing Dependencies")
35
}
36
});
37
}
38
39
private async getUninstalledMissingDependencies(): Promise<string[]> {
40
const allMissingDependencies = await this.getAllMissingDependencies();
41
const localExtensions = await this.extensionsWorkbenchService.queryLocal();
42
return allMissingDependencies.filter(id => localExtensions.every(l => !areSameExtensions(l.identifier, { id })));
43
}
44
45
private async getAllMissingDependencies(): Promise<string[]> {
46
await this.extensionService.whenInstalledExtensionsRegistered();
47
const runningExtensionsIds: Set<string> = this.extensionService.extensions.reduce((result, r) => { result.add(r.identifier.value.toLowerCase()); return result; }, new Set<string>());
48
const missingDependencies: Set<string> = new Set<string>();
49
for (const extension of this.extensionService.extensions) {
50
if (extension.extensionDependencies) {
51
extension.extensionDependencies.forEach(dep => {
52
if (!runningExtensionsIds.has(dep.toLowerCase())) {
53
missingDependencies.add(dep);
54
}
55
});
56
}
57
}
58
return [...missingDependencies.values()];
59
}
60
61
private async installMissingDependencies(): Promise<void> {
62
const missingDependencies = await this.getUninstalledMissingDependencies();
63
if (missingDependencies.length) {
64
const extensions = await this.extensionsWorkbenchService.getExtensions(missingDependencies.map(id => ({ id })), CancellationToken.None);
65
if (extensions.length) {
66
await Promises.settled(extensions.map(extension => this.extensionsWorkbenchService.install(extension)));
67
this.notificationService.notify({
68
severity: Severity.Info,
69
message: localize('finished installing missing deps', "Finished installing missing dependencies. Please reload the window now."),
70
actions: {
71
primary: [new Action('realod', localize('reload', "Reload Window"), '', true,
72
() => this.hostService.reload())]
73
}
74
});
75
}
76
} else {
77
this.notificationService.info(localize('no missing deps', "There are no missing dependencies to install."));
78
}
79
}
80
}
81
82