Skip to content

Commit 48cd8e0

Browse files
authored
1 parent 5be539a commit 48cd8e0

File tree

3 files changed

+70
-27
lines changed

3 files changed

+70
-27
lines changed

src/vs/workbench/services/extensionManagement/common/extensionManagementService.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -560,7 +560,19 @@ export class ExtensionManagementService extends Disposable implements IWorkbench
560560
await Promise.allSettled(this.servers.map(server => server.extensionManagementService.cleanUp()));
561561
}
562562

563+
copyExtensions(from: URI, to: URI): Promise<void> {
564+
if (this.extensionManagementServerService.remoteExtensionManagementServer) {
565+
throw new Error('Not Supported');
566+
}
567+
if (this.extensionManagementServerService.localExtensionManagementServer) {
568+
return this.extensionManagementServerService.localExtensionManagementServer.extensionManagementService.copyExtensions(from, to);
569+
}
570+
if (this.extensionManagementServerService.webExtensionManagementServer) {
571+
return this.extensionManagementServerService.webExtensionManagementServer.extensionManagementService.copyExtensions(from, to);
572+
}
573+
return Promise.resolve();
574+
}
575+
563576
registerParticipant() { throw new Error('Not Supported'); }
564-
copyExtensions(): Promise<void> { throw new Error('Not Supported'); }
565577
installExtensionsFromProfile(extensions: IExtensionIdentifier[], fromProfileLocation: URI, toProfileLocation: URI): Promise<ILocalExtension[]> { throw new Error('Not Supported'); }
566578
}

src/vs/workbench/services/userDataProfile/browser/extensionsResource.ts

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { localize } from 'vs/nls';
99
import { GlobalExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionEnablementService';
1010
import { EXTENSION_INSTALL_SKIP_WALKTHROUGH_CONTEXT, IExtensionGalleryService, IExtensionIdentifier, IExtensionManagementService, IGlobalExtensionEnablementService, ILocalExtension, InstallExtensionInfo } from 'vs/platform/extensionManagement/common/extensionManagement';
1111
import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
12+
import { ExtensionType } from 'vs/platform/extensions/common/extensions';
1213
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
1314
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
1415
import { ILogService } from 'vs/platform/log/common/log';
@@ -96,7 +97,6 @@ export class ExtensionsResourceInitializer implements IProfileResourceInitialize
9697
export class ExtensionsResource implements IProfileResource {
9798

9899
constructor(
99-
private readonly extensionsDisabled: boolean,
100100
@IExtensionManagementService private readonly extensionManagementService: IExtensionManagementService,
101101
@IExtensionGalleryService private readonly extensionGalleryService: IExtensionGalleryService,
102102
@IUserDataProfileStorageService private readonly userDataProfileStorageService: IUserDataProfileStorageService,
@@ -178,6 +178,20 @@ export class ExtensionsResource implements IProfileResource {
178178
});
179179
}
180180

181+
async copy(from: IUserDataProfile, to: IUserDataProfile, disableExtensions: boolean): Promise<void> {
182+
await this.extensionManagementService.copyExtensions(from.extensionsResource, to.extensionsResource);
183+
const extensionsToDisable = await this.withProfileScopedServices(from, async (extensionEnablementService) =>
184+
extensionEnablementService.getDisabledExtensions());
185+
if (disableExtensions) {
186+
const extensions = await this.extensionManagementService.getInstalled(ExtensionType.User, to.extensionsResource);
187+
for (const extension of extensions) {
188+
extensionsToDisable.push(extension.identifier);
189+
}
190+
}
191+
await this.withProfileScopedServices(to, async (extensionEnablementService) =>
192+
Promise.all(extensionsToDisable.map(extension => extensionEnablementService.disableExtension(extension))));
193+
}
194+
181195
async getLocalExtensions(profile: IUserDataProfile): Promise<IProfileExtension[]> {
182196
return this.withProfileScopedServices(profile, async (extensionEnablementService) => {
183197
const result: Array<IProfileExtension & { displayName?: string }> = [];
@@ -197,7 +211,7 @@ export class ExtensionsResource implements IProfileResource {
197211
}
198212
}
199213
const profileExtension: IProfileExtension = { identifier, displayName: extension.manifest.displayName };
200-
if (this.extensionsDisabled || disabled) {
214+
if (disabled) {
201215
profileExtension.disabled = true;
202216
}
203217
if (!extension.isBuiltin && extension.pinned) {
@@ -285,7 +299,6 @@ export class ExtensionsResourceExportTreeItem extends ExtensionsResourceTreeItem
285299

286300
constructor(
287301
private readonly profile: IUserDataProfile,
288-
private readonly extensionsDisabled: boolean,
289302
@IInstantiationService private readonly instantiationService: IInstantiationService,
290303
) {
291304
super();
@@ -296,11 +309,11 @@ export class ExtensionsResourceExportTreeItem extends ExtensionsResourceTreeItem
296309
}
297310

298311
protected getExtensions(): Promise<IProfileExtension[]> {
299-
return this.instantiationService.createInstance(ExtensionsResource, this.extensionsDisabled).getLocalExtensions(this.profile);
312+
return this.instantiationService.createInstance(ExtensionsResource).getLocalExtensions(this.profile);
300313
}
301314

302315
async getContent(): Promise<string> {
303-
return this.instantiationService.createInstance(ExtensionsResource, this.extensionsDisabled).getContent(this.profile, [...this.excludedExtensions.values()]);
316+
return this.instantiationService.createInstance(ExtensionsResource).getContent(this.profile, [...this.excludedExtensions.values()]);
304317
}
305318

306319
}
@@ -319,11 +332,11 @@ export class ExtensionsResourceImportTreeItem extends ExtensionsResourceTreeItem
319332
}
320333

321334
protected getExtensions(): Promise<IProfileExtension[]> {
322-
return this.instantiationService.createInstance(ExtensionsResource, false).getProfileExtensions(this.content);
335+
return this.instantiationService.createInstance(ExtensionsResource).getProfileExtensions(this.content);
323336
}
324337

325338
async getContent(): Promise<string> {
326-
const extensionsResource = this.instantiationService.createInstance(ExtensionsResource, false);
339+
const extensionsResource = this.instantiationService.createInstance(ExtensionsResource);
327340
const extensions = await extensionsResource.getProfileExtensions(this.content);
328341
return extensionsResource.toContent(extensions, [...this.excludedExtensions.values()]);
329342
}

src/vs/workbench/services/userDataProfile/browser/userDataProfileImportExportService.ts

Lines changed: 37 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ export class UserDataProfileImportExportService extends Disposable implements IU
225225
}
226226
const disposables = new DisposableStore();
227227
try {
228-
const userDataProfilesExportState = disposables.add(this.instantiationService.createInstance(UserDataProfileExportState, this.userDataProfileService.currentProfile, false));
228+
const userDataProfilesExportState = disposables.add(this.instantiationService.createInstance(UserDataProfileExportState, this.userDataProfileService.currentProfile));
229229
const barrier = new Barrier();
230230
const exportAction = new BarrierAction(barrier, new Action('export', localize('export', "Export"), undefined, true, async () => {
231231
exportAction.enabled = false;
@@ -247,7 +247,7 @@ export class UserDataProfileImportExportService extends Disposable implements IU
247247
}
248248

249249
async createFromCurrentProfile(name: string): Promise<void> {
250-
const userDataProfilesExportState = this.instantiationService.createInstance(UserDataProfileExportState, this.userDataProfileService.currentProfile, false);
250+
const userDataProfilesExportState = this.instantiationService.createInstance(UserDataProfileExportState, this.userDataProfileService.currentProfile);
251251
try {
252252
const profileTemplate = await userDataProfilesExportState.getProfileTemplate(name, undefined);
253253
await this.doImportProfile(profileTemplate);
@@ -257,15 +257,24 @@ export class UserDataProfileImportExportService extends Disposable implements IU
257257
}
258258

259259
async createTroubleshootProfile(): Promise<void> {
260-
const userDataProfilesExportState = this.instantiationService.createInstance(UserDataProfileExportState, this.userDataProfileService.currentProfile, true);
260+
const userDataProfilesExportState = this.instantiationService.createInstance(UserDataProfileExportState, this.userDataProfileService.currentProfile);
261261
try {
262262
const profileTemplate = await userDataProfilesExportState.getProfileTemplate(localize('troubleshoot issue', "Troubleshoot Issue"), undefined);
263263
await this.progressService.withProgress({
264264
location: ProgressLocation.Notification,
265265
delay: 1000,
266266
sticky: true,
267-
}, progress =>
268-
this.importAndSwitchWithProgress(profileTemplate, true, true, true, message => progress.report({ message: localize('troubleshoot profile progress', "Setting up Troubleshoot Profile: {0}", message) })));
267+
}, async progress => {
268+
const reportProgress = (message: string) => progress.report({ message: localize('troubleshoot profile progress', "Setting up Troubleshoot Profile: {0}", message) });
269+
const profile = await this.importWithProgress(profileTemplate, true, false, reportProgress);
270+
if (profile) {
271+
reportProgress(localize('progress extensions', "Applying Extensions..."));
272+
await this.instantiationService.createInstance(ExtensionsResource).copy(this.userDataProfileService.currentProfile, profile, true);
273+
274+
reportProgress(localize('switching profile', "Switching Profile..."));
275+
await this.userDataProfileManagementService.switchProfile(profile);
276+
}
277+
});
269278
} finally {
270279
userDataProfilesExportState.dispose();
271280
}
@@ -357,7 +366,7 @@ export class UserDataProfileImportExportService extends Disposable implements IU
357366
const userDataProfileImportState = disposables.add(this.instantiationService.createInstance(UserDataProfileImportState, profileTemplate));
358367
profileTemplate = await userDataProfileImportState.getProfileTemplateToImport();
359368

360-
const importedProfile = await this.importAndSwitch(profileTemplate, true, false, false, localize('preview profile', "Preview Profile"));
369+
const importedProfile = await this.importAndSwitch(profileTemplate, true, false, localize('preview profile', "Preview Profile"));
361370

362371
if (!importedProfile) {
363372
return;
@@ -400,15 +409,15 @@ export class UserDataProfileImportExportService extends Disposable implements IU
400409
view.setMessage(undefined);
401410
const profileTemplate = await userDataProfileImportState.getProfileTemplateToImport();
402411
if (profileTemplate.extensions) {
403-
await that.instantiationService.createInstance(ExtensionsResource, false).apply(profileTemplate.extensions, importedProfile);
412+
await that.instantiationService.createInstance(ExtensionsResource).apply(profileTemplate.extensions, importedProfile);
404413
}
405414
});
406415
}
407416
}));
408417
disposables.add(Event.debounce(this.extensionManagementService.onDidInstallExtensions, () => undefined, 100)(async () => {
409418
const profileTemplate = await userDataProfileImportState.getProfileTemplateToImport();
410419
if (profileTemplate.extensions) {
411-
const profileExtensions = await that.instantiationService.createInstance(ExtensionsResource, false).getProfileExtensions(profileTemplate.extensions!);
420+
const profileExtensions = await that.instantiationService.createInstance(ExtensionsResource).getProfileExtensions(profileTemplate.extensions!);
412421
const installed = await this.extensionManagementService.getInstalled(ExtensionType.User);
413422
if (profileExtensions.every(e => installed.some(i => areSameExtensions(e.identifier, i.identifier)))) {
414423
disposable.dispose();
@@ -447,7 +456,7 @@ export class UserDataProfileImportExportService extends Disposable implements IU
447456
const importProfileFn = async () => {
448457
importAction.enabled = false;
449458
const profileTemplate = await userDataProfileImportState.getProfileTemplateToImport();
450-
const importedProfile = await this.importAndSwitch(profileTemplate, false, true, false, title);
459+
const importedProfile = await this.importAndSwitch(profileTemplate, false, true, title);
451460
if (!importedProfile) {
452461
return;
453462
}
@@ -463,17 +472,29 @@ export class UserDataProfileImportExportService extends Disposable implements IU
463472
return importAction;
464473
}
465474

466-
private async importAndSwitch(profileTemplate: IUserDataProfileTemplate, temporaryProfile: boolean, extensions: boolean, extensionsDisabled: boolean, title: string): Promise<IUserDataProfile | undefined> {
475+
private async importAndSwitch(profileTemplate: IUserDataProfileTemplate, temporaryProfile: boolean, extensions: boolean, title: string): Promise<IUserDataProfile | undefined> {
467476
return this.progressService.withProgress({
468477
location: ProgressLocation.Window,
469478
command: showWindowLogActionId,
470479
}, async (progress) => {
471480
progress.report({ message: localize('Importing profile', "{0} ({1})...", title, profileTemplate.name) });
472-
return this.importAndSwitchWithProgress(profileTemplate, temporaryProfile, extensions, extensionsDisabled, message => progress.report({ message: `${title} (${profileTemplate.name}): ${message}` }));
481+
return this.importAndSwitchWithProgress(profileTemplate, temporaryProfile, extensions, message => progress.report({ message: `${title} (${profileTemplate.name}): ${message}` }));
473482
});
474483
}
475484

476-
private async importAndSwitchWithProgress(profileTemplate: IUserDataProfileTemplate, temporaryProfile: boolean, extensions: boolean, extensionsDisabled: boolean, progress: (message: string) => void): Promise<IUserDataProfile | undefined> {
485+
private async importAndSwitchWithProgress(profileTemplate: IUserDataProfileTemplate, temporaryProfile: boolean, extensions: boolean, progress: (message: string) => void): Promise<IUserDataProfile | undefined> {
486+
const profile = await this.importWithProgress(profileTemplate, temporaryProfile, extensions, progress);
487+
488+
if (!profile) {
489+
return;
490+
}
491+
492+
progress(localize('switching profile', "Switching Profile..."));
493+
await this.userDataProfileManagementService.switchProfile(profile);
494+
return profile;
495+
}
496+
497+
private async importWithProgress(profileTemplate: IUserDataProfileTemplate, temporaryProfile: boolean, extensions: boolean, progress: (message: string) => void): Promise<IUserDataProfile | undefined> {
477498
const profile = await this.getProfileToImport(profileTemplate, temporaryProfile);
478499
if (!profile) {
479500
return undefined;
@@ -484,7 +505,7 @@ export class UserDataProfileImportExportService extends Disposable implements IU
484505
await this.instantiationService.createInstance(SettingsResource).apply(profileTemplate.settings, profile);
485506
}
486507
if (profileTemplate.keybindings) {
487-
progress(localize('progress keybindings', "{0}ying Keyboard Shortcuts..."));
508+
progress(localize('progress keybindings', "Applying Keyboard Shortcuts..."));
488509
await this.instantiationService.createInstance(KeybindingsResource).apply(profileTemplate.keybindings, profile);
489510
}
490511
if (profileTemplate.tasks) {
@@ -501,11 +522,9 @@ export class UserDataProfileImportExportService extends Disposable implements IU
501522
}
502523
if (profileTemplate.extensions && extensions) {
503524
progress(localize('progress extensions', "Applying Extensions..."));
504-
await this.instantiationService.createInstance(ExtensionsResource, extensionsDisabled).apply(profileTemplate.extensions, profile);
525+
await this.instantiationService.createInstance(ExtensionsResource).apply(profileTemplate.extensions, profile);
505526
}
506527

507-
progress(localize('switching profile', " Applying..."));
508-
await this.userDataProfileManagementService.switchProfile(profile);
509528
return profile;
510529
}
511530

@@ -685,7 +704,7 @@ export class UserDataProfileImportExportService extends Disposable implements IU
685704
await this.instantiationService.createInstance(GlobalStateResource).apply(profile.globalState, this.userDataProfileService.currentProfile);
686705
}
687706
if (profile.extensions) {
688-
await this.instantiationService.createInstance(ExtensionsResource, false).apply(profile.extensions, this.userDataProfileService.currentProfile);
707+
await this.instantiationService.createInstance(ExtensionsResource).apply(profile.extensions, this.userDataProfileService.currentProfile);
689708
}
690709
});
691710
this.notificationService.info(localize('applied profile', "{0}: Applied successfully.", PROFILES_CATEGORY.value));
@@ -979,7 +998,6 @@ class UserDataProfileExportState extends UserDataProfileImportExportState {
979998

980999
constructor(
9811000
readonly profile: IUserDataProfile,
982-
private readonly disableExtensions: boolean,
9831001
@IQuickInputService quickInputService: IQuickInputService,
9841002
@IFileService private readonly fileService: IFileService,
9851003
@IInstantiationService private readonly instantiationService: IInstantiationService
@@ -1035,7 +1053,7 @@ class UserDataProfileExportState extends UserDataProfileImportExportState {
10351053
roots.push(globalStateResourceTreeItem);
10361054
}
10371055

1038-
const extensionsResourceTreeItem = this.instantiationService.createInstance(ExtensionsResourceExportTreeItem, exportPreviewProfle, this.disableExtensions);
1056+
const extensionsResourceTreeItem = this.instantiationService.createInstance(ExtensionsResourceExportTreeItem, exportPreviewProfle);
10391057
if (await extensionsResourceTreeItem.hasContent()) {
10401058
roots.push(extensionsResourceTreeItem);
10411059
}

0 commit comments

Comments
 (0)