提交 4a079b35 编写于 作者: S Sandeep Somavarapu

Introduce ignored extensions management service

上级 2ed69dff
......@@ -71,6 +71,7 @@ import { ExtensionRecommendationNotificationServiceChannelClient } from 'vs/plat
import { ActiveWindowManager } from 'vs/platform/windows/common/windowTracker';
import { TelemetryLogAppender } from 'vs/platform/telemetry/common/telemetryLogAppender';
import { UserDataAutoSyncEnablementService } from 'vs/platform/userDataSync/common/userDataAutoSyncService';
import { IgnoredExtensionsManagementService, IIgnoredExtensionsManagementService } from 'vs/platform/userDataSync/common/ignoredExtensions';
export interface ISharedProcessConfiguration {
readonly machineId: string;
......@@ -209,6 +210,7 @@ async function main(server: Server, initData: ISharedProcessInitData, configurat
services.set(IUserDataSyncLogService, new SyncDescriptor(UserDataSyncLogService));
services.set(IUserDataSyncUtilService, new UserDataSyncUtilServiceClient(server.getChannel('userDataSyncUtil', client => client.ctx !== 'main')));
services.set(IGlobalExtensionEnablementService, new SyncDescriptor(GlobalExtensionEnablementService));
services.set(IIgnoredExtensionsManagementService, new SyncDescriptor(IgnoredExtensionsManagementService));
services.set(IUserDataSyncStoreManagementService, new SyncDescriptor(UserDataSyncStoreManagementService));
services.set(IUserDataSyncStoreService, new SyncDescriptor(UserDataSyncStoreService));
services.set(IUserDataSyncMachinesService, new SyncDescriptor(UserDataSyncMachinesService));
......
......@@ -217,6 +217,7 @@ export interface IExtensionManagementService {
getExtensionsReport(): Promise<IReportedExtension[]>;
updateMetadata(local: ILocalExtension, metadata: IGalleryMetadata): Promise<ILocalExtension>;
updateExtensionScope(local: ILocalExtension, isMachineScoped: boolean): Promise<ILocalExtension>;
}
export const DISABLED_EXTENSIONS_STORAGE_PATH = 'extensionsIdentifiers/disabled';
......
......@@ -69,6 +69,7 @@ export class ExtensionManagementChannel implements IServerChannel {
case 'reinstallFromGallery': return this.service.reinstallFromGallery(transformIncomingExtension(args[0], uriTransformer));
case 'getInstalled': return this.service.getInstalled(args[0]).then(extensions => extensions.map(e => transformOutgoingExtension(e, uriTransformer)));
case 'updateMetadata': return this.service.updateMetadata(transformIncomingExtension(args[0], uriTransformer), args[1]).then(e => transformOutgoingExtension(e, uriTransformer));
case 'updateExtensionScope': return this.service.updateExtensionScope(transformIncomingExtension(args[0], uriTransformer), args[1]).then(e => transformOutgoingExtension(e, uriTransformer));
case 'getExtensionsReport': return this.service.getExtensionsReport();
}
......@@ -131,6 +132,11 @@ export class ExtensionManagementChannelClient implements IExtensionManagementSer
.then(extension => transformIncomingExtension(extension, null));
}
updateExtensionScope(local: ILocalExtension, isMachineScoped: boolean): Promise<ILocalExtension> {
return Promise.resolve(this.channel.call<ILocalExtension>('updateExtensionScope', [local, isMachineScoped]))
.then(extension => transformIncomingExtension(extension, null));
}
getExtensionsReport(): Promise<IReportedExtension[]> {
return Promise.resolve(this.channel.call('getExtensionsReport'));
}
......
......@@ -44,7 +44,7 @@ import { CancellationToken } from 'vs/base/common/cancellation';
import { getManifest } from 'vs/platform/extensionManagement/node/extensionManagementUtil';
import { IExtensionManifest, ExtensionType } from 'vs/platform/extensions/common/extensions';
import { ExtensionsDownloader } from 'vs/platform/extensionManagement/node/extensionDownloader';
import { ExtensionsScanner, IMetadata } from 'vs/platform/extensionManagement/node/extensionsScanner';
import { ExtensionsScanner, ILocalExtensionManifest, IMetadata } from 'vs/platform/extensionManagement/node/extensionsScanner';
import { ExtensionsLifecycle } from 'vs/platform/extensionManagement/node/extensionLifecycle';
const INSTALL_ERROR_UNSET_UNINSTALLED = 'unsetUninstalled';
......@@ -201,7 +201,7 @@ export class ExtensionManagementService extends Disposable implements IExtension
} catch (e) { /* Ignore */ }
try {
const local = await this.installFromZipPath(identifierWithVersion, zipPath, { ...(metadata || {}), ...options }, operation, token);
const local = await this.installFromZipPath(identifierWithVersion, zipPath, { ...(metadata || {}), ...options }, options, operation, token);
this.logService.info('Successfully installed the extension:', identifier.id);
return local;
} catch (e) {
......@@ -224,11 +224,11 @@ export class ExtensionManagementService extends Disposable implements IExtension
return downloadedLocation;
}
private async installFromZipPath(identifierWithVersion: ExtensionIdentifierWithVersion, zipPath: string, metadata: IMetadata | undefined, operation: InstallOperation, token: CancellationToken): Promise<ILocalExtension> {
private async installFromZipPath(identifierWithVersion: ExtensionIdentifierWithVersion, zipPath: string, metadata: IMetadata | undefined, options: InstallOptions, operation: InstallOperation, token: CancellationToken): Promise<ILocalExtension> {
try {
const local = await this.installExtension({ zipPath, identifierWithVersion, metadata }, token);
try {
await this.installDependenciesAndPackExtensions(local, undefined);
await this.installDependenciesAndPackExtensions(local, undefined, options);
} catch (error) {
if (isNonEmptyArray(local.manifest.extensionDependencies)) {
this.logService.warn(`Cannot install dependencies of extension:`, local.identifier.id, error.message);
......@@ -298,7 +298,7 @@ export class ExtensionManagementService extends Disposable implements IExtension
try { await this.extensionsDownloader.delete(URI.file(installableExtension.zipPath)); } catch (error) { /* Ignore */ }
try {
await this.installDependenciesAndPackExtensions(local, existingExtension);
await this.installDependenciesAndPackExtensions(local, existingExtension, options);
} catch (error) {
try { await this.uninstall(local); } catch (error) { /* Ignore */ }
throw error;
......@@ -434,7 +434,7 @@ export class ExtensionManagementService extends Disposable implements IExtension
return local;
}
private async installDependenciesAndPackExtensions(installed: ILocalExtension, existing: ILocalExtension | undefined): Promise<void> {
private async installDependenciesAndPackExtensions(installed: ILocalExtension, existing: ILocalExtension | undefined, options: InstallOptions): Promise<void> {
if (!this.galleryService.isEnabled()) {
return;
}
......@@ -457,7 +457,7 @@ export class ExtensionManagementService extends Disposable implements IExtension
const galleryResult = await this.galleryService.query({ names, pageSize: dependenciesAndPackExtensions.length }, CancellationToken.None);
const extensionsToInstall = galleryResult.firstPage;
try {
await Promise.all(extensionsToInstall.map(e => this.installFromGallery(e)));
await Promise.all(extensionsToInstall.map(e => this.installFromGallery(e, options)));
} catch (error) {
try { await this.rollback(extensionsToInstall); } catch (e) { /* ignore */ }
throw error;
......@@ -489,7 +489,14 @@ export class ExtensionManagementService extends Disposable implements IExtension
async updateMetadata(local: ILocalExtension, metadata: IGalleryMetadata): Promise<ILocalExtension> {
this.logService.trace('ExtensionManagementService#updateMetadata', local.identifier.id);
local = await this.extensionsScanner.saveMetadataForLocalExtension(local, { ...metadata, isMachineScoped: local.isMachineScoped });
local = await this.extensionsScanner.saveMetadataForLocalExtension(local, { ...((<ILocalExtensionManifest>local.manifest).__metadata || {}), ...metadata });
this.manifestCache.invalidate();
return local;
}
async updateExtensionScope(local: ILocalExtension, isMachineScoped: boolean): Promise<ILocalExtension> {
this.logService.trace('ExtensionManagementService#updateExtensionScope', local.identifier.id);
local = await this.extensionsScanner.saveMetadataForLocalExtension(local, { ...((<ILocalExtensionManifest>local.manifest).__metadata || {}), isMachineScoped });
this.manifestCache.invalidate();
return local;
}
......
......@@ -31,7 +31,7 @@ const INSTALL_ERROR_DELETING = 'deleting';
const INSTALL_ERROR_RENAMING = 'renaming';
export type IMetadata = Partial<IGalleryMetadata & { isMachineScoped: boolean; isBuiltin: boolean }>;
type ILocalExtensionManifest = IExtensionManifest & { __metadata?: IMetadata };
export type ILocalExtensionManifest = IExtensionManifest & { __metadata?: IMetadata };
type IRelaxedLocalExtension = Omit<ILocalExtension, 'isBuiltin'> & { isBuiltin: boolean };
export class ExtensionsScanner extends Disposable {
......@@ -365,7 +365,6 @@ export class ExtensionsScanner extends Disposable {
try {
const manifest = JSON.parse(raw);
const metadata = manifest.__metadata || null;
delete manifest.__metadata;
c({ manifest, metadata });
} catch (err) {
e(new Error(localize('invalidManifest', "Extension invalid: package.json is not a JSON file.")));
......
......@@ -6,9 +6,6 @@
import { ISyncExtension } from 'vs/platform/userDataSync/common/userDataSync';
import { IExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import { deepClone } from 'vs/base/common/objects';
import { ILocalExtension } from 'vs/platform/extensionManagement/common/extensionManagement';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { distinct } from 'vs/base/common/arrays';
export interface IMergeResult {
added: ISyncExtension[];
......@@ -202,31 +199,3 @@ function massageOutgoingExtension(extension: ISyncExtension, key: string): ISync
}
return massagedExtension;
}
export function getIgnoredExtensions(installed: ILocalExtension[], configurationService: IConfigurationService): string[] {
const defaultIgnoredExtensions = installed.filter(i => i.isMachineScoped).map(i => i.identifier.id.toLowerCase());
const value = getConfiguredIgnoredExtensions(configurationService).map(id => id.toLowerCase());
const added: string[] = [], removed: string[] = [];
if (Array.isArray(value)) {
for (const key of value) {
if (key.startsWith('-')) {
removed.push(key.substring(1));
} else {
added.push(key);
}
}
}
return distinct([...defaultIgnoredExtensions, ...added,].filter(setting => removed.indexOf(setting) === -1));
}
function getConfiguredIgnoredExtensions(configurationService: IConfigurationService): string[] {
let userValue = configurationService.inspect<string[]>('settingsSync.ignoredExtensions').userValue;
if (userValue !== undefined) {
return userValue;
}
userValue = configurationService.inspect<string[]>('sync.ignoredExtensions').userValue;
if (userValue !== undefined) {
return userValue;
}
return configurationService.getValue<string[]>('settingsSync.ignoredExtensions') || [];
}
......@@ -14,7 +14,7 @@ import { ExtensionType, IExtensionIdentifier } from 'vs/platform/extensions/comm
import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
import { IFileService } from 'vs/platform/files/common/files';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { merge, getIgnoredExtensions } from 'vs/platform/userDataSync/common/extensionsMerge';
import { merge } from 'vs/platform/userDataSync/common/extensionsMerge';
import { AbstractInitializer, AbstractSynchroniser, IAcceptResult, IMergeResult, IResourcePreview } from 'vs/platform/userDataSync/common/abstractSynchronizer';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { URI } from 'vs/base/common/uri';
......@@ -23,6 +23,7 @@ import { applyEdits } from 'vs/base/common/jsonEdit';
import { compare } from 'vs/base/common/strings';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { CancellationToken } from 'vs/base/common/cancellation';
import { IIgnoredExtensionsManagementService } from 'vs/platform/userDataSync/common/ignoredExtensions';
interface IExtensionResourceMergeResult extends IAcceptResult {
readonly added: ISyncExtension[];
......@@ -94,6 +95,7 @@ export class ExtensionsSynchroniser extends AbstractSynchroniser implements IUse
@IUserDataSyncBackupStoreService userDataSyncBackupStoreService: IUserDataSyncBackupStoreService,
@IExtensionManagementService private readonly extensionManagementService: IExtensionManagementService,
@IGlobalExtensionEnablementService private readonly extensionEnablementService: IGlobalExtensionEnablementService,
@IIgnoredExtensionsManagementService private readonly extensionSyncManagementService: IIgnoredExtensionsManagementService,
@IUserDataSyncLogService logService: IUserDataSyncLogService,
@IExtensionGalleryService private readonly extensionGalleryService: IExtensionGalleryService,
@IConfigurationService configurationService: IConfigurationService,
......@@ -117,7 +119,7 @@ export class ExtensionsSynchroniser extends AbstractSynchroniser implements IUse
const installedExtensions = await this.extensionManagementService.getInstalled();
const localExtensions = this.getLocalExtensions(installedExtensions);
const ignoredExtensions = getIgnoredExtensions(installedExtensions, this.configurationService);
const ignoredExtensions = this.extensionSyncManagementService.getIgnoredExtensions(installedExtensions);
if (remoteExtensions) {
this.logService.trace(`${this.syncResourceLogLabel}: Merging remote extensions with local extensions...`);
......@@ -201,7 +203,7 @@ export class ExtensionsSynchroniser extends AbstractSynchroniser implements IUse
private async acceptLocal(resourcePreview: IExtensionResourcePreview): Promise<IExtensionResourceMergeResult> {
const installedExtensions = await this.extensionManagementService.getInstalled();
const ignoredExtensions = getIgnoredExtensions(installedExtensions, this.configurationService);
const ignoredExtensions = this.extensionSyncManagementService.getIgnoredExtensions(installedExtensions);
const mergeResult = merge(resourcePreview.localExtensions, null, null, resourcePreview.skippedExtensions, ignoredExtensions);
const { added, removed, updated, remote } = mergeResult;
return {
......@@ -217,7 +219,7 @@ export class ExtensionsSynchroniser extends AbstractSynchroniser implements IUse
private async acceptRemote(resourcePreview: IExtensionResourcePreview): Promise<IExtensionResourceMergeResult> {
const installedExtensions = await this.extensionManagementService.getInstalled();
const ignoredExtensions = getIgnoredExtensions(installedExtensions, this.configurationService);
const ignoredExtensions = this.extensionSyncManagementService.getIgnoredExtensions(installedExtensions);
const remoteExtensions = resourcePreview.remoteContent ? JSON.parse(resourcePreview.remoteContent) : null;
if (remoteExtensions !== null) {
const mergeResult = merge(resourcePreview.localExtensions, remoteExtensions, resourcePreview.localExtensions, [], ignoredExtensions);
......@@ -277,7 +279,7 @@ export class ExtensionsSynchroniser extends AbstractSynchroniser implements IUse
async resolveContent(uri: URI): Promise<string | null> {
if (this.extUri.isEqual(uri, ExtensionsSynchroniser.EXTENSIONS_DATA_URI)) {
const installedExtensions = await this.extensionManagementService.getInstalled();
const ignoredExtensions = getIgnoredExtensions(installedExtensions, this.configurationService);
const ignoredExtensions = this.extensionSyncManagementService.getIgnoredExtensions(installedExtensions);
const localExtensions = this.getLocalExtensions(installedExtensions).filter(e => !ignoredExtensions.some(id => areSameExtensions({ id }, e.identifier)));
return this.format(localExtensions);
}
......
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { distinct } from 'vs/base/common/arrays';
import { ConfigurationTarget, IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ILocalExtension } from 'vs/platform/extensionManagement/common/extensionManagement';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
export const IIgnoredExtensionsManagementService = createDecorator<IIgnoredExtensionsManagementService>('IIgnoredExtensionsManagementService');
export interface IIgnoredExtensionsManagementService {
readonly _serviceBrand: any;
getIgnoredExtensions(installed: ILocalExtension[]): string[];
hasToNeverSyncExtension(extensionId: string): boolean;
hasToAlwaysSyncExtension(extensionId: string): boolean;
updateIgnoredExtensions(ignoredExtensionId: string, ignore: boolean): Promise<void>;
updateSynchronizedExtensions(ignoredExtensionId: string, sync: boolean): Promise<void>;
}
export class IgnoredExtensionsManagementService implements IIgnoredExtensionsManagementService {
declare readonly _serviceBrand: undefined;
constructor(
@IConfigurationService private readonly configurationService: IConfigurationService,
) {
}
hasToNeverSyncExtension(extensionId: string): boolean {
const configuredIgnoredExtensions = this.getConfiguredIgnoredExtensions();
return configuredIgnoredExtensions.includes(extensionId.toLowerCase());
}
hasToAlwaysSyncExtension(extensionId: string): boolean {
const configuredIgnoredExtensions = this.getConfiguredIgnoredExtensions();
return configuredIgnoredExtensions.includes(`-${extensionId.toLowerCase()}`);
}
updateIgnoredExtensions(ignoredExtensionId: string, ignore: boolean): Promise<void> {
// first remove the extension completely from ignored extensions
let currentValue = [...this.configurationService.getValue<string[]>('settingsSync.ignoredExtensions')].map(id => id.toLowerCase());
currentValue = currentValue.filter(v => v !== ignoredExtensionId && v !== `-${ignoredExtensionId}`);
// Add only if ignored
if (ignore) {
currentValue.push(ignoredExtensionId.toLowerCase());
}
return this.configurationService.updateValue('settingsSync.ignoredExtensions', currentValue.length ? currentValue : undefined, ConfigurationTarget.USER);
}
updateSynchronizedExtensions(extensionId: string, sync: boolean): Promise<void> {
// first remove the extension completely from ignored extensions
let currentValue = [...this.configurationService.getValue<string[]>('settingsSync.ignoredExtensions')].map(id => id.toLowerCase());
currentValue = currentValue.filter(v => v !== extensionId && v !== `-${extensionId}`);
// Add only if synced
if (sync) {
currentValue.push(`-${extensionId.toLowerCase()}`);
}
return this.configurationService.updateValue('settingsSync.ignoredExtensions', currentValue.length ? currentValue : undefined, ConfigurationTarget.USER);
}
getIgnoredExtensions(installed: ILocalExtension[]): string[] {
const defaultIgnoredExtensions = installed.filter(i => i.isMachineScoped).map(i => i.identifier.id.toLowerCase());
const value = this.getConfiguredIgnoredExtensions().map(id => id.toLowerCase());
const added: string[] = [], removed: string[] = [];
if (Array.isArray(value)) {
for (const key of value) {
if (key.startsWith('-')) {
removed.push(key.substring(1));
} else {
added.push(key);
}
}
}
return distinct([...defaultIgnoredExtensions, ...added,].filter(setting => removed.indexOf(setting) === -1));
}
private getConfiguredIgnoredExtensions(): string[] {
let userValue = this.configurationService.inspect<string[]>('settingsSync.ignoredExtensions').userValue;
if (userValue !== undefined) {
return userValue;
}
userValue = this.configurationService.inspect<string[]>('sync.ignoredExtensions').userValue;
if (userValue !== undefined) {
return userValue;
}
return (this.configurationService.getValue<string[]>('settingsSync.ignoredExtensions') || []).map(id => id.toLowerCase());
}
}
......@@ -39,6 +39,7 @@ import { UserDataSyncBackupStoreService } from 'vs/platform/userDataSync/common/
import { IStorageKeysSyncRegistryService, StorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys';
import { IUserDataSyncMachinesService, UserDataSyncMachinesService } from 'vs/platform/userDataSync/common/userDataSyncMachines';
import { UserDataAutoSyncEnablementService } from 'vs/platform/userDataSync/common/userDataAutoSyncService';
import { IgnoredExtensionsManagementService, IIgnoredExtensionsManagementService } from 'vs/platform/userDataSync/common/ignoredExtensions';
export class UserDataSyncClient extends Disposable {
......@@ -106,6 +107,7 @@ export class UserDataSyncClient extends Disposable {
this.instantiationService.stub(IStorageKeysSyncRegistryService, this.instantiationService.createInstance(StorageKeysSyncRegistryService));
this.instantiationService.stub(IGlobalExtensionEnablementService, this.instantiationService.createInstance(GlobalExtensionEnablementService));
this.instantiationService.stub(IIgnoredExtensionsManagementService, this.instantiationService.createInstance(IgnoredExtensionsManagementService));
this.instantiationService.stub(IExtensionManagementService, <Partial<IExtensionManagementService>>{
async getInstalled() { return []; },
onDidInstallExtension: new Emitter<DidInstallExtensionEvent>().event,
......
......@@ -19,7 +19,7 @@ import {
import { IWorkbenchExtensionEnablementService, EnablementState, IExtensionManagementServerService, IExtensionManagementServer, IWorkbenchExtensioManagementService } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
import { getGalleryExtensionTelemetryData, getLocalExtensionTelemetryData, areSameExtensions, getMaliciousExtensionsSet, groupByExtension, ExtensionIdentifierWithVersion, getGalleryExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IHostService } from 'vs/workbench/services/host/browser/host';
import { URI } from 'vs/base/common/uri';
import { IExtension, ExtensionState, IExtensionsWorkbenchService, AutoUpdateConfigurationKey, AutoCheckUpdatesConfigurationKey } from 'vs/workbench/contrib/extensions/common/extensions';
......@@ -36,10 +36,10 @@ import { IFileService } from 'vs/platform/files/common/files';
import { IExtensionManifest, ExtensionType, IExtension as IPlatformExtension } from 'vs/platform/extensions/common/extensions';
import { IModeService } from 'vs/editor/common/services/modeService';
import { IProductService } from 'vs/platform/product/common/productService';
import { getIgnoredExtensions } from 'vs/platform/userDataSync/common/extensionsMerge';
import { isWeb } from 'vs/base/common/platform';
import { getExtensionKind } from 'vs/workbench/services/extensions/common/extensionsUtil';
import { FileAccess } from 'vs/base/common/network';
import { IIgnoredExtensionsManagementService } from 'vs/platform/userDataSync/common/ignoredExtensions';
import { IUserDataAutoSyncService } from 'vs/platform/userDataSync/common/userDataSync';
interface IExtensionStateProvider<T> {
(extension: Extension): T;
......@@ -523,6 +523,8 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension
@IExtensionManagementServerService private readonly extensionManagementServerService: IExtensionManagementServerService,
@IStorageService private readonly storageService: IStorageService,
@IModeService private readonly modeService: IModeService,
@IIgnoredExtensionsManagementService private readonly extensionsSyncManagementService: IIgnoredExtensionsManagementService,
@IUserDataAutoSyncService private readonly userDataAutoSyncService: IUserDataAutoSyncService,
@IProductService private readonly productService: IProductService
) {
super();
......@@ -980,34 +982,40 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension
}
isExtensionIgnoredToSync(extension: IExtension): boolean {
const localExtensions = (!isWeb && this.localExtensions ? this.localExtensions.local : this.local)
.filter(l => !!l.local)
.map(l => l.local!);
const ignoredExtensions = getIgnoredExtensions(localExtensions, this.configurationService);
return ignoredExtensions.includes(extension.identifier.id.toLowerCase());
return extension.local ? !this.isInstalledExtensionSynced(extension.local)
: this.extensionsSyncManagementService.hasToNeverSyncExtension(extension.identifier.id);
}
toggleExtensionIgnoredToSync(extension: IExtension): Promise<void> {
async toggleExtensionIgnoredToSync(extension: IExtension): Promise<void> {
const isIgnored = this.isExtensionIgnoredToSync(extension);
const isDefaultIgnored = extension.local?.isMachineScoped;
const id = extension.identifier.id.toLowerCase();
// first remove the extension completely from ignored extensions
let currentValue = [...this.configurationService.getValue<string[]>('settingsSync.ignoredExtensions')].map(id => id.toLowerCase());
currentValue = currentValue.filter(v => v !== id && v !== `-${id}`);
// If ignored, then add only if it is ignored by default
if (isIgnored && isDefaultIgnored) {
currentValue.push(`-${id}`);
if (extension.local && isIgnored) {
(<Extension>extension).local = await this.updateSynchronizingInstalledExtension(extension.local, true);
this._onChange.fire(extension);
} else {
this.extensionsSyncManagementService.updateIgnoredExtensions(extension.identifier.id, !isIgnored);
}
await this.userDataAutoSyncService.triggerSync(['IgnoredExtensionsUpdated'], false, false);
}
// If asked not to sync, then add only if it is not ignored by default
if (!isIgnored && !isDefaultIgnored) {
currentValue.push(id);
private isInstalledExtensionSynced(extension: ILocalExtension): boolean {
if (extension.isMachineScoped) {
return false;
}
if (this.extensionsSyncManagementService.hasToAlwaysSyncExtension(extension.identifier.id)) {
return true;
}
return !this.extensionsSyncManagementService.hasToNeverSyncExtension(extension.identifier.id);
}
return this.configurationService.updateValue('settingsSync.ignoredExtensions', currentValue.length ? currentValue : undefined, ConfigurationTarget.USER);
async updateSynchronizingInstalledExtension(extension: ILocalExtension, sync: boolean): Promise<ILocalExtension> {
const isMachineScoped = !sync;
if (extension.isMachineScoped !== isMachineScoped) {
extension = await this.extensionManagementService.updateExtensionScope(extension, isMachineScoped);
}
if (sync) {
this.extensionsSyncManagementService.updateIgnoredExtensions(extension.identifier.id, false);
}
return extension;
}
private installWithProgress<T>(installTask: () => Promise<T>, extensionName?: string): Promise<T> {
......
......@@ -136,6 +136,14 @@ export class ExtensionManagementService extends Disposable implements IWorkbench
return Promise.reject(`Invalid location ${extension.location.toString()}`);
}
updateExtensionScope(extension: ILocalExtension, isMachineScoped: boolean): Promise<ILocalExtension> {
const server = this.getServer(extension);
if (server) {
return server.extensionManagementService.updateExtensionScope(extension, isMachineScoped);
}
return Promise.reject(`Invalid location ${extension.location.toString()}`);
}
zip(extension: ILocalExtension): Promise<URI> {
const server = this.getServer(extension);
if (server) {
......
......@@ -107,5 +107,5 @@ export class WebExtensionManagementService extends Disposable implements IExtens
install(vsix: URI): Promise<ILocalExtension> { throw new Error('unsupported'); }
reinstallFromGallery(extension: ILocalExtension): Promise<void> { throw new Error('unsupported'); }
getExtensionsReport(): Promise<IReportedExtension[]> { throw new Error('unsupported'); }
updateExtensionScope(): Promise<ILocalExtension> { throw new Error('unsupported'); }
}
......@@ -117,8 +117,10 @@ import { OpenerService } from 'vs/editor/browser/services/openerService';
import { IOpenerService } from 'vs/platform/opener/common/opener';
import { IUserDataSyncResourceEnablementService } from 'vs/platform/userDataSync/common/userDataSync';
import { UserDataSyncResourceEnablementService } from 'vs/platform/userDataSync/common/userDataSyncResourceEnablementService';
import { IgnoredExtensionsManagementService, IIgnoredExtensionsManagementService } from 'vs/platform/userDataSync/common/ignoredExtensions';
registerSingleton(IUserDataSyncResourceEnablementService, UserDataSyncResourceEnablementService);
registerSingleton(IIgnoredExtensionsManagementService, IgnoredExtensionsManagementService);
registerSingleton(IGlobalExtensionEnablementService, GlobalExtensionEnablementService);
registerSingleton(IExtensionGalleryService, ExtensionGalleryService, true);
registerSingleton(IContextViewService, ContextViewService, true);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册