Skip to content

Commit

Permalink
Merge pull request #128112 from microsoft/sandy081/1.58/fix128088
Browse files Browse the repository at this point in the history
Bulk install event for python extensions
  • Loading branch information
sandy081 authored Jul 7, 2021
2 parents 62fddf3 + df338a7 commit 2d23c42
Show file tree
Hide file tree
Showing 6 changed files with 42 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ export interface DidInstallExtensionEvent {
gallery?: IGalleryExtension;
local?: ILocalExtension;
error?: string;
isBulkInstall?: boolean;
}

export interface DidUninstallExtensionEvent {
Expand Down Expand Up @@ -213,6 +214,7 @@ export interface IExtensionManagementService {

onInstallExtension: Event<InstallExtensionEvent>;
onDidInstallExtension: Event<DidInstallExtensionEvent>;
onDidInstallExtensions: Event<DidInstallExtensionEvent[]>;
onUninstallExtension: Event<IExtensionIdentifier>;
onDidUninstallExtension: Event<DidUninstallExtensionEvent>;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,14 @@ export class ExtensionManagementChannel implements IServerChannel {

onInstallExtension: Event<InstallExtensionEvent>;
onDidInstallExtension: Event<DidInstallExtensionEvent>;
onDidInstallExtensions: Event<DidInstallExtensionEvent[]>;
onUninstallExtension: Event<IExtensionIdentifier>;
onDidUninstallExtension: Event<DidUninstallExtensionEvent>;

constructor(private service: IExtensionManagementService, private getUriTransformer: (requestContext: any) => IURITransformer | null) {
this.onInstallExtension = Event.buffer(service.onInstallExtension, true);
this.onDidInstallExtension = Event.buffer(service.onDidInstallExtension, true);
this.onDidInstallExtensions = Event.buffer(service.onDidInstallExtensions, true);
this.onUninstallExtension = Event.buffer(service.onUninstallExtension, true);
this.onDidUninstallExtension = Event.buffer(service.onDidUninstallExtension, true);
}
Expand All @@ -50,6 +52,7 @@ export class ExtensionManagementChannel implements IServerChannel {
switch (event) {
case 'onInstallExtension': return this.onInstallExtension;
case 'onDidInstallExtension': return Event.map(this.onDidInstallExtension, i => ({ ...i, local: i.local ? transformOutgoingExtension(i.local, uriTransformer) : i.local }));
case 'onDidInstallExtensions': return Event.map(this.onDidInstallExtensions, i => i.map(e => ({ ...e, local: e.local ? transformOutgoingExtension(e.local, uriTransformer) : e.local })));
case 'onUninstallExtension': return this.onUninstallExtension;
case 'onDidUninstallExtension': return this.onDidUninstallExtension;
}
Expand Down Expand Up @@ -88,6 +91,9 @@ export class ExtensionManagementChannelClient extends Disposable implements IExt
private readonly _onDidInstallExtension = this._register(new Emitter<DidInstallExtensionEvent>());
readonly onDidInstallExtension = this._onDidInstallExtension.event;

private readonly _onDidInstallExtensions = this._register(new Emitter<DidInstallExtensionEvent[]>());
readonly onDidInstallExtensions = this._onDidInstallExtensions.event;

private readonly _onUninstallExtension = this._register(new Emitter<IExtensionIdentifier>());
readonly onUninstallExtension = this._onUninstallExtension.event;

Expand All @@ -100,6 +106,7 @@ export class ExtensionManagementChannelClient extends Disposable implements IExt
super();
this._register(this.channel.listen<InstallExtensionEvent>('onInstallExtension')(e => this._onInstallExtension.fire(e)));
this._register(this.channel.listen<DidInstallExtensionEvent>('onDidInstallExtension')(e => this._onDidInstallExtension.fire({ ...e, local: e.local ? transformIncomingExtension(e.local, null) : e.local })));
this._register(this.channel.listen<DidInstallExtensionEvent[]>('onDidInstallExtensions')(e => this._onDidInstallExtensions.fire(e.map(event => ({ ...event, local: event.local ? transformIncomingExtension(event.local, null) : event.local })))));
this._register(this.channel.listen<IExtensionIdentifier>('onUninstallExtension')(e => this._onUninstallExtension.fire(e)));
this._register(this.channel.listen<DidUninstallExtensionEvent>('onDidUninstallExtension')(e => this._onDidUninstallExtension.fire(e)));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ export class ExtensionManagementService extends Disposable implements IExtension
private readonly _onDidInstallExtension = this._register(new Emitter<DidInstallExtensionEvent>());
readonly onDidInstallExtension: Event<DidInstallExtensionEvent> = this._onDidInstallExtension.event;

private readonly _onDidInstallExtensions = this._register(new Emitter<DidInstallExtensionEvent[]>());
readonly onDidInstallExtensions = this._onDidInstallExtensions.event;

private readonly _onUninstallExtension = this._register(new Emitter<IExtensionIdentifier>());
readonly onUninstallExtension: Event<IExtensionIdentifier> = this._onUninstallExtension.event;

Expand Down Expand Up @@ -294,12 +297,13 @@ export class ExtensionManagementService extends Disposable implements IExtension
this.logService.info('Extensions is already requested to install', extension.identifier.id);
return (await installExtensionTask.resultPromise).local;
} else {
installExtensionTask = this.createInstallFromGalleryExtensionTask(extension, options);
return (await this.runInstallGalleryExtensionTask(installExtensionTask, options)).local;
const isBulkInstall = ['ms-python.python', 'ms-python.vscode-pylance'].includes(extension.identifier.id.toLowerCase());
installExtensionTask = this.createInstallFromGalleryExtensionTask(extension, options, isBulkInstall);
return (await this.runInstallGalleryExtensionTask(installExtensionTask, options, isBulkInstall)).local;
}
}

private createInstallFromGalleryExtensionTask(extension: IGalleryExtension, options: InstallOptions): InstallExtensionTask {
private createInstallFromGalleryExtensionTask(extension: IGalleryExtension, options: InstallOptions, isBulkInstall: boolean): InstallExtensionTask {
const key = new ExtensionIdentifierWithVersion(extension.identifier, extension.version).key();
this._onInstallExtension.fire({ identifier: extension.identifier, gallery: extension });
this.logService.info('Installing extension:', extension.identifier.id);
Expand All @@ -315,7 +319,7 @@ export class ExtensionManagementService extends Disposable implements IExtension
try {
const result = await this.installGalleryExtension(extension, options, token);
this.logService.info(`Extensions installed successfully:`, extension.identifier.id);
this._onDidInstallExtension.fire({ identifier: extension.identifier, gallery: result.gallery, local: result.local, operation: result.operation });
this._onDidInstallExtension.fire({ identifier: extension.identifier, gallery: result.gallery, local: result.local, operation: result.operation, isBulkInstall });
return result;
} catch (error) {
const errorCode = error && (<ExtensionManagementError>error).code ? (<ExtensionManagementError>error).code : ERROR_UNKNOWN;
Expand Down Expand Up @@ -344,7 +348,7 @@ export class ExtensionManagementService extends Disposable implements IExtension
return installExtensionTask;
}

private async runInstallGalleryExtensionTask(installExtensionTask: InstallExtensionTask, options: InstallOptions): Promise<InstallResult> {
private async runInstallGalleryExtensionTask(installExtensionTask: InstallExtensionTask, options: InstallOptions, isBulkInstall: boolean): Promise<InstallResult> {
if (options.donotIncludePackAndDependencies) {
this.logService.info('Installing the extension without checking dependencies and pack', installExtensionTask.extension.identifier.id);
return installExtensionTask.run();
Expand All @@ -369,7 +373,7 @@ export class ExtensionManagementService extends Disposable implements IExtension
if (this.installingExtensions.has(new ExtensionIdentifierWithVersion(gallery.identifier, gallery.version).key())) {
this.logService.info('Extension is already requested to install', gallery.identifier.id);
} else {
const task = this.createInstallFromGalleryExtensionTask(gallery, { ...options, donotIncludePackAndDependencies: true });
const task = this.createInstallFromGalleryExtensionTask(gallery, { ...options, donotIncludePackAndDependencies: true }, isBulkInstall);
extensionsToInstallMap.set(gallery.identifier.id.toLowerCase(), { task, manifest });
}
}
Expand Down Expand Up @@ -405,6 +409,10 @@ export class ExtensionManagementService extends Disposable implements IExtension
installExtensionTask.cancel();
}
throw error;
} finally {
if (installResults.length && isBulkInstall) {
this._onDidInstallExtensions.fire(installResults.map(({ gallery, local, operation }) => ({ identifier: local.identifier, gallery, local, operation })));
}
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import { Event, EventMultiplexer } from 'vs/base/common/event';
import {
ILocalExtension, IGalleryExtension, IExtensionIdentifier, IReportedExtension, IGalleryMetadata, IExtensionGalleryService, InstallOptions, UninstallOptions, INSTALL_ERROR_NOT_SUPPORTED, InstallVSIXOptions
ILocalExtension, IGalleryExtension, IExtensionIdentifier, IReportedExtension, IGalleryMetadata, IExtensionGalleryService, InstallOptions, UninstallOptions, INSTALL_ERROR_NOT_SUPPORTED, InstallVSIXOptions, DidInstallExtensionEvent
} from 'vs/platform/extensionManagement/common/extensionManagement';
import { DidInstallExtensionOnServerEvent, DidUninstallExtensionOnServerEvent, IExtensionManagementServer, IExtensionManagementServerService, InstallExtensionOnServerEvent, IWorkbenchExtensionManagementService, UninstallExtensionOnServerEvent } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
import { ExtensionType, isLanguagePackExtension, IExtensionManifest } from 'vs/platform/extensions/common/extensions';
Expand Down Expand Up @@ -35,6 +35,7 @@ export class ExtensionManagementService extends Disposable implements IWorkbench
readonly onDidInstallExtension: Event<DidInstallExtensionOnServerEvent>;
readonly onUninstallExtension: Event<UninstallExtensionOnServerEvent>;
readonly onDidUninstallExtension: Event<DidUninstallExtensionOnServerEvent>;
readonly onDidInstallExtensions: Event<DidInstallExtensionEvent[]>;

protected readonly servers: IExtensionManagementServer[] = [];

Expand Down Expand Up @@ -63,6 +64,7 @@ export class ExtensionManagementService extends Disposable implements IWorkbench

this.onInstallExtension = this._register(this.servers.reduce((emitter: EventMultiplexer<InstallExtensionOnServerEvent>, server) => { emitter.add(Event.map(server.extensionManagementService.onInstallExtension, e => ({ ...e, server }))); return emitter; }, new EventMultiplexer<InstallExtensionOnServerEvent>())).event;
this.onDidInstallExtension = this._register(this.servers.reduce((emitter: EventMultiplexer<DidInstallExtensionOnServerEvent>, server) => { emitter.add(Event.map(server.extensionManagementService.onDidInstallExtension, e => ({ ...e, server }))); return emitter; }, new EventMultiplexer<DidInstallExtensionOnServerEvent>())).event;
this.onDidInstallExtensions = this._register(this.servers.reduce((emitter: EventMultiplexer<DidInstallExtensionEvent[]>, server) => { emitter.add(server.extensionManagementService.onDidInstallExtensions); return emitter; }, new EventMultiplexer<DidInstallExtensionEvent[]>())).event;
this.onUninstallExtension = this._register(this.servers.reduce((emitter: EventMultiplexer<UninstallExtensionOnServerEvent>, server) => { emitter.add(Event.map(server.extensionManagementService.onUninstallExtension, e => ({ ...e, server }))); return emitter; }, new EventMultiplexer<UninstallExtensionOnServerEvent>())).event;
this.onDidUninstallExtension = this._register(this.servers.reduce((emitter: EventMultiplexer<DidUninstallExtensionOnServerEvent>, server) => { emitter.add(Event.map(server.extensionManagementService.onDidUninstallExtension, e => ({ ...e, server }))); return emitter; }, new EventMultiplexer<DidUninstallExtensionOnServerEvent>())).event;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ export class WebExtensionManagementService extends Disposable implements IExtens
private readonly _onDidInstallExtension = this._register(new Emitter<DidInstallExtensionEvent>());
readonly onDidInstallExtension: Event<DidInstallExtensionEvent> = this._onDidInstallExtension.event;

private readonly _onDidInstallExtensions = this._register(new Emitter<DidInstallExtensionEvent[]>());
readonly onDidInstallExtensions = this._onDidInstallExtensions.event;

private readonly _onUninstallExtension = this._register(new Emitter<IExtensionIdentifier>());
readonly onUninstallExtension: Event<IExtensionIdentifier> = this._onUninstallExtension.event;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -222,14 +222,26 @@ export abstract class AbstractExtensionService extends Disposable implements IEx
}));

this._register(this._extensionManagementService.onDidInstallExtension((event) => {
if (event.local) {
if (event.local && !event.isBulkInstall) {
if (this._safeInvokeIsEnabled(event.local)) {
// an extension has been installed
this._handleDeltaExtensions(new DeltaExtensionsQueueItem([event.local], []));
}
}
}));

this._register(this._extensionManagementService.onDidInstallExtensions((events) => {
const extensions: IExtension[] = [];
for (const { local } of events) {
if (local && this._safeInvokeIsEnabled(local)) {
extensions.push(local);
}
}
if (extensions.length) {
this._handleDeltaExtensions(new DeltaExtensionsQueueItem(extensions, []));
}
}));

this._register(this._extensionManagementService.onDidUninstallExtension((event) => {
if (!event.error) {
// an extension has been uninstalled
Expand Down

0 comments on commit 2d23c42

Please sign in to comment.