From e6d385f2588f2f5a09facfe01f9d66fca2957c09 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Mon, 17 Oct 2016 10:49:22 +0200 Subject: [PATCH] fix #13734 --- extensions/configuration-editing/package.json | 8 -- .../platform/extensions/common/extensions.ts | 6 +- src/vs/platform/storage/common/storage.ts | 14 +-- src/vs/test/utils/servicesTestUtils.ts | 7 +- src/vs/workbench/{node => common}/storage.ts | 61 ----------- src/vs/workbench/electron-browser/shell.ts | 2 +- .../extensions.contribution.ts | 13 +-- .../electron-browser/extensionsActions.ts | 78 +------------- .../extensionsFileTemplate.ts | 28 ----- .../electron-browser/extensionHost.ts | 60 ++++++++++- .../extensions/electron-browser/extensions.ts | 101 ++++++------------ src/vs/workbench/test/browser/part.test.ts | 2 +- src/vs/workbench/test/common/memento.test.ts | 2 +- src/vs/workbench/test/node/storage.test.ts | 2 +- 14 files changed, 99 insertions(+), 285 deletions(-) rename src/vs/workbench/{node => common}/storage.ts (82%) diff --git a/extensions/configuration-editing/package.json b/extensions/configuration-editing/package.json index f5a5adb12bf..8f64f1c9663 100644 --- a/extensions/configuration-editing/package.json +++ b/extensions/configuration-editing/package.json @@ -61,14 +61,6 @@ { "fileMatch": "/.vscode/extensions.json", "url": "vscode://schemas/extensions" - }, - { - "fileMatch": "%APP_SETTINGS_HOME%/extensions.json", - "url": "vscode://schemas/extensionsstorage" - }, - { - "fileMatch": "%APP_SETTINGS_HOME%/**/extensions.json", - "url": "vscode://schemas/extensionsstorage" } ] } diff --git a/src/vs/platform/extensions/common/extensions.ts b/src/vs/platform/extensions/common/extensions.ts index b9a8424c9e5..5a2c4059f1e 100644 --- a/src/vs/platform/extensions/common/extensions.ts +++ b/src/vs/platform/extensions/common/extensions.ts @@ -64,14 +64,10 @@ export interface IExtensionService { getExtensionsStatus(): { [id: string]: IExtensionsStatus }; } -export interface IExtensionsStorageData { - disabled?: string[]; -} - export const IExtensionsRuntimeService = createDecorator('extensionsRuntimeService'); export interface IExtensionsRuntimeService { _serviceBrand: any; - getStoragePath(scope: StorageScope): string; + // setEnablement(id: string, enable: boolean, displayName: string): TPromise; getDisabledExtensions(scope?: StorageScope): string[]; } diff --git a/src/vs/platform/storage/common/storage.ts b/src/vs/platform/storage/common/storage.ts index 74b58bc651b..fcd926adcb9 100644 --- a/src/vs/platform/storage/common/storage.ts +++ b/src/vs/platform/storage/common/storage.ts @@ -61,17 +61,6 @@ export interface IStorageService { * The optional scope argument allows to define the scope of the operation. */ getBoolean(key: string, scope?: StorageScope, defaultValue?: boolean): boolean; - - /** - * Returns an absolute file path in which private state can be stored as JSON data - * in separate modules. - * - * For workspace scope {StorageScope.WORKSPACE}, a workspace specific directory - * under global scope is returned. - * - * NOTE: This is not the same as the local storage used by the other APIs. - */ - getStoragePath(scope: StorageScope): string; } export enum StorageScope { @@ -95,6 +84,5 @@ export const NullStorageService: IStorageService = { remove() { return undefined; }, get(a, b, defaultValue) { return defaultValue; }, getInteger(a, b, defaultValue) { return defaultValue; }, - getBoolean(a, b, defaultValue) { return defaultValue; }, - getStoragePath(scope) { return void 0; }, + getBoolean(a, b, defaultValue) { return defaultValue; } }; diff --git a/src/vs/test/utils/servicesTestUtils.ts b/src/vs/test/utils/servicesTestUtils.ts index 65bcd65c288..e1c5b5e187c 100644 --- a/src/vs/test/utils/servicesTestUtils.ts +++ b/src/vs/test/utils/servicesTestUtils.ts @@ -13,7 +13,7 @@ import { EventEmitter } from 'vs/base/common/eventEmitter'; import * as paths from 'vs/base/common/paths'; import URI from 'vs/base/common/uri'; import { ITelemetryService, NullTelemetryService } from 'vs/platform/telemetry/common/telemetry'; -import { Storage, InMemoryLocalStorage } from 'vs/workbench/node/storage'; +import { Storage, InMemoryLocalStorage } from 'vs/workbench/common/storage'; import { IEditorGroup, ConfirmResult } from 'vs/workbench/common/editor'; import Event, { Emitter } from 'vs/base/common/event'; import Severity from 'vs/base/common/severity'; @@ -304,11 +304,6 @@ export class TestStorageService extends EventEmitter implements IStorageService getBoolean(key: string, scope: StorageScope = StorageScope.GLOBAL, defaultValue?: boolean): boolean { return this.storage.getBoolean(key, scope, defaultValue); } - - getStoragePath(scope: StorageScope = StorageScope.GLOBAL): string { - return this.storage.getStoragePath(scope); - } - } export class TestEditorGroupService implements IEditorGroupService { diff --git a/src/vs/workbench/node/storage.ts b/src/vs/workbench/common/storage.ts similarity index 82% rename from src/vs/workbench/node/storage.ts rename to src/vs/workbench/common/storage.ts index f400d8a83d2..65c0dac4906 100644 --- a/src/vs/workbench/node/storage.ts +++ b/src/vs/workbench/common/storage.ts @@ -4,9 +4,6 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import * as fs from 'fs'; -import * as crypto from 'crypto'; -import * as paths from 'vs/base/common/paths'; import types = require('vs/base/common/types'); import errors = require('vs/base/common/errors'); import strings = require('vs/base/common/strings'); @@ -38,7 +35,6 @@ export class Storage implements IStorageService { private globalStorage: IStorage; private workspaceKey: string; - private workspaceStoragePath: string; constructor( globalStorage: IStorage, @@ -196,63 +192,6 @@ export class Storage implements IStorageService { return value ? true : false; } - public getStoragePath(scope: StorageScope): string { - if (StorageScope.GLOBAL === scope) { - return this.environmentService.appSettingsHome; - } - - const workspace = this.contextService.getWorkspace(); - - if (!workspace) { - return void 0; - } - - if (this.workspaceStoragePath) { - return this.workspaceStoragePath; - } - - function rmkDir(directory: string): boolean { - try { - fs.mkdirSync(directory); - return true; - } catch (err) { - if (err.code === 'ENOENT') { - if (rmkDir(paths.dirname(directory))) { - fs.mkdirSync(directory); - return true; - } - } else { - return fs.statSync(directory).isDirectory(); - } - } - } - - if (workspace) { - const hash = crypto.createHash('md5'); - hash.update(workspace.resource.fsPath); - if (workspace.uid) { - hash.update(workspace.uid.toString()); - } - this.workspaceStoragePath = paths.join(this.environmentService.appSettingsHome, 'workspaceStorage', hash.digest('hex')); - if (!fs.existsSync(this.workspaceStoragePath)) { - try { - if (rmkDir(this.workspaceStoragePath)) { - fs.writeFileSync(paths.join(this.workspaceStoragePath, 'meta.json'), JSON.stringify({ - workspacePath: workspace.resource.fsPath, - uid: workspace.uid ? workspace.uid : null - }, null, 4)); - } else { - this.workspaceStoragePath = void 0; - } - } catch (err) { - this.workspaceStoragePath = void 0; - } - } - } - - return this.workspaceStoragePath; - } - private toStorageKey(key: string, scope: StorageScope): string { if (scope === StorageScope.GLOBAL) { return Storage.GLOBAL_PREFIX + key.toLowerCase(); diff --git a/src/vs/workbench/electron-browser/shell.ts b/src/vs/workbench/electron-browser/shell.ts index f43c4eadb6e..dfc8efbf59b 100644 --- a/src/vs/workbench/electron-browser/shell.ts +++ b/src/vs/workbench/electron-browser/shell.ts @@ -21,7 +21,7 @@ import pkg from 'vs/platform/package'; import { ContextViewService } from 'vs/platform/contextview/browser/contextViewService'; import timer = require('vs/base/common/timer'); import { Workbench } from 'vs/workbench/electron-browser/workbench'; -import { Storage, inMemoryLocalStorageInstance } from 'vs/workbench/node/storage'; +import { Storage, inMemoryLocalStorageInstance } from 'vs/workbench/common/storage'; import { ITelemetryService, NullTelemetryService, loadExperiments } from 'vs/platform/telemetry/common/telemetry'; import { ITelemetryAppenderChannel, TelemetryAppenderClient } from 'vs/platform/telemetry/common/telemetryIpc'; import { TelemetryService, ITelemetryServiceConfig } from 'vs/platform/telemetry/common/telemetryService'; diff --git a/src/vs/workbench/parts/extensions/electron-browser/extensions.contribution.ts b/src/vs/workbench/parts/extensions/electron-browser/extensions.contribution.ts index 78a0f76edba..83e3de0bafe 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/extensions.contribution.ts +++ b/src/vs/workbench/parts/extensions/electron-browser/extensions.contribution.ts @@ -20,7 +20,7 @@ import { IEditorRegistry, Extensions as EditorExtensions } from 'vs/workbench/co import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { VIEWLET_ID, IExtensionsWorkbenchService } from './extensions'; import { ExtensionsWorkbenchService } from './extensionsWorkbenchService'; -import { OpenExtensionsViewletAction, InstallExtensionsAction, ShowOutdatedExtensionsAction, ShowRecommendedExtensionsAction, ShowWorkspaceRecommendedExtensionsAction, ShowPopularExtensionsAction, ShowInstalledExtensionsAction, ShowDisabledExtensionsAction, UpdateAllAction, OpenExtensionsFolderAction, ConfigureWorkspaceRecommendedExtensionsAction, OpenWorkspaceExtensionsStorageFile, OpenGlobalExtensionsStorageFile, InstallVSIXAction } from './extensionsActions'; +import { OpenExtensionsViewletAction, InstallExtensionsAction, ShowOutdatedExtensionsAction, ShowRecommendedExtensionsAction, ShowWorkspaceRecommendedExtensionsAction, ShowPopularExtensionsAction, ShowInstalledExtensionsAction, ShowDisabledExtensionsAction, UpdateAllAction, OpenExtensionsFolderAction, ConfigureWorkspaceRecommendedExtensionsAction, InstallVSIXAction } from './extensionsActions'; import { ExtensionsInput } from './extensionsInput'; import { ViewletRegistry, Extensions as ViewletExtensions, ViewletDescriptor } from 'vs/workbench/browser/viewlet'; import { ExtensionEditor } from './extensionEditor'; @@ -28,7 +28,7 @@ import { StatusUpdater } from './extensionsViewlet'; import { IQuickOpenRegistry, Extensions, QuickOpenHandlerDescriptor } from 'vs/workbench/browser/quickopen'; import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry'; import jsonContributionRegistry = require('vs/platform/jsonschemas/common/jsonContributionRegistry'); -import { ExtensionsConfigurationSchema, ExtensionsConfigurationSchemaId, ExtensionsStorageSchema, ExtensionsStorageSchemaId } from 'vs/workbench/parts/extensions/electron-browser/extensionsFileTemplate'; +import { ExtensionsConfigurationSchema, ExtensionsConfigurationSchemaId } from 'vs/workbench/parts/extensions/electron-browser/extensionsFileTemplate'; // Singletons registerSingleton(IExtensionGalleryService, ExtensionGalleryService); @@ -122,12 +122,6 @@ actionRegistry.registerWorkbenchAction(openExtensionsFolderActionDescriptor, 'Ex const openExtensionsFileActionDescriptor = new SyncActionDescriptor(ConfigureWorkspaceRecommendedExtensionsAction, ConfigureWorkspaceRecommendedExtensionsAction.ID, ConfigureWorkspaceRecommendedExtensionsAction.LABEL); actionRegistry.registerWorkbenchAction(openExtensionsFileActionDescriptor, 'Extensions: Open Extensions File', ExtensionsLabel); -const disableExtensionsActionDescriptor = new SyncActionDescriptor(OpenGlobalExtensionsStorageFile, OpenGlobalExtensionsStorageFile.ID, localize('disableGlobalExtensions', "Configure Disabled Extensions")); -actionRegistry.registerWorkbenchAction(disableExtensionsActionDescriptor, 'Extensions: Configure Disabled Extensions', ExtensionsLabel); - -const disableWorkspaceExtensionsActionDescriptor = new SyncActionDescriptor(OpenWorkspaceExtensionsStorageFile, OpenWorkspaceExtensionsStorageFile.ID, localize('disableWorkspaceExtensions', "Configure Disabled Extensions (Workspace)")); -actionRegistry.registerWorkbenchAction(disableWorkspaceExtensionsActionDescriptor, 'Extensions: Configure Disabled Extensions (Workspace)', ExtensionsLabel); - const installVSIXActionDescriptor = new SyncActionDescriptor(InstallVSIXAction, InstallVSIXAction.ID, InstallVSIXAction.LABEL); actionRegistry.registerWorkbenchAction(installVSIXActionDescriptor, 'Extensions: Install from VSIX...', ExtensionsLabel); @@ -147,5 +141,4 @@ Registry.as(ConfigurationExtensions.Configuration) }); const jsonRegistry = Registry.as(jsonContributionRegistry.Extensions.JSONContribution); -jsonRegistry.registerSchema(ExtensionsConfigurationSchemaId, ExtensionsConfigurationSchema); -jsonRegistry.registerSchema(ExtensionsStorageSchemaId, ExtensionsStorageSchema); \ No newline at end of file +jsonRegistry.registerSchema(ExtensionsConfigurationSchemaId, ExtensionsConfigurationSchema); \ No newline at end of file diff --git a/src/vs/workbench/parts/extensions/electron-browser/extensionsActions.ts b/src/vs/workbench/parts/extensions/electron-browser/extensionsActions.ts index e4465ce11e6..f7f1a0e05a1 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/extensionsActions.ts +++ b/src/vs/workbench/parts/extensions/electron-browser/extensionsActions.ts @@ -14,7 +14,6 @@ import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { ReloadWindowAction } from 'vs/workbench/electron-browser/actions'; import { IExtension, ExtensionState, IExtensionsWorkbenchService, VIEWLET_ID, IExtensionsViewlet, ConfigurationKey } from './extensions'; import { LocalExtensionType } from 'vs/platform/extensionManagement/common/extensionManagement'; -import { IExtensionsRuntimeService } from 'vs/platform/extensions/common/extensions'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IMessageService, LaterAction } from 'vs/platform/message/common/message'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; @@ -23,11 +22,10 @@ import { IViewletService } from 'vs/workbench/services/viewlet/common/viewletSer import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService'; import { Query } from '../common/extensionQuery'; import { shell, remote } from 'electron'; -import { ExtensionsConfigurationInitialContent, ExtensionStorageInitialContent } from 'vs/workbench/parts/extensions/electron-browser/extensionsFileTemplate'; +import { ExtensionsConfigurationInitialContent } from 'vs/workbench/parts/extensions/electron-browser/extensionsFileTemplate'; import { IFileService } from 'vs/platform/files/common/files'; import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import URI from 'vs/base/common/uri'; -import { StorageScope } from 'vs/platform/storage/common/storage'; const dialog = remote.dialog; @@ -662,80 +660,6 @@ export class ConfigureWorkspaceRecommendedExtensionsAction extends Action { } } -export abstract class OpenExtensionsStorageFile extends Action { - - constructor( - id: string, - label: string, - enabled: boolean, - private scope: StorageScope, - @IFileService private fileService: IFileService, - @IWorkbenchEditorService private editorService: IWorkbenchEditorService, - @IExtensionsRuntimeService private extensionsRuntimeService: IExtensionsRuntimeService - ) { - super(id, label, null, enabled); - } - - public run(event: any): TPromise { - return this.openExtensionsStorageFile(); - } - - private openExtensionsStorageFile(): TPromise { - return this.getOrCreateExtensionsFile().then(value => { - return this.editorService.openEditor({ - resource: value.extensionsFileResource, - options: { - forceOpen: true, - pinned: value.created - }, - }); - }, (error) => TPromise.wrapError(new Error(localize('OpenGlobalExtensionsStorageFile.failed', "Unable to create 'extensions.json' file inside the '{0}' folder ({1}).", this.extensionsRuntimeService.getStoragePath(this.scope), error)))); - } - - private getOrCreateExtensionsFile(): TPromise<{ created: boolean, extensionsFileResource: URI }> { - const extensionsFileResource = URI.file(this.extensionsRuntimeService.getStoragePath(this.scope)); - - return this.fileService.resolveContent(extensionsFileResource).then(content => { - return { created: false, extensionsFileResource }; - }, err => { - return this.fileService.updateContent(extensionsFileResource, ExtensionStorageInitialContent).then(() => { - return { created: true, extensionsFileResource }; - }); - }); - } -} - -export class OpenWorkspaceExtensionsStorageFile extends OpenExtensionsStorageFile { - - static ID = 'workbench.extensions.action.openWorkspaceExtensionsStorageFile'; - - constructor( - id: string, - label: string, - @IFileService fileService: IFileService, - @IWorkspaceContextService contextService: IWorkspaceContextService, - @IWorkbenchEditorService editorService: IWorkbenchEditorService, - @IExtensionsRuntimeService extensionsRuntimeService: IExtensionsRuntimeService - ) { - super(id, label, !!contextService.getWorkspace(), StorageScope.WORKSPACE, fileService, editorService, extensionsRuntimeService); - } -} - -export class OpenGlobalExtensionsStorageFile extends OpenExtensionsStorageFile { - - static ID = 'workbench.extensions.action.openGlobalExtensionsStorageFile'; - - constructor( - id: string, - label: string, - @IFileService fileService: IFileService, - @IWorkbenchEditorService editorService: IWorkbenchEditorService, - @IExtensionsRuntimeService extensionsRuntimeService: IExtensionsRuntimeService - ) { - super(id, label, true, StorageScope.GLOBAL, fileService, editorService, extensionsRuntimeService); - } -} - export class InstallVSIXAction extends Action { static ID = 'workbench.extensions.action.installVSIX'; diff --git a/src/vs/workbench/parts/extensions/electron-browser/extensionsFileTemplate.ts b/src/vs/workbench/parts/extensions/electron-browser/extensionsFileTemplate.ts index 8aab06a3a99..d97f7986c35 100644 --- a/src/vs/workbench/parts/extensions/electron-browser/extensionsFileTemplate.ts +++ b/src/vs/workbench/parts/extensions/electron-browser/extensionsFileTemplate.ts @@ -35,32 +35,4 @@ export const ExtensionsConfigurationInitialContent: string = [ '\t\t', '\t]', '}' -].join('\n'); - -export const ExtensionsStorageSchemaId = 'vscode://schemas/extensionsstorage'; -export const ExtensionsStorageSchema: IJSONSchema = { - id: ExtensionsStorageSchemaId, - type: 'object', - title: localize('app.extensionsstorage.json.title', "Extensions Storage"), - properties: { - disabled: { - type: 'array', - description: localize('app.extensionsstorage.json.disabled', "List of disabled extensions. The identifier of an extension is always '${publisher}.${name}'. For example: 'vscode.csharp'."), - items: { - type: 'string', - defaultSnippets: [{ label: 'Example', body: 'vscode.csharp' }], - pattern: EXTENSION_IDENTIFIER_PATTERN, - errorMessage: localize('app.extension.identifier.errorMessage', "Expected format '${publisher}.${name}'. Example: 'vscode.csharp'.") - }, - }, - } -}; - -export const ExtensionStorageInitialContent: string = [ - '{', - '\t"disabled": [', - '\t\t// Extension identifier format: ${publisher}.${name}. Example: vscode.csharp', - '\t\t', - '\t]', - '}' ].join('\n'); \ No newline at end of file diff --git a/src/vs/workbench/services/extensions/electron-browser/extensionHost.ts b/src/vs/workbench/services/extensions/electron-browser/extensionHost.ts index ea9fec3515c..b3415684643 100644 --- a/src/vs/workbench/services/extensions/electron-browser/extensionHost.ts +++ b/src/vs/workbench/services/extensions/electron-browser/extensionHost.ts @@ -5,6 +5,8 @@ 'use strict'; +import * as fs from 'fs'; +import * as crypto from 'crypto'; import * as nls from 'vs/nls'; import pkg from 'vs/platform/package'; import paths = require('vs/base/common/paths'); @@ -28,7 +30,6 @@ import { IExtensionDescription, IMessage, IExtensionsRuntimeService } from 'vs/p import { ExtensionScanner, MessagesCollector } from 'vs/workbench/node/extensionPoints'; import { IMessagePassingProtocol } from 'vs/base/parts/ipc/common/ipc'; import Event, { Emitter } from 'vs/base/common/event'; -import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; import { createQueuedSender, IQueuedSender } from 'vs/base/node/processes'; export const EXTENSION_LOG_BROADCAST_CHANNEL = 'vscode:extensionLog'; @@ -51,6 +52,7 @@ export class ExtensionHostProcessWorker { private extensionHostProcessQueuedSender: IQueuedSender; private extensionHostProcessReady: boolean; private initializeTimer: number; + private workspaceStoragePath: string; private lastExtensionHostError: string; private unsentMessages: any[]; @@ -72,7 +74,6 @@ export class ExtensionHostProcessWorker { @ILifecycleService lifecycleService: ILifecycleService, @IInstantiationService private instantiationService: IInstantiationService, @IEnvironmentService private environmentService: IEnvironmentService, - @IStorageService private storageService: IStorageService, @IExtensionsRuntimeService private extensionsRuntimeService: IExtensionsRuntimeService ) { // handle extension host lifecycle a bit special when we know we are developing an extension that runs inside @@ -221,7 +222,7 @@ export class ExtensionHostProcessWorker { contextService: { workspace: this.contextService.getWorkspace() }, - workspaceStoragePath: this.storageService.getStoragePath(StorageScope.WORKSPACE), + workspaceStoragePath: this.getStoragePath(), extensions: extensionDescriptors }); this.extensionHostProcessQueuedSender.send(initPayload); @@ -408,4 +409,57 @@ export class ExtensionHostProcessWorker { } } } + + private getStoragePath(): string { + const workspace = this.contextService.getWorkspace(); + + if (!workspace) { + return void 0; + } + + if (this.workspaceStoragePath) { + return this.workspaceStoragePath; + } + + function rmkDir(directory: string): boolean { + try { + fs.mkdirSync(directory); + return true; + } catch (err) { + if (err.code === 'ENOENT') { + if (rmkDir(paths.dirname(directory))) { + fs.mkdirSync(directory); + return true; + } + } else { + return fs.statSync(directory).isDirectory(); + } + } + } + + if (workspace) { + const hash = crypto.createHash('md5'); + hash.update(workspace.resource.fsPath); + if (workspace.uid) { + hash.update(workspace.uid.toString()); + } + this.workspaceStoragePath = paths.join(this.environmentService.appSettingsHome, 'workspaceStorage', hash.digest('hex')); + if (!fs.existsSync(this.workspaceStoragePath)) { + try { + if (rmkDir(this.workspaceStoragePath)) { + fs.writeFileSync(paths.join(this.workspaceStoragePath, 'meta.json'), JSON.stringify({ + workspacePath: workspace.resource.fsPath, + uid: workspace.uid ? workspace.uid : null + }, null, 4)); + } else { + this.workspaceStoragePath = void 0; + } + } catch (err) { + this.workspaceStoragePath = void 0; + } + } + } + + return this.workspaceStoragePath; + } } \ No newline at end of file diff --git a/src/vs/workbench/services/extensions/electron-browser/extensions.ts b/src/vs/workbench/services/extensions/electron-browser/extensions.ts index ea281fef286..be281634380 100644 --- a/src/vs/workbench/services/extensions/electron-browser/extensions.ts +++ b/src/vs/workbench/services/extensions/electron-browser/extensions.ts @@ -4,95 +4,56 @@ *--------------------------------------------------------------------------------------------*/ import { distinct } from 'vs/base/common/arrays'; -import * as paths from 'vs/base/common/paths'; -import { ConfigWatcher } from 'vs/base/node/config'; -import { Disposable } from 'vs/base/common/lifecycle'; -import { IExtensionsRuntimeService, IExtensionsStorageData } from 'vs/platform/extensions/common/extensions'; +import { IWorkspaceContextService, IWorkspace } from 'vs/platform/workspace/common/workspace'; +import { IExtensionsRuntimeService } from 'vs/platform/extensions/common/extensions'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; +import { IChoiceService } from 'vs/platform/message/common/message'; + +const DISABLED_EXTENSIONS_STORAGE_PATH = 'extensions/disabled'; export class ExtensionsRuntimeService implements IExtensionsRuntimeService { _serviceBrand: any; - private workspaceStorage: ExtensionsStorage; - private globalStorage: ExtensionsStorage; + private workspace: IWorkspace; + private allDisabledExtensions: string[]; + private globalDisabledExtensions: string[]; + private workspaceDisabledExtensions: string[]; constructor( - @IStorageService private storageService: IStorageService + @IStorageService private storageService: IStorageService, + @IChoiceService private choiceService: IChoiceService, + @IWorkspaceContextService contextService: IWorkspaceContextService ) { - } - - public getStoragePath(scope: StorageScope): string { - return this.getPath(scope); + this.workspace = contextService.getWorkspace(); } public getDisabledExtensions(scope?: StorageScope): string[] { - if (scope) { - return this.getData(scope).disabled || []; + if (!this.allDisabledExtensions) { + this.globalDisabledExtensions = this.getDisabledExtensionsFromStorage(StorageScope.GLOBAL); + this.workspaceDisabledExtensions = this.getDisabledExtensionsFromStorage(StorageScope.WORKSPACE); + this.allDisabledExtensions = distinct([...this.globalDisabledExtensions, ...this.workspaceDisabledExtensions]); } - const globalData = this.getData(StorageScope.GLOBAL).disabled || []; - const workspaceData = this.getData(StorageScope.WORKSPACE).disabled || []; - return distinct([...globalData, ...workspaceData]); - } - - private getData(scope: StorageScope): IExtensionsStorageData { - const extensionsStorage = this.getStorage(scope); - return extensionsStorage ? extensionsStorage.data : {}; - } - - private getStorage(scope: StorageScope): ExtensionsStorage { - const path = this.getPath(scope); - if (path) { - if (StorageScope.WORKSPACE === scope) { - return this.getWorkspaceStorage(path); - } - return this.getGlobalStorage(path); + switch (scope) { + case StorageScope.GLOBAL: return this.globalDisabledExtensions; + case StorageScope.WORKSPACE: return this.workspaceDisabledExtensions; } - return null; + return this.allDisabledExtensions; } - private getGlobalStorage(path: string): ExtensionsStorage { - if (!this.globalStorage) { - this.globalStorage = new ExtensionsStorage(path); + private getDisabledExtensionsFromStorage(scope?: StorageScope): string[] { + if (scope !== void 0) { + return this._getDisabledExtensions(scope); } - return this.globalStorage; + + const globallyDisabled = this._getDisabledExtensions(StorageScope.GLOBAL); + const workspaceDisabled = this._getDisabledExtensions(StorageScope.WORKSPACE); + return [...globallyDisabled, ...workspaceDisabled]; } - private getWorkspaceStorage(path: string): ExtensionsStorage { - if (!this.workspaceStorage) { - this.workspaceStorage = new ExtensionsStorage(path); - } - return this.workspaceStorage; - } - - private getPath(scope: StorageScope): string { - const path = this.storageService.getStoragePath(scope); - return path ? paths.join(path, 'extensions.json') : void 0; - } - - public dispose() { - if (this.workspaceStorage) { - this.workspaceStorage.dispose(); - this.workspaceStorage = null; - } - if (this.globalStorage) { - this.globalStorage.dispose(); - this.globalStorage = null; - } - } -} - -export class ExtensionsStorage extends Disposable { - - private _watcher: ConfigWatcher; - - constructor(path: string) { - super(); - this._watcher = this._register(new ConfigWatcher(path, { changeBufferDelay: 300, defaultConfig: Object.create(null) })); - } - - public get data(): IExtensionsStorageData { - return this._watcher.getConfig(); + private _getDisabledExtensions(scope: StorageScope): string[] { + const value = this.storageService.get(DISABLED_EXTENSIONS_STORAGE_PATH, scope, ''); + return value ? distinct(value.split(',')) : []; } } \ No newline at end of file diff --git a/src/vs/workbench/test/browser/part.test.ts b/src/vs/workbench/test/browser/part.test.ts index e1eb9a53302..6badb83c14c 100644 --- a/src/vs/workbench/test/browser/part.test.ts +++ b/src/vs/workbench/test/browser/part.test.ts @@ -12,7 +12,7 @@ import * as Types from 'vs/base/common/types'; import * as TestUtils from 'vs/test/utils/servicesTestUtils'; import { IWorkspaceContextService, WorkspaceContextService } from 'vs/platform/workspace/common/workspace'; import { IStorageService } from 'vs/platform/storage/common/storage'; -import { Storage, InMemoryLocalStorage } from 'vs/workbench/node/storage'; +import { Storage, InMemoryLocalStorage } from 'vs/workbench/common/storage'; class MyPart extends Part { diff --git a/src/vs/workbench/test/common/memento.test.ts b/src/vs/workbench/test/common/memento.test.ts index 855b7441c33..a29f55a2cfd 100644 --- a/src/vs/workbench/test/common/memento.test.ts +++ b/src/vs/workbench/test/common/memento.test.ts @@ -10,7 +10,7 @@ import { WorkspaceContextService } from 'vs/platform/workspace/common/workspace' import { StorageScope } from 'vs/platform/storage/common/storage'; import * as TestUtils from 'vs/test/utils/servicesTestUtils'; import { Memento, Scope } from 'vs/workbench/common/memento'; -import { Storage, InMemoryLocalStorage } from 'vs/workbench/node/storage'; +import { Storage, InMemoryLocalStorage } from 'vs/workbench/common/storage'; suite('Workbench Memento', () => { let context; diff --git a/src/vs/workbench/test/node/storage.test.ts b/src/vs/workbench/test/node/storage.test.ts index 7836d808466..8b8f8eabc6e 100644 --- a/src/vs/workbench/test/node/storage.test.ts +++ b/src/vs/workbench/test/node/storage.test.ts @@ -9,7 +9,7 @@ import * as assert from 'assert'; import { clone } from 'vs/base/common/objects'; import { StorageScope } from 'vs/platform/storage/common/storage'; import { TestContextService, TestWorkspace, TestEnvironmentService } from 'vs/test/utils/servicesTestUtils'; -import { Storage, InMemoryLocalStorage } from 'vs/workbench/node/storage'; +import { Storage, InMemoryLocalStorage } from 'vs/workbench/common/storage'; suite('Workbench Storage', () => {