@codingame/monaco-vscode-extension-gallery-service-override 2.2.2 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/extensionGallery.js +23 -8
- package/package.json +9 -9
- package/vscode/src/vs/platform/extensionManagement/common/abstractExtensionManagementService.js +123 -163
- package/vscode/src/vs/platform/extensionManagement/common/extensionGalleryService.js +1 -1
- package/vscode/src/vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor.js +42 -7
- package/vscode/src/vs/workbench/contrib/extensions/browser/extensionEditor.js +43 -827
- package/vscode/src/vs/workbench/contrib/extensions/browser/extensionFeaturesTab.js +542 -0
- package/vscode/src/vs/workbench/contrib/extensions/browser/extensions.contribution.js +63 -54
- package/vscode/src/vs/workbench/contrib/extensions/browser/extensionsList.js +0 -1
- package/vscode/src/vs/workbench/contrib/extensions/browser/extensionsViewlet.js +10 -13
- package/vscode/src/vs/workbench/contrib/extensions/browser/extensionsViews.js +36 -8
- package/vscode/src/vs/workbench/contrib/extensions/browser/extensionsWidgets.js +2 -2
- package/vscode/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.js +1 -5
- package/vscode/src/vs/workbench/contrib/extensions/browser/media/extension.css.js +1 -1
- package/vscode/src/vs/workbench/contrib/extensions/browser/media/extensionEditor.css.js +1 -1
- package/vscode/src/vs/workbench/services/extensionManagement/common/extensionFeaturesManagemetService.js +234 -0
- package/vscode/src/vs/workbench/services/extensionManagement/common/webExtensionManagementService.js +2 -2
package/extensionGallery.js
CHANGED
|
@@ -21,30 +21,44 @@ import { ExtensionTipsService } from './vscode/src/vs/platform/extensionManageme
|
|
|
21
21
|
import { ExtensionManagementService } from './vscode/src/vs/workbench/services/extensionManagement/common/extensionManagementService.js';
|
|
22
22
|
import { IRemoteUserDataProfilesService, RemoteUserDataProfilesService } from 'vscode/vscode/vs/workbench/services/userDataProfile/common/remoteUserDataProfiles';
|
|
23
23
|
import { ExtensionEnablementService } from './vscode/src/vs/workbench/services/extensionManagement/browser/extensionEnablementService.js';
|
|
24
|
-
import './vscode/src/vs/workbench/contrib/extensions/browser/extensions.contribution.js';
|
|
25
|
-
import './vscode/src/vs/workbench/contrib/extensions/browser/extensions.web.contribution.js';
|
|
26
24
|
import { IExtensionUrlHandler, ExtensionUrlHandler } from 'vscode/vscode/vs/workbench/services/extensions/browser/extensionUrlHandler';
|
|
27
25
|
import { IRemoteAgentService } from 'vscode/vscode/vs/workbench/services/remote/common/remoteAgentService';
|
|
28
26
|
import { IInstantiationService } from 'vscode/vscode/vs/platform/instantiation/common/instantiation';
|
|
29
27
|
import { ILabelService } from 'vscode/vscode/vs/platform/label/common/label';
|
|
28
|
+
import { IExtensionFeaturesManagementService } from 'vscode/vscode/vs/workbench/services/extensionManagement/common/extensionFeatures';
|
|
29
|
+
import { ExtensionFeaturesManagementService } from './vscode/src/vs/workbench/services/extensionManagement/common/extensionFeaturesManagemetService.js';
|
|
30
30
|
import { registerAssets } from 'vscode/assets';
|
|
31
31
|
import { getExtensionManifests } from 'vscode/extensions';
|
|
32
|
+
import './vscode/src/vs/workbench/contrib/extensions/browser/extensions.contribution.js';
|
|
33
|
+
import './vscode/src/vs/workbench/contrib/extensions/browser/extensions.web.contribution.js';
|
|
32
34
|
|
|
33
35
|
registerAssets({
|
|
34
36
|
'vs/workbench/services/extensionManagement/common/media/defaultIcon.png': ( new URL('./assets/defaultIcon.png', import.meta.url).toString()),
|
|
35
37
|
'vs/workbench/contrib/extensions/browser/media/theme-icon.png': new URL('./assets/theme-icon.png', import.meta.url).href,
|
|
36
38
|
'vs/workbench/contrib/extensions/browser/media/language-icon.svg': new URL('./assets/theme-icon.png', import.meta.url).href
|
|
37
39
|
});
|
|
40
|
+
class EmptyRemoteAgentService {
|
|
41
|
+
constructor() {
|
|
42
|
+
this.getConnection = () => null;
|
|
43
|
+
this.getEnvironment = async () => null;
|
|
44
|
+
this.getRawEnvironment = async () => null;
|
|
45
|
+
this.getExtensionHostExitInfo = async () => null;
|
|
46
|
+
this.getRoundTripTime = async () => undefined;
|
|
47
|
+
this.whenExtensionsReady = async () => undefined;
|
|
48
|
+
this.scanExtensions = async () => [];
|
|
49
|
+
this.scanSingleExtension = async () => null;
|
|
50
|
+
this.getDiagnosticInfo = async () => undefined;
|
|
51
|
+
this.updateTelemetryLevel = async () => undefined;
|
|
52
|
+
this.logTelemetry = async () => undefined;
|
|
53
|
+
this.flushTelemetry = async () => undefined;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
38
56
|
let ExtensionManagementServerServiceOverride = class ExtensionManagementServerServiceOverride extends ExtensionManagementServerService {
|
|
39
57
|
constructor(isWebOnly, remoteAgentService, labelService, instantiationService) {
|
|
40
|
-
super(remoteAgentService, labelService, instantiationService);
|
|
41
|
-
this.isWebOnly = isWebOnly;
|
|
58
|
+
super(isWebOnly ? new EmptyRemoteAgentService() : remoteAgentService, labelService, instantiationService);
|
|
42
59
|
this.remoteAgentService = remoteAgentService;
|
|
43
60
|
this.labelService = labelService;
|
|
44
61
|
this.instantiationService = instantiationService;
|
|
45
|
-
if (this.isWebOnly) {
|
|
46
|
-
this.remoteExtensionManagementServer = null;
|
|
47
|
-
}
|
|
48
62
|
}
|
|
49
63
|
};
|
|
50
64
|
ExtensionManagementServerServiceOverride = __decorate([
|
|
@@ -75,7 +89,8 @@ function getServiceOverride(options = { webOnly: false }) {
|
|
|
75
89
|
[( IExtensionTipsService.toString())]: new SyncDescriptor(ExtensionTipsService, [], true),
|
|
76
90
|
[( IRemoteUserDataProfilesService.toString())]: new SyncDescriptor(RemoteUserDataProfilesService, [], true),
|
|
77
91
|
[( IWorkbenchExtensionEnablementService.toString())]: new SyncDescriptor(ExtensionEnablementService, [], true),
|
|
78
|
-
[( IExtensionUrlHandler.toString())]: new SyncDescriptor(ExtensionUrlHandler, [], true)
|
|
92
|
+
[( IExtensionUrlHandler.toString())]: new SyncDescriptor(ExtensionUrlHandler, [], true),
|
|
93
|
+
[( IExtensionFeaturesManagementService.toString())]: new SyncDescriptor(ExtensionFeaturesManagementService, [], true)
|
|
79
94
|
};
|
|
80
95
|
}
|
|
81
96
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@codingame/monaco-vscode-extension-gallery-service-override",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.1.0",
|
|
4
4
|
"keywords": [],
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "CodinGame",
|
|
@@ -18,15 +18,15 @@
|
|
|
18
18
|
"module": "index.js",
|
|
19
19
|
"types": "index.d.ts",
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"vscode": "npm:@codingame/monaco-vscode-api@
|
|
21
|
+
"vscode": "npm:@codingame/monaco-vscode-api@3.1.0",
|
|
22
22
|
"vscode-marked": "npm:marked@=3.0.2",
|
|
23
23
|
"vscode-semver": "npm:semver@=5.5.0",
|
|
24
|
-
"@codingame/monaco-vscode-files-service-override": "
|
|
25
|
-
"@codingame/monaco-vscode-quickaccess-service-override": "
|
|
26
|
-
"@codingame/monaco-vscode-extensions-service-override": "
|
|
27
|
-
"@codingame/monaco-vscode-environment-service-override": "
|
|
28
|
-
"@codingame/monaco-vscode-layout-service-override": "
|
|
29
|
-
"@codingame/monaco-vscode-host-service-override": "
|
|
30
|
-
"@codingame/monaco-vscode-base-service-override": "
|
|
24
|
+
"@codingame/monaco-vscode-files-service-override": "3.1.0",
|
|
25
|
+
"@codingame/monaco-vscode-quickaccess-service-override": "3.1.0",
|
|
26
|
+
"@codingame/monaco-vscode-extensions-service-override": "3.1.0",
|
|
27
|
+
"@codingame/monaco-vscode-environment-service-override": "3.1.0",
|
|
28
|
+
"@codingame/monaco-vscode-layout-service-override": "3.1.0",
|
|
29
|
+
"@codingame/monaco-vscode-host-service-override": "3.1.0",
|
|
30
|
+
"@codingame/monaco-vscode-base-service-override": "3.1.0"
|
|
31
31
|
}
|
|
32
32
|
}
|
package/vscode/src/vs/platform/extensionManagement/common/abstractExtensionManagementService.js
CHANGED
|
@@ -10,7 +10,7 @@ import { isDefined } from 'vscode/vscode/vs/base/common/types';
|
|
|
10
10
|
import { URI } from 'vscode/vscode/vs/base/common/uri';
|
|
11
11
|
import { localizeWithPath } from 'vscode/vscode/vs/nls';
|
|
12
12
|
import { isTargetPlatformCompatible, ExtensionManagementError, ExtensionManagementErrorCode, EXTENSION_INSTALL_DEP_PACK_CONTEXT, TargetPlatformToString, IExtensionGalleryService, ExtensionGalleryError } from 'vscode/vscode/vs/platform/extensionManagement/common/extensionManagement';
|
|
13
|
-
import { areSameExtensions, getGalleryExtensionTelemetryData,
|
|
13
|
+
import { areSameExtensions, getGalleryExtensionTelemetryData, ExtensionKey, getLocalExtensionTelemetryData } from 'vscode/vscode/vs/platform/extensionManagement/common/extensionManagementUtil';
|
|
14
14
|
import { isApplicationScopedExtension } from 'vscode/vscode/vs/platform/extensions/common/extensions';
|
|
15
15
|
import { ILogService } from 'vscode/vscode/vs/platform/log/common/log';
|
|
16
16
|
import { IProductService } from 'vscode/vscode/vs/platform/product/common/productService';
|
|
@@ -145,191 +145,153 @@ let AbstractExtensionManagementService = class AbstractExtensionManagementServic
|
|
|
145
145
|
}
|
|
146
146
|
async installExtensions(extensions) {
|
|
147
147
|
const results = [];
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
catch (error) {
|
|
161
|
-
results.push({ identifier: { id: getGalleryExtensionId(e.manifest.publisher, e.manifest.name) }, operation: 2 , source: e.extension, error });
|
|
148
|
+
const installingExtensionsMap = ( new Map());
|
|
149
|
+
const alreadyRequestedInstallations = [];
|
|
150
|
+
const successResults = [];
|
|
151
|
+
const getInstallExtensionTaskKey = (extension, profileLocation) => `${( ExtensionKey.create(extension).toString())}-${( profileLocation.toString())}`;
|
|
152
|
+
const createInstallExtensionTask = (manifest, extension, options) => {
|
|
153
|
+
const installExtensionTask = this.createInstallExtensionTask(manifest, extension, options);
|
|
154
|
+
const key = URI.isUri(extension) ? extension.path : `${extension.identifier.id.toLowerCase()}-${( options.profileLocation.toString())}`;
|
|
155
|
+
installingExtensionsMap.set(key, { task: installExtensionTask, manifest });
|
|
156
|
+
this._onInstallExtension.fire({ identifier: installExtensionTask.identifier, source: extension, profileLocation: options.profileLocation });
|
|
157
|
+
this.logService.info('Installing extension:', installExtensionTask.identifier.id);
|
|
158
|
+
if (!URI.isUri(extension)) {
|
|
159
|
+
this.installingExtensions.set(getInstallExtensionTaskKey(extension, options.profileLocation), { task: installExtensionTask, waitingTasks: [] });
|
|
162
160
|
}
|
|
163
|
-
})));
|
|
164
|
-
this._onDidInstallExtensions.fire(results);
|
|
165
|
-
return results;
|
|
166
|
-
}
|
|
167
|
-
async installExtension({ manifest, extension, options }, shouldWait) {
|
|
168
|
-
const isApplicationScoped = options.isApplicationScoped || options.isBuiltin || isApplicationScopedExtension(manifest);
|
|
169
|
-
const installExtensionTaskOptions = {
|
|
170
|
-
...options,
|
|
171
|
-
installOnlyNewlyAddedFromExtensionPack: URI.isUri(extension) ? options.installOnlyNewlyAddedFromExtensionPack : true,
|
|
172
|
-
isApplicationScoped,
|
|
173
|
-
profileLocation: isApplicationScoped ? this.userDataProfilesService.defaultProfile.extensionsResource : options.profileLocation ?? this.getCurrentExtensionsManifestLocation()
|
|
174
161
|
};
|
|
175
|
-
const getInstallExtensionTaskKey = (extension) => `${( ExtensionKey.create(extension).toString())}${installExtensionTaskOptions.profileLocation ? `-${( installExtensionTaskOptions.profileLocation.toString())}` : ''}`;
|
|
176
|
-
if (!URI.isUri(extension)) {
|
|
177
|
-
const installingExtension = this.installingExtensions.get(getInstallExtensionTaskKey(extension));
|
|
178
|
-
if (installingExtension) {
|
|
179
|
-
this.logService.info('Extensions is already requested to install', extension.identifier.id);
|
|
180
|
-
await installingExtension.task.waitUntilTaskIsFinished();
|
|
181
|
-
return [];
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
const allInstallExtensionTasks = [];
|
|
185
|
-
const alreadyRequestedInstallations = [];
|
|
186
|
-
const installResults = [];
|
|
187
|
-
const installExtensionTask = this.createInstallExtensionTask(manifest, extension, installExtensionTaskOptions);
|
|
188
|
-
if (!URI.isUri(extension)) {
|
|
189
|
-
this.installingExtensions.set(getInstallExtensionTaskKey(extension), { task: installExtensionTask, waitingTasks: [] });
|
|
190
|
-
}
|
|
191
|
-
this._onInstallExtension.fire({ identifier: installExtensionTask.identifier, source: extension, profileLocation: installExtensionTaskOptions.profileLocation });
|
|
192
|
-
this.logService.info('Installing extension:', installExtensionTask.identifier.id);
|
|
193
|
-
allInstallExtensionTasks.push({ task: installExtensionTask, manifest });
|
|
194
|
-
let installExtensionHasDependents = false;
|
|
195
162
|
try {
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
if (existingInstallingExtension) {
|
|
209
|
-
if (shouldWait(installExtensionTask, existingInstallingExtension.task)) {
|
|
210
|
-
const identifier = existingInstallingExtension.task.identifier;
|
|
211
|
-
this.logService.info('Waiting for already requested installing extension', identifier.id, installExtensionTask.identifier.id);
|
|
212
|
-
existingInstallingExtension.waitingTasks.push(installExtensionTask);
|
|
213
|
-
alreadyRequestedInstallations.push(Event.toPromise(Event.filter(this.onDidInstallExtensions, results => ( results.some(result => areSameExtensions(result.identifier, identifier))))).then(results => {
|
|
214
|
-
this.logService.info('Finished waiting for already requested installing extension', identifier.id, installExtensionTask.identifier.id);
|
|
215
|
-
const result = results.find(result => areSameExtensions(result.identifier, identifier));
|
|
216
|
-
if (!result?.local) {
|
|
217
|
-
throw new Error(`Extension ${identifier.id} is not installed`);
|
|
218
|
-
}
|
|
219
|
-
}));
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
else if (!( installed.some(({ identifier }) => areSameExtensions(identifier, gallery.identifier)))) {
|
|
223
|
-
const task = this.createInstallExtensionTask(manifest, gallery, options);
|
|
224
|
-
this.installingExtensions.set(key, { task, waitingTasks: [installExtensionTask] });
|
|
225
|
-
this._onInstallExtension.fire({ identifier: task.identifier, source: gallery, profileLocation: installExtensionTaskOptions.profileLocation });
|
|
226
|
-
this.logService.info('Installing extension:', task.identifier.id, installExtensionTask.identifier.id);
|
|
227
|
-
allInstallExtensionTasks.push({ task, manifest });
|
|
228
|
-
}
|
|
229
|
-
}
|
|
163
|
+
for (const { manifest, extension, options } of extensions) {
|
|
164
|
+
const isApplicationScoped = options.isApplicationScoped || options.isBuiltin || isApplicationScopedExtension(manifest);
|
|
165
|
+
const installExtensionTaskOptions = {
|
|
166
|
+
...options,
|
|
167
|
+
installOnlyNewlyAddedFromExtensionPack: URI.isUri(extension) ? options.installOnlyNewlyAddedFromExtensionPack : true,
|
|
168
|
+
isApplicationScoped,
|
|
169
|
+
profileLocation: isApplicationScoped ? this.userDataProfilesService.defaultProfile.extensionsResource : options.profileLocation ?? this.getCurrentExtensionsManifestLocation()
|
|
170
|
+
};
|
|
171
|
+
const existingInstallExtensionTask = !URI.isUri(extension) ? this.installingExtensions.get(getInstallExtensionTaskKey(extension, installExtensionTaskOptions.profileLocation)) : undefined;
|
|
172
|
+
if (existingInstallExtensionTask) {
|
|
173
|
+
this.logService.info('Extension is already requested to install', existingInstallExtensionTask.task.identifier.id);
|
|
174
|
+
alreadyRequestedInstallations.push(existingInstallExtensionTask.task.waitUntilTaskIsFinished());
|
|
230
175
|
}
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
if (isNonEmptyArray(manifest.extensionDependencies)) {
|
|
234
|
-
this.logService.warn(`Cannot install dependencies of extension:`, installExtensionTask.identifier.id, error.message);
|
|
235
|
-
}
|
|
236
|
-
if (isNonEmptyArray(manifest.extensionPack)) {
|
|
237
|
-
this.logService.warn(`Cannot install packed extensions of extension:`, installExtensionTask.identifier.id, error.message);
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
else {
|
|
241
|
-
this.logService.error('Error while preparing to install dependencies and extension packs of the extension:', installExtensionTask.identifier.id);
|
|
242
|
-
throw error;
|
|
243
|
-
}
|
|
176
|
+
else {
|
|
177
|
+
createInstallExtensionTask(manifest, extension, installExtensionTaskOptions);
|
|
244
178
|
}
|
|
245
179
|
}
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
}, ( new Map()));
|
|
250
|
-
while (extensionsToInstallMap.size) {
|
|
251
|
-
let extensionsToInstall;
|
|
252
|
-
const extensionsWithoutDepsToInstall = [...( extensionsToInstallMap.values())].filter(({ manifest }) => !manifest.extensionDependencies?.some(id => ( extensionsToInstallMap.has(id.toLowerCase()))));
|
|
253
|
-
if (extensionsWithoutDepsToInstall.length) {
|
|
254
|
-
extensionsToInstall = extensionsToInstallMap.size === 1 ? extensionsWithoutDepsToInstall
|
|
255
|
-
: extensionsWithoutDepsToInstall.filter(({ task }) => !(task === installExtensionTask && !installExtensionHasDependents));
|
|
180
|
+
await Promise.all(( [...( installingExtensionsMap.values())].map(async ({ task, manifest }) => {
|
|
181
|
+
if (task.options.donotIncludePackAndDependencies) {
|
|
182
|
+
this.logService.info('Installing the extension without checking dependencies and pack', task.identifier.id);
|
|
256
183
|
}
|
|
257
184
|
else {
|
|
258
|
-
this.logService.info('Found extensions with circular dependencies', ( extensionsWithoutDepsToInstall.map(({ task }) => task.identifier.id)));
|
|
259
|
-
extensionsToInstall = [...( extensionsToInstallMap.values())];
|
|
260
|
-
}
|
|
261
|
-
await this.joinAllSettled(( extensionsToInstall.map(async ({ task }) => {
|
|
262
|
-
const startTime = ( new Date()).getTime();
|
|
263
185
|
try {
|
|
264
|
-
const
|
|
265
|
-
await this.
|
|
266
|
-
|
|
267
|
-
)))
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
186
|
+
const allDepsAndPackExtensionsToInstall = await this.getAllDepsAndPackExtensions(task.identifier, manifest, !!task.options.installOnlyNewlyAddedFromExtensionPack, !!task.options.installPreReleaseVersion, task.options.profileLocation);
|
|
187
|
+
const installed = await this.getInstalled(undefined, task.options.profileLocation);
|
|
188
|
+
const options = { ...task.options, donotIncludePackAndDependencies: true, context: { ...task.options.context, [EXTENSION_INSTALL_DEP_PACK_CONTEXT]: true } };
|
|
189
|
+
for (const { gallery, manifest } of distinct(allDepsAndPackExtensionsToInstall, ({ gallery }) => gallery.identifier.id)) {
|
|
190
|
+
if (( installingExtensionsMap.has(`${gallery.identifier.id.toLowerCase()}-${( options.profileLocation.toString())}`))) {
|
|
191
|
+
continue;
|
|
192
|
+
}
|
|
193
|
+
const existingInstallingExtension = this.installingExtensions.get(getInstallExtensionTaskKey(gallery, options.profileLocation));
|
|
194
|
+
if (existingInstallingExtension) {
|
|
195
|
+
if (this.canWaitForTask(task, existingInstallingExtension.task)) {
|
|
196
|
+
const identifier = existingInstallingExtension.task.identifier;
|
|
197
|
+
this.logService.info('Waiting for already requested installing extension', identifier.id, task.identifier.id);
|
|
198
|
+
existingInstallingExtension.waitingTasks.push(task);
|
|
199
|
+
alreadyRequestedInstallations.push(Event.toPromise(Event.filter(this.onDidInstallExtensions, results => ( results.some(result => areSameExtensions(result.identifier, identifier))))).then(results => {
|
|
200
|
+
this.logService.info('Finished waiting for already requested installing extension', identifier.id, task.identifier.id);
|
|
201
|
+
const result = results.find(result => areSameExtensions(result.identifier, identifier));
|
|
202
|
+
if (!result?.local) {
|
|
203
|
+
throw new Error(`Extension ${identifier.id} is not installed`);
|
|
204
|
+
}
|
|
205
|
+
}));
|
|
280
206
|
}
|
|
281
|
-
|
|
207
|
+
}
|
|
208
|
+
else if (!( installed.some(({ identifier }) => areSameExtensions(identifier, gallery.identifier)))) {
|
|
209
|
+
createInstallExtensionTask(manifest, gallery, options);
|
|
282
210
|
}
|
|
283
211
|
}
|
|
284
|
-
installResults.push({ local, identifier: task.identifier, operation: task.operation, source: task.source, context: task.options.context, profileLocation: task.profileLocation, applicationScoped: local.isApplicationScoped });
|
|
285
212
|
}
|
|
286
213
|
catch (error) {
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
214
|
+
if (URI.isUri(task.source)) {
|
|
215
|
+
if (isNonEmptyArray(manifest.extensionDependencies)) {
|
|
216
|
+
this.logService.warn(`Cannot install dependencies of extension:`, task.identifier.id, error.message);
|
|
217
|
+
}
|
|
218
|
+
if (isNonEmptyArray(manifest.extensionPack)) {
|
|
219
|
+
this.logService.warn(`Cannot install packed extensions of extension:`, task.identifier.id, error.message);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
this.logService.error('Error while preparing to install dependencies and extension packs of the extension:', task.identifier.id);
|
|
224
|
+
throw error;
|
|
225
|
+
}
|
|
292
226
|
}
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
}
|
|
298
|
-
installResults.forEach(({ identifier }) => this.logService.info(`Extension installed successfully:`, identifier.id));
|
|
299
|
-
return installResults;
|
|
300
|
-
}
|
|
301
|
-
catch (error) {
|
|
302
|
-
allInstallExtensionTasks.forEach(({ task }) => task.cancel());
|
|
303
|
-
if (installResults.length) {
|
|
227
|
+
}
|
|
228
|
+
})));
|
|
229
|
+
await this.joinAllSettled(( [...( installingExtensionsMap.values())].map(async ({ task }) => {
|
|
230
|
+
const startTime = ( new Date()).getTime();
|
|
304
231
|
try {
|
|
305
|
-
const
|
|
306
|
-
|
|
232
|
+
const local = await task.run();
|
|
233
|
+
await this.joinAllSettled(( this.participants.map(
|
|
234
|
+
participant => participant.postInstall(local, task.source, task.options, CancellationToken.None)
|
|
307
235
|
)));
|
|
308
|
-
|
|
309
|
-
const
|
|
310
|
-
const
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
236
|
+
if (!URI.isUri(task.source)) {
|
|
237
|
+
const isUpdate = task.operation === 3 ;
|
|
238
|
+
const durationSinceUpdate = isUpdate ? undefined : (( new Date()).getTime() - task.source.lastUpdated) / 1000;
|
|
239
|
+
reportTelemetry(this.telemetryService, isUpdate ? 'extensionGallery:update' : 'extensionGallery:install', {
|
|
240
|
+
extensionData: getGalleryExtensionTelemetryData(task.source),
|
|
241
|
+
verificationStatus: task.verificationStatus,
|
|
242
|
+
duration: ( new Date()).getTime() - startTime,
|
|
243
|
+
durationSinceUpdate
|
|
244
|
+
});
|
|
245
|
+
if (isWeb && task.operation !== 3 ) {
|
|
246
|
+
try {
|
|
247
|
+
await this.galleryService.reportStatistic(local.manifest.publisher, local.manifest.name, local.manifest.version, "install" );
|
|
248
|
+
}
|
|
249
|
+
catch (error) { }
|
|
316
250
|
}
|
|
317
251
|
}
|
|
252
|
+
successResults.push({ local, identifier: task.identifier, operation: task.operation, source: task.source, context: task.options.context, profileLocation: task.profileLocation, applicationScoped: local.isApplicationScoped });
|
|
318
253
|
}
|
|
319
254
|
catch (error) {
|
|
320
|
-
this.logService.
|
|
255
|
+
this.logService.error('Error while installing the extension', task.identifier.id, getErrorMessage(error));
|
|
256
|
+
throw error;
|
|
321
257
|
}
|
|
258
|
+
})));
|
|
259
|
+
if (alreadyRequestedInstallations.length) {
|
|
260
|
+
await this.joinAllSettled(alreadyRequestedInstallations);
|
|
322
261
|
}
|
|
323
|
-
|
|
324
|
-
(
|
|
325
|
-
|
|
262
|
+
for (const result of successResults) {
|
|
263
|
+
this.logService.info(`Extension installed successfully:`, result.identifier.id);
|
|
264
|
+
results.push(result);
|
|
265
|
+
}
|
|
266
|
+
return results;
|
|
267
|
+
}
|
|
268
|
+
catch (error) {
|
|
269
|
+
if (successResults.length) {
|
|
270
|
+
await Promise.allSettled(( successResults.map(async ({ local, profileLocation }) => {
|
|
271
|
+
try {
|
|
272
|
+
await this.createUninstallExtensionTask(local, { versionOnly: true, profileLocation }).run();
|
|
273
|
+
this.logService.info('Rollback: Uninstalled extension', local.identifier.id);
|
|
274
|
+
}
|
|
275
|
+
catch (error) {
|
|
276
|
+
this.logService.warn('Rollback: Error while uninstalling extension', local.identifier.id, getErrorMessage(error));
|
|
277
|
+
}
|
|
278
|
+
})));
|
|
279
|
+
}
|
|
280
|
+
for (const { task } of ( installingExtensionsMap.values())) {
|
|
281
|
+
task.cancel();
|
|
282
|
+
results.push({ identifier: task.identifier, operation: 2 , source: task.source, context: task.options.context, profileLocation: task.profileLocation, error });
|
|
283
|
+
}
|
|
284
|
+
throw error;
|
|
326
285
|
}
|
|
327
286
|
finally {
|
|
328
|
-
for (const { task } of
|
|
287
|
+
for (const { task } of ( installingExtensionsMap.values())) {
|
|
329
288
|
if (task.source && !URI.isUri(task.source)) {
|
|
330
|
-
this.installingExtensions.delete(getInstallExtensionTaskKey(task.source));
|
|
289
|
+
this.installingExtensions.delete(getInstallExtensionTaskKey(task.source, task.profileLocation));
|
|
331
290
|
}
|
|
332
291
|
}
|
|
292
|
+
if (results.length) {
|
|
293
|
+
this._onDidInstallExtensions.fire(results);
|
|
294
|
+
}
|
|
333
295
|
}
|
|
334
296
|
}
|
|
335
297
|
canWaitForTask(taskToWait, taskToWaitFor) {
|
|
@@ -682,13 +644,11 @@ let AbstractExtensionManagementService = class AbstractExtensionManagementServic
|
|
|
682
644
|
}
|
|
683
645
|
async updateControlCache() {
|
|
684
646
|
try {
|
|
685
|
-
this.logService.trace('ExtensionManagementService.
|
|
686
|
-
|
|
687
|
-
this.logService.trace(`ExtensionManagementService.refreshControlCache`, manifest);
|
|
688
|
-
return manifest;
|
|
647
|
+
this.logService.trace('ExtensionManagementService.updateControlCache');
|
|
648
|
+
return await this.galleryService.getExtensionsControlManifest();
|
|
689
649
|
}
|
|
690
650
|
catch (err) {
|
|
691
|
-
this.logService.trace('ExtensionManagementService.refreshControlCache - failed to get extension control manifest');
|
|
651
|
+
this.logService.trace('ExtensionManagementService.refreshControlCache - failed to get extension control manifest', getErrorMessage(err));
|
|
692
652
|
return { malicious: [], deprecated: {}, search: [] };
|
|
693
653
|
}
|
|
694
654
|
}
|
|
@@ -269,7 +269,7 @@ function toExtension(galleryExtension, version, allTargetPlatforms, queryContext
|
|
|
269
269
|
publisherDisplayName: galleryExtension.publisher.displayName,
|
|
270
270
|
publisherDomain: galleryExtension.publisher.domain ? { link: galleryExtension.publisher.domain, verified: !!galleryExtension.publisher.isDomainVerified } : undefined,
|
|
271
271
|
publisherSponsorLink: getSponsorLink(latestVersion),
|
|
272
|
-
description: galleryExtension.shortDescription
|
|
272
|
+
description: galleryExtension.shortDescription ?? '',
|
|
273
273
|
installCount: getStatistic(galleryExtension.statistics, 'install'),
|
|
274
274
|
rating: getStatistic(galleryExtension.statistics, 'averagerating'),
|
|
275
275
|
ratingCount: getStatistic(galleryExtension.statistics, 'ratingcount'),
|
package/vscode/src/vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor.js
CHANGED
|
@@ -5,11 +5,12 @@ import { renderLabelWithIcons } from 'vscode/vscode/vs/base/browser/ui/iconLabel
|
|
|
5
5
|
import { Action, Separator } from 'vscode/vscode/vs/base/common/actions';
|
|
6
6
|
import { isNonEmptyArray } from 'vscode/vscode/vs/base/common/arrays';
|
|
7
7
|
import { RunOnceScheduler } from 'vscode/vscode/vs/base/common/async';
|
|
8
|
+
import { fromNow } from 'vscode/vscode/vs/base/common/date';
|
|
8
9
|
import { memoize } from 'vscode/vscode/vs/base/common/decorators';
|
|
9
10
|
import { dispose } from 'vscode/vscode/vs/base/common/lifecycle';
|
|
10
11
|
import { Schemas } from 'vscode/vscode/vs/base/common/network';
|
|
11
12
|
import './media/runtimeExtensionsEditor.css.js';
|
|
12
|
-
import { localizeWithPath } from 'vscode/vscode/vs/nls';
|
|
13
|
+
import { localizeWithPath, localize2WithPath } from 'vscode/vscode/vs/nls';
|
|
13
14
|
import { Categories } from 'vscode/vscode/vs/platform/action/common/actionCommonCategories';
|
|
14
15
|
import { Action2, MenuId } from 'vscode/vscode/vs/platform/actions/common/actions';
|
|
15
16
|
import { IClipboardService } from 'vscode/vscode/vs/platform/clipboard/common/clipboardService';
|
|
@@ -19,16 +20,19 @@ import { ExtensionIdentifierMap } from 'vscode/vscode/vs/platform/extensions/com
|
|
|
19
20
|
import { IInstantiationService } from 'vscode/vscode/vs/platform/instantiation/common/instantiation';
|
|
20
21
|
import { ILabelService } from 'vscode/vscode/vs/platform/label/common/label';
|
|
21
22
|
import { WorkbenchList } from 'vscode/vscode/vs/platform/list/browser/listService';
|
|
22
|
-
import { INotificationService } from 'vscode/vscode/vs/platform/notification/common/notification';
|
|
23
|
+
import { Severity, INotificationService } from 'vscode/vscode/vs/platform/notification/common/notification';
|
|
24
|
+
import { Registry } from 'vscode/vscode/vs/platform/registry/common/platform';
|
|
23
25
|
import { IStorageService } from 'vscode/vscode/vs/platform/storage/common/storage';
|
|
24
26
|
import { ITelemetryService } from 'vscode/vscode/vs/platform/telemetry/common/telemetry';
|
|
25
27
|
import { editorBackground } from 'vscode/vscode/vs/platform/theme/common/colorRegistry';
|
|
26
28
|
import { IThemeService } from 'vscode/vscode/vs/platform/theme/common/themeService';
|
|
27
29
|
import { EditorPane } from 'vscode/vscode/vs/workbench/browser/parts/editor/editorPane';
|
|
30
|
+
import { errorIcon, warningIcon } from 'vscode/vscode/vs/workbench/contrib/extensions/browser/extensionsIcons';
|
|
28
31
|
import { IExtensionsWorkbenchService } from 'vscode/vscode/vs/workbench/contrib/extensions/common/extensions';
|
|
29
32
|
import { RuntimeExtensionsInput } from '../common/runtimeExtensionsInput.js';
|
|
30
33
|
import { IEditorService } from 'vscode/vscode/vs/workbench/services/editor/common/editorService';
|
|
31
34
|
import { IWorkbenchEnvironmentService } from 'vscode/vscode/vs/workbench/services/environment/common/environmentService';
|
|
35
|
+
import { Extensions, IExtensionFeaturesManagementService } from 'vscode/vscode/vs/workbench/services/extensionManagement/common/extensionFeatures';
|
|
32
36
|
import { getDefaultIconPath } from 'vscode/vscode/vs/workbench/services/extensionManagement/common/extensionManagement';
|
|
33
37
|
import { LocalWebWorkerRunningLocation } from 'vscode/vscode/vs/workbench/services/extensions/common/extensionRunningLocation';
|
|
34
38
|
import { IExtensionService } from 'vscode/vscode/vs/workbench/services/extensions/common/extensions';
|
|
@@ -37,7 +41,7 @@ var AbstractRuntimeExtensionsEditor_1;
|
|
|
37
41
|
let AbstractRuntimeExtensionsEditor = class AbstractRuntimeExtensionsEditor extends EditorPane {
|
|
38
42
|
static { AbstractRuntimeExtensionsEditor_1 = this; }
|
|
39
43
|
static { this.ID = 'workbench.editor.runtimeExtensions'; }
|
|
40
|
-
constructor(telemetryService, themeService, contextKeyService, _extensionsWorkbenchService, _extensionService, _notificationService, _contextMenuService, _instantiationService, storageService, _labelService, _environmentService, _clipboardService) {
|
|
44
|
+
constructor(telemetryService, themeService, contextKeyService, _extensionsWorkbenchService, _extensionService, _notificationService, _contextMenuService, _instantiationService, storageService, _labelService, _environmentService, _clipboardService, _extensionFeaturesManagementService) {
|
|
41
45
|
super(AbstractRuntimeExtensionsEditor_1.ID, telemetryService, themeService, storageService);
|
|
42
46
|
this._extensionsWorkbenchService = _extensionsWorkbenchService;
|
|
43
47
|
this._extensionService = _extensionService;
|
|
@@ -47,10 +51,12 @@ let AbstractRuntimeExtensionsEditor = class AbstractRuntimeExtensionsEditor exte
|
|
|
47
51
|
this._labelService = _labelService;
|
|
48
52
|
this._environmentService = _environmentService;
|
|
49
53
|
this._clipboardService = _clipboardService;
|
|
54
|
+
this._extensionFeaturesManagementService = _extensionFeaturesManagementService;
|
|
50
55
|
this._list = null;
|
|
51
56
|
this._elements = null;
|
|
52
57
|
this._updateSoon = this._register(( new RunOnceScheduler(() => this._updateExtensions(), 200)));
|
|
53
58
|
this._register(this._extensionService.onDidChangeExtensionsStatus(() => this._updateSoon.schedule()));
|
|
59
|
+
this._register(this._extensionFeaturesManagementService.onDidChangeAccessData(() => this._updateSoon.schedule()));
|
|
54
60
|
this._updateExtensions();
|
|
55
61
|
}
|
|
56
62
|
async _updateExtensions() {
|
|
@@ -153,7 +159,7 @@ let AbstractRuntimeExtensionsEditor = class AbstractRuntimeExtensionsEditor exte
|
|
|
153
159
|
const name = append(header, $('div.name'));
|
|
154
160
|
const version = append(header, $('span.version'));
|
|
155
161
|
const msgContainer = append(desc, $('div.msg'));
|
|
156
|
-
const actionbar = ( new ActionBar(desc
|
|
162
|
+
const actionbar = ( new ActionBar(desc));
|
|
157
163
|
actionbar.onDidRun(({ error }) => error && this._notificationService.error(error));
|
|
158
164
|
const timeContainer = append(element, $('.time'));
|
|
159
165
|
const activationTime = append(timeContainer, $('div.activation-time'));
|
|
@@ -364,6 +370,34 @@ let AbstractRuntimeExtensionsEditor = class AbstractRuntimeExtensionsEditor exte
|
|
|
364
370
|
const el = $('span', undefined, ...renderLabelWithIcons(extraLabel));
|
|
365
371
|
data.msgContainer.appendChild(el);
|
|
366
372
|
}
|
|
373
|
+
const features = ( Registry.as(Extensions.ExtensionFeaturesRegistry)).getExtensionFeatures();
|
|
374
|
+
for (const feature of features) {
|
|
375
|
+
const accessData = this._extensionFeaturesManagementService.getAccessData(element.description.identifier, feature.id);
|
|
376
|
+
if (accessData) {
|
|
377
|
+
const status = accessData?.current?.status;
|
|
378
|
+
if (status) {
|
|
379
|
+
data.msgContainer.appendChild($('span', undefined, `${feature.label}: `));
|
|
380
|
+
data.msgContainer.appendChild($('span', undefined, ...renderLabelWithIcons(`$(${status.severity === Severity.Error ? errorIcon.id : warningIcon.id}) ${status.message}`)));
|
|
381
|
+
}
|
|
382
|
+
if (accessData?.current) {
|
|
383
|
+
const element = $('span', undefined, ( localizeWithPath(
|
|
384
|
+
'vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor',
|
|
385
|
+
'requests count',
|
|
386
|
+
"{0} Requests: {1} (Session)",
|
|
387
|
+
feature.label,
|
|
388
|
+
accessData.current.count
|
|
389
|
+
)));
|
|
390
|
+
element.title = ( localizeWithPath(
|
|
391
|
+
'vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor',
|
|
392
|
+
'requests count title',
|
|
393
|
+
"Last request was {0}. Overall Requests: {1}",
|
|
394
|
+
fromNow(accessData.current.lastAccessed, true, true),
|
|
395
|
+
accessData.totalCount
|
|
396
|
+
));
|
|
397
|
+
data.msgContainer.appendChild(element);
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
}
|
|
367
401
|
if (element.profileInfo) {
|
|
368
402
|
data.profileTime.textContent = `Profile: ${(element.profileInfo.totalTime / 1000).toFixed(2)}ms`;
|
|
369
403
|
}
|
|
@@ -463,17 +497,18 @@ AbstractRuntimeExtensionsEditor = AbstractRuntimeExtensionsEditor_1 = ( __decora
|
|
|
463
497
|
( __param(8, IStorageService)),
|
|
464
498
|
( __param(9, ILabelService)),
|
|
465
499
|
( __param(10, IWorkbenchEnvironmentService)),
|
|
466
|
-
( __param(11, IClipboardService))
|
|
500
|
+
( __param(11, IClipboardService)),
|
|
501
|
+
( __param(12, IExtensionFeaturesManagementService))
|
|
467
502
|
], AbstractRuntimeExtensionsEditor));
|
|
468
503
|
class ShowRuntimeExtensionsAction extends Action2 {
|
|
469
504
|
constructor() {
|
|
470
505
|
super({
|
|
471
506
|
id: 'workbench.action.showRuntimeExtensions',
|
|
472
|
-
title:
|
|
507
|
+
title: ( localize2WithPath(
|
|
473
508
|
'vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor',
|
|
474
509
|
'showRuntimeExtensions',
|
|
475
510
|
"Show Running Extensions"
|
|
476
|
-
)),
|
|
511
|
+
)),
|
|
477
512
|
category: Categories.Developer,
|
|
478
513
|
f1: true,
|
|
479
514
|
menu: {
|