diff --git a/src/vs/workbench/api/common/extHostMemento.ts b/src/vs/workbench/api/common/extHostMemento.ts new file mode 100644 index 00000000000..3921d40d632 --- /dev/null +++ b/src/vs/workbench/api/common/extHostMemento.ts @@ -0,0 +1,59 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { IDisposable } from 'vs/base/common/lifecycle'; +import { IExtensionMemento } from 'vs/workbench/api/common/extHostExtensionActivator'; +import { ExtHostStorage } from 'vs/workbench/api/common/extHostStorage'; + +export class ExtensionMemento implements IExtensionMemento { + + private readonly _id: string; + private readonly _shared: boolean; + private readonly _storage: ExtHostStorage; + + private readonly _init: Promise; + private _value: { [n: string]: any; }; + private readonly _storageListener: IDisposable; + + constructor(id: string, global: boolean, storage: ExtHostStorage) { + this._id = id; + this._shared = global; + this._storage = storage; + + this._init = this._storage.getValue(this._shared, this._id, Object.create(null)).then(value => { + this._value = value; + return this; + }); + + this._storageListener = this._storage.onDidChangeStorage(e => { + if (e.shared === this._shared && e.key === this._id) { + this._value = e.value; + } + }); + } + + get whenReady(): Promise { + return this._init; + } + + get(key: string, defaultValue: T): T { + let value = this._value[key]; + if (typeof value === 'undefined') { + value = defaultValue; + } + return value; + } + + update(key: string, value: any): Promise { + this._value[key] = value; + return this._storage + .setValue(this._shared, this._id, this._value) + .then(() => true); + } + + dispose(): void { + this._storageListener.dispose(); + } +} diff --git a/src/vs/workbench/api/node/extHostExtensionService.ts b/src/vs/workbench/api/node/extHostExtensionService.ts index 64a819a6ba1..2ae6f86bc2b 100644 --- a/src/vs/workbench/api/node/extHostExtensionService.ts +++ b/src/vs/workbench/api/node/extHostExtensionService.ts @@ -7,15 +7,15 @@ import * as nls from 'vs/nls'; import * as path from 'vs/base/common/path'; import { originalFSPath } from 'vs/base/common/resources'; import { Barrier } from 'vs/base/common/async'; -import { IDisposable, dispose, toDisposable } from 'vs/base/common/lifecycle'; +import { dispose, toDisposable } from 'vs/base/common/lifecycle'; import { TernarySearchTree } from 'vs/base/common/map'; import { URI } from 'vs/base/common/uri'; import * as pfs from 'vs/base/node/pfs'; import { ILogService } from 'vs/platform/log/common/log'; import { createApiFactory, IExtensionApiFactory, NodeModuleRequireInterceptor, VSCodeNodeModuleFactory, KeytarNodeModuleFactory, OpenNodeModuleFactory } from 'vs/workbench/api/node/extHost.api.impl'; -import { ExtHostExtensionServiceShape, IEnvironment, IInitData, IMainContext, MainContext, MainThreadExtensionServiceShape, MainThreadTelemetryShape, MainThreadWorkspaceShape, IStaticWorkspaceData } from 'vs/workbench/api/common/extHost.protocol'; +import { ExtHostExtensionServiceShape, IEnvironment, IInitData, IMainContext, MainContext, MainThreadExtensionServiceShape, MainThreadTelemetryShape, MainThreadWorkspaceShape } from 'vs/workbench/api/common/extHost.protocol'; import { ExtHostConfiguration } from 'vs/workbench/api/common/extHostConfiguration'; -import { ActivatedExtension, EmptyExtension, ExtensionActivatedByAPI, ExtensionActivatedByEvent, ExtensionActivationReason, ExtensionActivationTimes, ExtensionActivationTimesBuilder, ExtensionsActivator, IExtensionAPI, IExtensionContext, IExtensionMemento, IExtensionModule, HostExtension } from 'vs/workbench/api/common/extHostExtensionActivator'; +import { ActivatedExtension, EmptyExtension, ExtensionActivatedByAPI, ExtensionActivatedByEvent, ExtensionActivationReason, ExtensionActivationTimes, ExtensionActivationTimesBuilder, ExtensionsActivator, IExtensionAPI, IExtensionContext, IExtensionModule, HostExtension } from 'vs/workbench/api/common/extHostExtensionActivator'; import { ExtHostLogService } from 'vs/workbench/api/common/extHostLogService'; import { ExtHostStorage } from 'vs/workbench/api/common/extHostStorage'; import { ExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace'; @@ -33,122 +33,8 @@ import { withNullAsUndefined } from 'vs/base/common/types'; import { realpath } from 'vs/base/node/extpath'; import { VSBuffer } from 'vs/base/common/buffer'; import { ISchemeTransformer } from 'vs/workbench/api/common/extHostLanguageFeatures'; - -class ExtensionMemento implements IExtensionMemento { - - private readonly _id: string; - private readonly _shared: boolean; - private readonly _storage: ExtHostStorage; - - private readonly _init: Promise; - private _value: { [n: string]: any; }; - private readonly _storageListener: IDisposable; - - constructor(id: string, global: boolean, storage: ExtHostStorage) { - this._id = id; - this._shared = global; - this._storage = storage; - - this._init = this._storage.getValue(this._shared, this._id, Object.create(null)).then(value => { - this._value = value; - return this; - }); - - this._storageListener = this._storage.onDidChangeStorage(e => { - if (e.shared === this._shared && e.key === this._id) { - this._value = e.value; - } - }); - } - - get whenReady(): Promise { - return this._init; - } - - get(key: string, defaultValue: T): T { - let value = this._value[key]; - if (typeof value === 'undefined') { - value = defaultValue; - } - return value; - } - - update(key: string, value: any): Promise { - this._value[key] = value; - return this._storage - .setValue(this._shared, this._id, this._value) - .then(() => true); - } - - dispose(): void { - this._storageListener.dispose(); - } -} - -class ExtensionStoragePath { - - private readonly _workspace?: IStaticWorkspaceData; - private readonly _environment: IEnvironment; - - private readonly _ready: Promise; - private _value?: string; - - constructor(workspace: IStaticWorkspaceData | undefined, environment: IEnvironment) { - this._workspace = workspace; - this._environment = environment; - this._ready = this._getOrCreateWorkspaceStoragePath().then(value => this._value = value); - } - - get whenReady(): Promise { - return this._ready; - } - - workspaceValue(extension: IExtensionDescription): string | undefined { - if (this._value) { - return path.join(this._value, extension.identifier.value); - } - return undefined; - } - - globalValue(extension: IExtensionDescription): string { - return path.join(this._environment.globalStorageHome.fsPath, extension.identifier.value.toLowerCase()); - } - - private async _getOrCreateWorkspaceStoragePath(): Promise { - if (!this._workspace) { - return Promise.resolve(undefined); - } - - if (!this._environment.appSettingsHome) { - return undefined; - } - const storageName = this._workspace.id; - const storagePath = path.join(this._environment.appSettingsHome.fsPath, 'workspaceStorage', storageName); - - const exists = await pfs.dirExists(storagePath); - - if (exists) { - return storagePath; - } - - try { - await pfs.mkdirp(storagePath); - await pfs.writeFile( - path.join(storagePath, 'meta.json'), - JSON.stringify({ - id: this._workspace.id, - configuration: this._workspace.configuration && URI.revive(this._workspace.configuration).toString(), - name: this._workspace.name - }, undefined, 2) - ); - return storagePath; - - } catch (e) { - console.error(e); - return undefined; - } - } -} +import { ExtensionMemento } from 'vs/workbench/api/common/extHostMemento'; +import { ExtensionStoragePaths } from 'vs/workbench/api/node/extHostStoragePaths'; interface ITestRunner { run(testsRoot: string, clb: (error: Error, failures?: number) => void): void; @@ -174,7 +60,7 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape { private readonly _readyToRunExtensions: Barrier; private readonly _registry: ExtensionDescriptionRegistry; private readonly _storage: ExtHostStorage; - private readonly _storagePath: ExtensionStoragePath; + private readonly _storagePath: ExtensionStoragePaths; private readonly _activator: ExtensionsActivator; private _extensionPathIndex: Promise> | null; private readonly _extensionApiFactory: IExtensionApiFactory; @@ -210,7 +96,7 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape { this._readyToRunExtensions = new Barrier(); this._registry = new ExtensionDescriptionRegistry(initData.extensions); this._storage = new ExtHostStorage(this._extHostContext); - this._storagePath = new ExtensionStoragePath(withNullAsUndefined(initData.workspace), initData.environment); + this._storagePath = new ExtensionStoragePaths(withNullAsUndefined(initData.workspace), initData.environment); const hostExtensions = new Set(); initData.hostExtensions.forEach((extensionId) => hostExtensions.add(ExtensionIdentifier.toKey(extensionId))); diff --git a/src/vs/workbench/api/node/extHostStoragePaths.ts b/src/vs/workbench/api/node/extHostStoragePaths.ts new file mode 100644 index 00000000000..0adb497de02 --- /dev/null +++ b/src/vs/workbench/api/node/extHostStoragePaths.ts @@ -0,0 +1,75 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as path from 'vs/base/common/path'; +import { URI } from 'vs/base/common/uri'; +import * as pfs from 'vs/base/node/pfs'; +import { IEnvironment, IStaticWorkspaceData } from 'vs/workbench/api/common/extHost.protocol'; +import { IExtensionDescription } from 'vs/platform/extensions/common/extensions'; + +export class ExtensionStoragePaths { + + private readonly _workspace?: IStaticWorkspaceData; + private readonly _environment: IEnvironment; + + private readonly _ready: Promise; + private _value?: string; + + constructor(workspace: IStaticWorkspaceData | undefined, environment: IEnvironment) { + this._workspace = workspace; + this._environment = environment; + this._ready = this._getOrCreateWorkspaceStoragePath().then(value => this._value = value); + } + + get whenReady(): Promise { + return this._ready; + } + + workspaceValue(extension: IExtensionDescription): string | undefined { + if (this._value) { + return path.join(this._value, extension.identifier.value); + } + return undefined; + } + + globalValue(extension: IExtensionDescription): string { + return path.join(this._environment.globalStorageHome.fsPath, extension.identifier.value.toLowerCase()); + } + + private async _getOrCreateWorkspaceStoragePath(): Promise { + if (!this._workspace) { + return Promise.resolve(undefined); + } + + if (!this._environment.appSettingsHome) { + return undefined; + } + const storageName = this._workspace.id; + const storagePath = path.join(this._environment.appSettingsHome.fsPath, 'workspaceStorage', storageName); + + const exists = await pfs.dirExists(storagePath); + + if (exists) { + return storagePath; + } + + try { + await pfs.mkdirp(storagePath); + await pfs.writeFile( + path.join(storagePath, 'meta.json'), + JSON.stringify({ + id: this._workspace.id, + configuration: this._workspace.configuration && URI.revive(this._workspace.configuration).toString(), + name: this._workspace.name + }, undefined, 2) + ); + return storagePath; + + } catch (e) { + console.error(e); + return undefined; + } + } +}