Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

prepare for syncing profiles #160298

Merged
merged 2 commits into from Sep 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -5,7 +5,7 @@

import { Disposable, DisposableStore, MutableDisposable, toDisposable } from 'vs/base/common/lifecycle';
import { URI } from 'vs/base/common/uri';
import { IExtensionGalleryService, IExtensionIdentifier, IGlobalExtensionEnablementService, ServerDidUninstallExtensionEvent, ServerInstallExtensionResult, UninstallOptions } from 'vs/platform/extensionManagement/common/extensionManagement';
import { IExtensionGalleryService, IExtensionIdentifier, IGlobalExtensionEnablementService, DidUninstallExtensionEvent, InstallExtensionResult, UninstallOptions } from 'vs/platform/extensionManagement/common/extensionManagement';
import { getIdAndVersion } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
import { IExtensionsProfileScannerService } from 'vs/platform/extensionManagement/common/extensionsProfileScannerService';
import { ExtensionStorageService, IExtensionStorageService } from 'vs/platform/extensionManagement/common/extensionStorage';
Expand Down Expand Up @@ -102,7 +102,7 @@ class ProfileExtensionsCleaner extends Disposable {
}
}

private async onDidInstallExtensions(installedExtensions: readonly ServerInstallExtensionResult[]): Promise<void> {
private async onDidInstallExtensions(installedExtensions: readonly InstallExtensionResult[]): Promise<void> {
for (const { local, profileLocation } of installedExtensions) {
if (!local || !profileLocation) {
continue;
Expand All @@ -111,7 +111,7 @@ class ProfileExtensionsCleaner extends Disposable {
}
}

private async onDidUninstallExtension(e: ServerDidUninstallExtensionEvent): Promise<void> {
private async onDidUninstallExtension(e: DidUninstallExtensionEvent): Promise<void> {
if (!e.profileLocation || !e.version) {
return;
}
Expand Down
Expand Up @@ -14,8 +14,8 @@ import { URI } from 'vs/base/common/uri';
import * as nls from 'vs/nls';
import {
ExtensionManagementError, IExtensionGalleryService, IExtensionIdentifier, IExtensionManagementParticipant, IGalleryExtension, IGalleryMetadata, ILocalExtension, InstallOperation,
IExtensionsControlManifest, StatisticType, isTargetPlatformCompatible, TargetPlatformToString, ExtensionManagementErrorCode, IServerExtensionManagementService,
ServerInstallOptions, ServerInstallVSIXOptions, ServerUninstallOptions, Metadata, ServerInstallExtensionEvent, ServerInstallExtensionResult, ServerUninstallExtensionEvent, ServerDidUninstallExtensionEvent
IExtensionsControlManifest, StatisticType, isTargetPlatformCompatible, TargetPlatformToString, ExtensionManagementErrorCode,
InstallOptions, InstallVSIXOptions, UninstallOptions, Metadata, InstallExtensionEvent, DidUninstallExtensionEvent, InstallExtensionResult, UninstallExtensionEvent, IExtensionManagementService
} from 'vs/platform/extensionManagement/common/extensionManagement';
import { areSameExtensions, ExtensionKey, getGalleryExtensionTelemetryData, getLocalExtensionTelemetryData } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
import { ExtensionType, IExtensionManifest, isApplicationScopedExtension, TargetPlatform } from 'vs/platform/extensions/common/extensions';
Expand All @@ -40,7 +40,7 @@ export interface IUninstallExtensionTask {
cancel(): void;
}

export abstract class AbstractExtensionManagementService extends Disposable implements IServerExtensionManagementService {
export abstract class AbstractExtensionManagementService extends Disposable implements IExtensionManagementService {

declare readonly _serviceBrand: undefined;

Expand All @@ -49,16 +49,16 @@ export abstract class AbstractExtensionManagementService extends Disposable impl
private readonly installingExtensions = new Map<string, { task: IInstallExtensionTask; waitingTasks: IInstallExtensionTask[] }>();
private readonly uninstallingExtensions = new Map<string, IUninstallExtensionTask>();

private readonly _onInstallExtension = this._register(new Emitter<ServerInstallExtensionEvent>());
private readonly _onInstallExtension = this._register(new Emitter<InstallExtensionEvent>());
readonly onInstallExtension = this._onInstallExtension.event;

protected readonly _onDidInstallExtensions = this._register(new Emitter<ServerInstallExtensionResult[]>());
protected readonly _onDidInstallExtensions = this._register(new Emitter<InstallExtensionResult[]>());
readonly onDidInstallExtensions = this._onDidInstallExtensions.event;

protected readonly _onUninstallExtension = this._register(new Emitter<ServerUninstallExtensionEvent>());
protected readonly _onUninstallExtension = this._register(new Emitter<UninstallExtensionEvent>());
readonly onUninstallExtension = this._onUninstallExtension.event;

protected _onDidUninstallExtension = this._register(new Emitter<ServerDidUninstallExtensionEvent>());
protected _onDidUninstallExtension = this._register(new Emitter<DidUninstallExtensionEvent>());
readonly onDidUninstallExtension = this._onDidUninstallExtension.event;

private readonly participants: IExtensionManagementParticipant[] = [];
Expand All @@ -84,7 +84,7 @@ export abstract class AbstractExtensionManagementService extends Disposable impl
return extension.allTargetPlatforms.some(targetPlatform => isTargetPlatformCompatible(targetPlatform, extension.allTargetPlatforms, currentTargetPlatform));
}

async installFromGallery(extension: IGalleryExtension, options: ServerInstallOptions = {}): Promise<ILocalExtension> {
async installFromGallery(extension: IGalleryExtension, options: InstallOptions = {}): Promise<ILocalExtension> {
try {
if (!this.galleryService.isEnabled()) {
throw new ExtensionManagementError(nls.localize('MarketPlaceDisabled', "Marketplace is not enabled"), ExtensionManagementErrorCode.Internal);
Expand All @@ -99,7 +99,7 @@ export abstract class AbstractExtensionManagementService extends Disposable impl
}
}

async uninstall(extension: ILocalExtension, options: ServerUninstallOptions = {}): Promise<void> {
async uninstall(extension: ILocalExtension, options: UninstallOptions = {}): Promise<void> {
this.logService.trace('ExtensionManagementService#uninstall', extension.identifier.id);
return this.uninstallExtension(extension, options);
}
Expand Down Expand Up @@ -135,7 +135,7 @@ export abstract class AbstractExtensionManagementService extends Disposable impl
this.participants.push(participant);
}

protected async installExtension(manifest: IExtensionManifest, extension: URI | IGalleryExtension, options: ServerInstallOptions & ServerInstallVSIXOptions): Promise<ILocalExtension> {
protected async installExtension(manifest: IExtensionManifest, extension: URI | IGalleryExtension, options: InstallOptions & InstallVSIXOptions): Promise<ILocalExtension> {

const getInstallExtensionTaskKey = (extension: IGalleryExtension) => `${ExtensionKey.create(extension).toString()}${options.profileLocation ? `-${options.profileLocation.toString()}` : ''}`;

Expand All @@ -152,7 +152,7 @@ export abstract class AbstractExtensionManagementService extends Disposable impl

const allInstallExtensionTasks: { task: IInstallExtensionTask; manifest: IExtensionManifest }[] = [];
const alreadyRequestedInstallations: Promise<void>[] = [];
const installResults: (ServerInstallExtensionResult & { local: ILocalExtension })[] = [];
const installResults: (InstallExtensionResult & { local: ILocalExtension })[] = [];
const installExtensionTask = this.createInstallExtensionTask(manifest, extension, options);
if (!URI.isUri(extension)) {
this.installingExtensions.set(getInstallExtensionTaskKey(extension), { task: installExtensionTask, waitingTasks: [] });
Expand Down Expand Up @@ -467,15 +467,15 @@ export abstract class AbstractExtensionManagementService extends Disposable impl
return compatibleExtension;
}

private async uninstallExtension(extension: ILocalExtension, options: ServerUninstallOptions): Promise<void> {
private async uninstallExtension(extension: ILocalExtension, options: UninstallOptions): Promise<void> {
const getUninstallExtensionTaskKey = (identifier: IExtensionIdentifier) => `${identifier.id.toLowerCase()}${options.versionOnly ? `-${extension.manifest.version}` : ''}${options.profileLocation ? `@${options.profileLocation.toString()}` : ''}`;
const uninstallExtensionTask = this.uninstallingExtensions.get(getUninstallExtensionTaskKey(extension.identifier));
if (uninstallExtensionTask) {
this.logService.info('Extensions is already requested to uninstall', extension.identifier.id);
return uninstallExtensionTask.waitUntilTaskIsFinished();
}

const createUninstallExtensionTask = (extension: ILocalExtension, uninstallOptions: ServerUninstallOptions): IUninstallExtensionTask => {
const createUninstallExtensionTask = (extension: ILocalExtension, uninstallOptions: UninstallOptions): IUninstallExtensionTask => {
const uninstallExtensionTask = this.createUninstallExtensionTask(extension, uninstallOptions);
this.uninstallingExtensions.set(getUninstallExtensionTaskKey(uninstallExtensionTask.extension.identifier), uninstallExtensionTask);
if (options.profileLocation) {
Expand Down Expand Up @@ -645,14 +645,14 @@ export abstract class AbstractExtensionManagementService extends Disposable impl
}
}

private createInstallExtensionTask(manifest: IExtensionManifest, extension: URI | IGalleryExtension, options: ServerInstallOptions & ServerInstallVSIXOptions): IInstallExtensionTask {
private createInstallExtensionTask(manifest: IExtensionManifest, extension: URI | IGalleryExtension, options: InstallOptions & InstallVSIXOptions): IInstallExtensionTask {
if (options.profileLocation && isApplicationScopedExtension(manifest)) {
options = { ...options, profileLocation: this.userDataProfilesService.defaultProfile.extensionsResource };
}
return this.doCreateInstallExtensionTask(manifest, extension, options);
}

private createUninstallExtensionTask(extension: ILocalExtension, options: ServerUninstallOptions): IUninstallExtensionTask {
private createUninstallExtensionTask(extension: ILocalExtension, options: UninstallOptions): IUninstallExtensionTask {
if (options.profileLocation && extension.isApplicationScoped) {
options = { ...options, profileLocation: this.userDataProfilesService.defaultProfile.extensionsResource };
}
Expand All @@ -663,15 +663,15 @@ export abstract class AbstractExtensionManagementService extends Disposable impl
abstract zip(extension: ILocalExtension): Promise<URI>;
abstract unzip(zipLocation: URI): Promise<IExtensionIdentifier>;
abstract getManifest(vsix: URI): Promise<IExtensionManifest>;
abstract install(vsix: URI, options?: ServerInstallVSIXOptions): Promise<ILocalExtension>;
abstract install(vsix: URI, options?: InstallVSIXOptions): Promise<ILocalExtension>;
abstract getInstalled(type?: ExtensionType, profileLocation?: URI): Promise<ILocalExtension[]>;

abstract getMetadata(extension: ILocalExtension): Promise<Metadata | undefined>;
abstract updateMetadata(local: ILocalExtension, metadata: IGalleryMetadata): Promise<ILocalExtension>;
abstract updateExtensionScope(local: ILocalExtension, isMachineScoped: boolean): Promise<ILocalExtension>;

protected abstract doCreateInstallExtensionTask(manifest: IExtensionManifest, extension: URI | IGalleryExtension, options: ServerInstallOptions & ServerInstallVSIXOptions): IInstallExtensionTask;
protected abstract doCreateUninstallExtensionTask(extension: ILocalExtension, options: ServerUninstallOptions): IUninstallExtensionTask;
protected abstract doCreateInstallExtensionTask(manifest: IExtensionManifest, extension: URI | IGalleryExtension, options: InstallOptions & InstallVSIXOptions): IInstallExtensionTask;
protected abstract doCreateUninstallExtensionTask(extension: ILocalExtension, options: UninstallOptions): IUninstallExtensionTask;
}

export function joinErrors(errorOrErrors: (Error | string) | (Array<Error | string>)): Error {
Expand Down
43 changes: 15 additions & 28 deletions src/vs/platform/extensionManagement/common/extensionManagement.ts
Expand Up @@ -11,7 +11,7 @@ import { Platform } from 'vs/base/common/platform';
import { URI } from 'vs/base/common/uri';
import { localize } from 'vs/nls';
import { ExtensionType, IExtension, IExtensionManifest, TargetPlatform } from 'vs/platform/extensions/common/extensions';
import { createDecorator, refineServiceDecorator } from 'vs/platform/instantiation/common/instantiation';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';

export const EXTENSION_IDENTIFIER_PATTERN = '^([a-z0-9A-Z][a-z0-9-A-Z]*)\\.([a-z0-9A-Z][a-z0-9-A-Z]*)$';
export const EXTENSION_IDENTIFIER_REGEX = new RegExp(EXTENSION_IDENTIFIER_PATTERN);
Expand Down Expand Up @@ -344,8 +344,10 @@ export interface IExtensionGalleryService {
}

export interface InstallExtensionEvent {
identifier: IExtensionIdentifier;
source: URI | IGalleryExtension;
readonly identifier: IExtensionIdentifier;
readonly source: URI | IGalleryExtension;
readonly profileLocation?: URI;
readonly applicationScoped?: boolean;
}

export interface InstallExtensionResult {
Expand All @@ -354,16 +356,22 @@ export interface InstallExtensionResult {
readonly source?: URI | IGalleryExtension;
readonly local?: ILocalExtension;
readonly context?: IStringDictionary<any>;
readonly profileLocation?: URI;
readonly applicationScoped?: boolean;
}

export interface UninstallExtensionEvent {
identifier: IExtensionIdentifier;
readonly identifier: IExtensionIdentifier;
readonly profileLocation?: URI;
readonly applicationScoped?: boolean;
}

export interface DidUninstallExtensionEvent {
readonly identifier: IExtensionIdentifier;
readonly version?: string;
readonly error?: string;
readonly profileLocation?: URI;
readonly applicationScoped?: boolean;
}

export enum ExtensionManagementErrorCode {
Expand Down Expand Up @@ -402,9 +410,10 @@ export type InstallOptions = {
* Context passed through to InstallExtensionResult
*/
context?: IStringDictionary<any>;
profileLocation?: URI;
};
export type InstallVSIXOptions = Omit<InstallOptions, 'installGivenVersion'> & { installOnlyNewlyAddedFromExtensionPack?: boolean };
export type UninstallOptions = { readonly donotIncludePack?: boolean; readonly donotCheckDependents?: boolean; readonly versionOnly?: boolean; readonly remove?: boolean };
export type UninstallOptions = { readonly donotIncludePack?: boolean; readonly donotCheckDependents?: boolean; readonly versionOnly?: boolean; readonly remove?: boolean; readonly profileLocation?: URI };

export interface IExtensionManagementParticipant {
postInstall(local: ILocalExtension, source: URI | IGalleryExtension, options: InstallOptions | InstallVSIXOptions, token: CancellationToken): Promise<void>;
Expand All @@ -428,7 +437,7 @@ export interface IExtensionManagementService {
installFromGallery(extension: IGalleryExtension, options?: InstallOptions): Promise<ILocalExtension>;
uninstall(extension: ILocalExtension, options?: UninstallOptions): Promise<void>;
reinstallFromGallery(extension: ILocalExtension): Promise<void>;
getInstalled(type?: ExtensionType): Promise<ILocalExtension[]>;
getInstalled(type?: ExtensionType, profileLocation?: URI): Promise<ILocalExtension[]>;
getExtensionsControlManifest(): Promise<IExtensionsControlManifest>;

getMetadata(extension: ILocalExtension): Promise<Metadata | undefined>;
Expand All @@ -439,28 +448,6 @@ export interface IExtensionManagementService {
getTargetPlatform(): Promise<TargetPlatform>;
}

export type ServerInstallExtensionEvent = InstallExtensionEvent & { profileLocation?: URI; applicationScoped?: boolean };
export type ServerInstallExtensionResult = InstallExtensionResult & { profileLocation?: URI; applicationScoped?: boolean };
export type ServerUninstallExtensionEvent = UninstallExtensionEvent & { profileLocation?: URI; applicationScoped?: boolean };
export type ServerDidUninstallExtensionEvent = DidUninstallExtensionEvent & { profileLocation?: URI; applicationScoped?: boolean };

export type ServerInstallOptions = InstallOptions & { profileLocation?: URI };
export type ServerInstallVSIXOptions = InstallVSIXOptions & { profileLocation?: URI };
export type ServerUninstallOptions = UninstallOptions & { profileLocation?: URI };

export const IServerExtensionManagementService = refineServiceDecorator<IExtensionManagementService, IServerExtensionManagementService>(IExtensionManagementService);
export interface IServerExtensionManagementService extends IExtensionManagementService {
readonly _serviceBrand: undefined;
onInstallExtension: Event<ServerInstallExtensionEvent>;
onDidInstallExtensions: Event<readonly ServerInstallExtensionResult[]>;
onUninstallExtension: Event<ServerUninstallExtensionEvent>;
onDidUninstallExtension: Event<ServerDidUninstallExtensionEvent>;
getInstalled(type?: ExtensionType, profileLocation?: URI): Promise<ILocalExtension[]>;
install(vsix: URI, options?: ServerInstallVSIXOptions): Promise<ILocalExtension>;
installFromGallery(extension: IGalleryExtension, options?: ServerInstallOptions): Promise<ILocalExtension>;
uninstall(extension: ILocalExtension, options?: ServerUninstallOptions): Promise<void>;
}

export const DISABLED_EXTENSIONS_STORAGE_PATH = 'extensionsIdentifiers/disabled';
export const ENABLED_EXTENSIONS_STORAGE_PATH = 'extensionsIdentifiers/enabled';
export const IGlobalExtensionEnablementService = createDecorator<IGlobalExtensionEnablementService>('IGlobalExtensionEnablementService');
Expand Down