mirror of
https://github.com/coder/code-server.git
synced 2026-05-10 14:27:26 +02:00
chore(vscode): update to 1.55.2
This commit is contained in:
@@ -5,13 +5,11 @@
|
||||
|
||||
import { once } from 'vs/base/common/functional';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { ILifecycleMainService, LifecycleMainPhase } from 'vs/platform/lifecycle/electron-main/lifecycleMainService';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { GlobalStorageMain, IStorageMain, IStorageMainOptions, WorkspaceStorageMain } from 'vs/platform/storage/electron-main/storageMain';
|
||||
import { IWindowSettings } from 'vs/platform/windows/common/windows';
|
||||
import { IEmptyWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier, IWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
|
||||
|
||||
export const IStorageMainService = createDecorator<IStorageMainService>('storageMainService');
|
||||
@@ -38,8 +36,7 @@ export class StorageMainService extends Disposable implements IStorageMainServic
|
||||
constructor(
|
||||
@ILogService private readonly logService: ILogService,
|
||||
@IEnvironmentService private readonly environmentService: IEnvironmentService,
|
||||
@ILifecycleMainService private readonly lifecycleMainService: ILifecycleMainService,
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService
|
||||
@ILifecycleMainService private readonly lifecycleMainService: ILifecycleMainService
|
||||
) {
|
||||
super();
|
||||
|
||||
@@ -52,10 +49,6 @@ export class StorageMainService extends Disposable implements IStorageMainServic
|
||||
};
|
||||
}
|
||||
|
||||
protected enableMainWorkspaceStorage(): boolean {
|
||||
return !!(this.configurationService.getValue<IWindowSettings | undefined>('window')?.enableExperimentalMainProcessWorkspaceStorage);
|
||||
}
|
||||
|
||||
private registerListeners(): void {
|
||||
|
||||
// Global Storage: Warmup when any window opens
|
||||
@@ -66,13 +59,11 @@ export class StorageMainService extends Disposable implements IStorageMainServic
|
||||
})();
|
||||
|
||||
// Workspace Storage: Warmup when related window with workspace loads
|
||||
if (this.enableMainWorkspaceStorage()) {
|
||||
this._register(this.lifecycleMainService.onWillLoadWindow(async e => {
|
||||
if (e.workspace) {
|
||||
this.workspaceStorage(e.workspace).init();
|
||||
}
|
||||
}));
|
||||
}
|
||||
this._register(this.lifecycleMainService.onWillLoadWindow(async e => {
|
||||
if (e.workspace) {
|
||||
this.workspaceStorage(e.workspace).init();
|
||||
}
|
||||
}));
|
||||
|
||||
// All Storage: Close when shutting down
|
||||
this._register(this.lifecycleMainService.onWillShutdown(e => {
|
||||
|
||||
@@ -14,7 +14,7 @@ import { IMainProcessService } from 'vs/platform/ipc/electron-sandbox/services';
|
||||
import { StorageDatabaseChannelClient } from 'vs/platform/storage/common/storageIpc';
|
||||
import { joinPath } from 'vs/base/common/resources';
|
||||
|
||||
export class NativeStorageService2 extends AbstractStorageService {
|
||||
export class NativeStorageService extends AbstractStorageService {
|
||||
|
||||
// Global Storage is readonly and shared across windows
|
||||
private readonly globalStorage: IStorage;
|
||||
@@ -85,7 +85,7 @@ export class NativeStorageService2 extends AbstractStorageService {
|
||||
}
|
||||
|
||||
protected getLogDetails(scope: StorageScope): string | undefined {
|
||||
return scope === StorageScope.GLOBAL ? this.environmentService.globalStorageHome.fsPath : this.workspaceStorageId ? `${joinPath(this.environmentService.workspaceStorageHome, this.workspaceStorageId, 'state.vscdb').fsPath} [!!! Experimental Main Storage !!!]` : undefined;
|
||||
return scope === StorageScope.GLOBAL ? this.environmentService.globalStorageHome.fsPath : this.workspaceStorageId ? `${joinPath(this.environmentService.workspaceStorageHome, this.workspaceStorageId, 'state.vscdb').fsPath}` : undefined;
|
||||
}
|
||||
|
||||
async close(): Promise<void> {
|
||||
@@ -1,198 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { promises } from 'fs';
|
||||
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import { ILogService, LogLevel } from 'vs/platform/log/common/log';
|
||||
import { StorageScope, WillSaveStateReason, IS_NEW_KEY, AbstractStorageService } from 'vs/platform/storage/common/storage';
|
||||
import { SQLiteStorageDatabase, ISQLiteStorageDatabaseLoggingOptions } from 'vs/base/parts/storage/node/storage';
|
||||
import { Storage, IStorageDatabase, IStorage, StorageHint } from 'vs/base/parts/storage/common/storage';
|
||||
import { mark } from 'vs/base/common/performance';
|
||||
import { join } from 'vs/base/common/path';
|
||||
import { copy, exists, writeFile } from 'vs/base/node/pfs';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { isSingleFolderWorkspaceIdentifier, isWorkspaceIdentifier, IWorkspaceInitializationPayload } from 'vs/platform/workspaces/common/workspaces';
|
||||
import { assertIsDefined } from 'vs/base/common/types';
|
||||
import { Promises } from 'vs/base/common/async';
|
||||
|
||||
export class NativeStorageService extends AbstractStorageService {
|
||||
|
||||
private static readonly WORKSPACE_STORAGE_NAME = 'state.vscdb';
|
||||
private static readonly WORKSPACE_META_NAME = 'workspace.json';
|
||||
|
||||
private readonly globalStorage = new Storage(this.globalStorageDatabase);
|
||||
|
||||
private workspaceStoragePath: string | undefined;
|
||||
private workspaceStorage: IStorage | undefined;
|
||||
private workspaceStorageListener: IDisposable | undefined;
|
||||
|
||||
constructor(
|
||||
private globalStorageDatabase: IStorageDatabase,
|
||||
private payload: IWorkspaceInitializationPayload | undefined,
|
||||
@ILogService private readonly logService: ILogService,
|
||||
@IEnvironmentService private readonly environmentService: IEnvironmentService
|
||||
) {
|
||||
super();
|
||||
|
||||
this.registerListeners();
|
||||
}
|
||||
|
||||
private registerListeners(): void {
|
||||
|
||||
// Global Storage change events
|
||||
this._register(this.globalStorage.onDidChangeStorage(key => this.emitDidChangeValue(StorageScope.GLOBAL, key)));
|
||||
}
|
||||
|
||||
protected async doInitialize(): Promise<void> {
|
||||
|
||||
// Init all storage locations
|
||||
await Promises.settled([
|
||||
this.initializeGlobalStorage(),
|
||||
this.payload ? this.initializeWorkspaceStorage(this.payload) : Promise.resolve()
|
||||
]);
|
||||
}
|
||||
|
||||
private initializeGlobalStorage(): Promise<void> {
|
||||
return this.globalStorage.init();
|
||||
}
|
||||
|
||||
private async initializeWorkspaceStorage(payload: IWorkspaceInitializationPayload): Promise<void> {
|
||||
|
||||
// Prepare workspace storage folder for DB
|
||||
try {
|
||||
const result = await this.prepareWorkspaceStorageFolder(payload);
|
||||
|
||||
const useInMemoryStorage = !!this.environmentService.extensionTestsLocationURI; // no storage during extension tests!
|
||||
|
||||
// Create workspace storage and initialize
|
||||
mark('code/willInitWorkspaceStorage');
|
||||
try {
|
||||
const workspaceStorage = this.createWorkspaceStorage(
|
||||
useInMemoryStorage ? SQLiteStorageDatabase.IN_MEMORY_PATH : join(result.path, NativeStorageService.WORKSPACE_STORAGE_NAME),
|
||||
result.wasCreated ? StorageHint.STORAGE_DOES_NOT_EXIST : undefined
|
||||
);
|
||||
await workspaceStorage.init();
|
||||
|
||||
// Check to see if this is the first time we are "opening" this workspace
|
||||
const firstWorkspaceOpen = workspaceStorage.getBoolean(IS_NEW_KEY);
|
||||
if (firstWorkspaceOpen === undefined) {
|
||||
workspaceStorage.set(IS_NEW_KEY, result.wasCreated);
|
||||
} else if (firstWorkspaceOpen) {
|
||||
workspaceStorage.set(IS_NEW_KEY, false);
|
||||
}
|
||||
} finally {
|
||||
mark('code/didInitWorkspaceStorage');
|
||||
}
|
||||
} catch (error) {
|
||||
this.logService.error(`[storage] initializeWorkspaceStorage(): Unable to init workspace storage due to ${error}`);
|
||||
}
|
||||
}
|
||||
|
||||
private createWorkspaceStorage(workspaceStoragePath: string, hint?: StorageHint): IStorage {
|
||||
|
||||
// Logger for workspace storage
|
||||
const workspaceLoggingOptions: ISQLiteStorageDatabaseLoggingOptions = {
|
||||
logTrace: (this.logService.getLevel() === LogLevel.Trace) ? msg => this.logService.trace(msg) : undefined,
|
||||
logError: error => this.logService.error(error)
|
||||
};
|
||||
|
||||
// Dispose old (if any)
|
||||
dispose(this.workspaceStorage);
|
||||
dispose(this.workspaceStorageListener);
|
||||
|
||||
// Create new
|
||||
this.workspaceStoragePath = workspaceStoragePath;
|
||||
this.workspaceStorage = new Storage(new SQLiteStorageDatabase(workspaceStoragePath, { logging: workspaceLoggingOptions }), { hint });
|
||||
this.workspaceStorageListener = this.workspaceStorage.onDidChangeStorage(key => this.emitDidChangeValue(StorageScope.WORKSPACE, key));
|
||||
|
||||
return this.workspaceStorage;
|
||||
}
|
||||
|
||||
private getWorkspaceStorageFolderPath(payload: IWorkspaceInitializationPayload): string {
|
||||
return join(this.environmentService.workspaceStorageHome.fsPath, payload.id); // workspace home + workspace id;
|
||||
}
|
||||
|
||||
private async prepareWorkspaceStorageFolder(payload: IWorkspaceInitializationPayload): Promise<{ path: string, wasCreated: boolean }> {
|
||||
const workspaceStorageFolderPath = this.getWorkspaceStorageFolderPath(payload);
|
||||
|
||||
const storageExists = await exists(workspaceStorageFolderPath);
|
||||
if (storageExists) {
|
||||
return { path: workspaceStorageFolderPath, wasCreated: false };
|
||||
}
|
||||
|
||||
await promises.mkdir(workspaceStorageFolderPath, { recursive: true });
|
||||
|
||||
// Write metadata into folder
|
||||
this.ensureWorkspaceStorageFolderMeta(payload);
|
||||
|
||||
return { path: workspaceStorageFolderPath, wasCreated: true };
|
||||
}
|
||||
|
||||
private ensureWorkspaceStorageFolderMeta(payload: IWorkspaceInitializationPayload): void {
|
||||
let meta: object | undefined = undefined;
|
||||
if (isSingleFolderWorkspaceIdentifier(payload)) {
|
||||
meta = { folder: payload.uri.toString() };
|
||||
} else if (isWorkspaceIdentifier(payload)) {
|
||||
meta = { workspace: payload.configPath.toString() };
|
||||
}
|
||||
|
||||
if (meta) {
|
||||
(async () => {
|
||||
try {
|
||||
const workspaceStorageMetaPath = join(this.getWorkspaceStorageFolderPath(payload), NativeStorageService.WORKSPACE_META_NAME);
|
||||
const storageExists = await exists(workspaceStorageMetaPath);
|
||||
if (!storageExists) {
|
||||
await writeFile(workspaceStorageMetaPath, JSON.stringify(meta, undefined, 2));
|
||||
}
|
||||
} catch (error) {
|
||||
this.logService.error(error);
|
||||
}
|
||||
})();
|
||||
}
|
||||
}
|
||||
|
||||
protected getStorage(scope: StorageScope): IStorage | undefined {
|
||||
return scope === StorageScope.GLOBAL ? this.globalStorage : this.workspaceStorage;
|
||||
}
|
||||
|
||||
protected getLogDetails(scope: StorageScope): string | undefined {
|
||||
return scope === StorageScope.GLOBAL ? this.environmentService.globalStorageHome.fsPath : this.workspaceStoragePath;
|
||||
}
|
||||
|
||||
async close(): Promise<void> {
|
||||
|
||||
// Stop periodic scheduler and idle runner as we now collect state normally
|
||||
this.stopFlushWhenIdle();
|
||||
|
||||
// Signal as event so that clients can still store data
|
||||
this.emitWillSaveState(WillSaveStateReason.SHUTDOWN);
|
||||
|
||||
// Do it
|
||||
await Promises.settled([
|
||||
this.globalStorage.close(),
|
||||
this.workspaceStorage ? this.workspaceStorage.close() : Promise.resolve()
|
||||
]);
|
||||
}
|
||||
|
||||
async migrate(toWorkspace: IWorkspaceInitializationPayload): Promise<void> {
|
||||
if (this.workspaceStoragePath === SQLiteStorageDatabase.IN_MEMORY_PATH) {
|
||||
return; // no migration needed if running in memory
|
||||
}
|
||||
|
||||
// Close workspace DB to be able to copy
|
||||
await this.workspaceStorage?.close();
|
||||
|
||||
// Prepare new workspace storage folder
|
||||
const result = await this.prepareWorkspaceStorageFolder(toWorkspace);
|
||||
|
||||
const newWorkspaceStoragePath = join(result.path, NativeStorageService.WORKSPACE_STORAGE_NAME);
|
||||
|
||||
// Copy current storage over to new workspace storage
|
||||
await copy(assertIsDefined(this.workspaceStoragePath), newWorkspaceStoragePath, { preserveSymlinks: false });
|
||||
|
||||
// Recreate and init workspace storage
|
||||
return this.createWorkspaceStorage(newWorkspaceStoragePath).init();
|
||||
}
|
||||
}
|
||||
@@ -17,10 +17,13 @@ import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { NativeParsedArgs } from 'vs/platform/environment/common/argv';
|
||||
import { ICodeWindow } from 'vs/platform/windows/electron-main/windows';
|
||||
import { Promises } from 'vs/base/common/async';
|
||||
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
|
||||
import product from 'vs/platform/product/common/product';
|
||||
import { IProductService } from 'vs/platform/product/common/productService';
|
||||
|
||||
suite('StorageMainService', function () {
|
||||
|
||||
const productService: IProductService = { _serviceBrand: undefined, ...product };
|
||||
|
||||
class TestStorageMainService extends StorageMainService {
|
||||
|
||||
protected getStorageOptions(): IStorageMainOptions {
|
||||
@@ -28,10 +31,6 @@ suite('StorageMainService', function () {
|
||||
useInMemoryStorage: true
|
||||
};
|
||||
}
|
||||
|
||||
protected enableMainWorkspaceStorage(): boolean {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class StorageTestLifecycleMainService implements ILifecycleMainService {
|
||||
@@ -48,9 +47,7 @@ suite('StorageMainService', function () {
|
||||
|
||||
this._onWillShutdown.fire({
|
||||
join(promise) {
|
||||
if (promise) {
|
||||
joiners.push(promise);
|
||||
}
|
||||
joiners.push(promise);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -129,14 +126,14 @@ suite('StorageMainService', function () {
|
||||
}
|
||||
|
||||
test('basics (global)', function () {
|
||||
const storageMainService = new TestStorageMainService(new NullLogService(), new NativeEnvironmentService(parseArgs(process.argv, OPTIONS)), new StorageTestLifecycleMainService(), new TestConfigurationService());
|
||||
const storageMainService = new TestStorageMainService(new NullLogService(), new NativeEnvironmentService(parseArgs(process.argv, OPTIONS), productService), new StorageTestLifecycleMainService());
|
||||
|
||||
return testStorage(storageMainService.globalStorage, true);
|
||||
});
|
||||
|
||||
test('basics (workspace)', function () {
|
||||
const workspace = { id: generateUuid() };
|
||||
const storageMainService = new TestStorageMainService(new NullLogService(), new NativeEnvironmentService(parseArgs(process.argv, OPTIONS)), new StorageTestLifecycleMainService(), new TestConfigurationService());
|
||||
const storageMainService = new TestStorageMainService(new NullLogService(), new NativeEnvironmentService(parseArgs(process.argv, OPTIONS), productService), new StorageTestLifecycleMainService());
|
||||
|
||||
return testStorage(storageMainService.workspaceStorage(workspace), false);
|
||||
});
|
||||
@@ -144,7 +141,7 @@ suite('StorageMainService', function () {
|
||||
test('storage closed onWillShutdown', async function () {
|
||||
const lifecycleMainService = new StorageTestLifecycleMainService();
|
||||
const workspace = { id: generateUuid() };
|
||||
const storageMainService = new TestStorageMainService(new NullLogService(), new NativeEnvironmentService(parseArgs(process.argv, OPTIONS)), lifecycleMainService, new TestConfigurationService());
|
||||
const storageMainService = new TestStorageMainService(new NullLogService(), new NativeEnvironmentService(parseArgs(process.argv, OPTIONS), productService), lifecycleMainService);
|
||||
|
||||
let workspaceStorage = storageMainService.workspaceStorage(workspace);
|
||||
let didCloseWorkspaceStorage = false;
|
||||
@@ -175,7 +172,7 @@ suite('StorageMainService', function () {
|
||||
});
|
||||
|
||||
test('storage closed before init works', async function () {
|
||||
const storageMainService = new TestStorageMainService(new NullLogService(), new NativeEnvironmentService(parseArgs(process.argv, OPTIONS)), new StorageTestLifecycleMainService(), new TestConfigurationService());
|
||||
const storageMainService = new TestStorageMainService(new NullLogService(), new NativeEnvironmentService(parseArgs(process.argv, OPTIONS), productService), new StorageTestLifecycleMainService());
|
||||
const workspace = { id: generateUuid() };
|
||||
|
||||
let workspaceStorage = storageMainService.workspaceStorage(workspace);
|
||||
@@ -198,7 +195,7 @@ suite('StorageMainService', function () {
|
||||
});
|
||||
|
||||
test('storage closed before init awaits works', async function () {
|
||||
const storageMainService = new TestStorageMainService(new NullLogService(), new NativeEnvironmentService(parseArgs(process.argv, OPTIONS)), new StorageTestLifecycleMainService(), new TestConfigurationService());
|
||||
const storageMainService = new TestStorageMainService(new NullLogService(), new NativeEnvironmentService(parseArgs(process.argv, OPTIONS), productService), new StorageTestLifecycleMainService());
|
||||
const workspace = { id: generateUuid() };
|
||||
|
||||
let workspaceStorage = storageMainService.workspaceStorage(workspace);
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { strictEqual } from 'assert';
|
||||
import { StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
|
||||
import { NativeStorageService } from 'vs/platform/storage/node/storageService';
|
||||
import { tmpdir } from 'os';
|
||||
import { promises } from 'fs';
|
||||
import { rimraf } from 'vs/base/node/pfs';
|
||||
import { NullLogService } from 'vs/platform/log/common/log';
|
||||
import { NativeEnvironmentService } from 'vs/platform/environment/node/environmentService';
|
||||
import { parseArgs, OPTIONS } from 'vs/platform/environment/node/argv';
|
||||
import { InMemoryStorageDatabase } from 'vs/base/parts/storage/common/storage';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { flakySuite, getRandomTestPath } from 'vs/base/test/node/testUtils';
|
||||
import { createSuite } from 'vs/platform/storage/test/common/storageService.test';
|
||||
|
||||
flakySuite('StorageService (native)', function () {
|
||||
|
||||
class StorageTestEnvironmentService extends NativeEnvironmentService {
|
||||
|
||||
constructor(private workspaceStorageFolderPath: URI, private _extensionsPath: string) {
|
||||
super(parseArgs(process.argv, OPTIONS));
|
||||
}
|
||||
|
||||
get workspaceStorageHome(): URI {
|
||||
return this.workspaceStorageFolderPath;
|
||||
}
|
||||
|
||||
get extensionsPath(): string {
|
||||
return this._extensionsPath;
|
||||
}
|
||||
}
|
||||
|
||||
let testDir: string;
|
||||
|
||||
createSuite<NativeStorageService>({
|
||||
setup: async () => {
|
||||
testDir = getRandomTestPath(tmpdir(), 'vsctests', 'storageservice');
|
||||
|
||||
await promises.mkdir(testDir, { recursive: true });
|
||||
|
||||
const storageService = new NativeStorageService(new InMemoryStorageDatabase(), { id: String(Date.now()) }, new NullLogService(), new StorageTestEnvironmentService(URI.file(testDir), testDir));
|
||||
await storageService.initialize();
|
||||
|
||||
return storageService;
|
||||
},
|
||||
teardown: async storageService => {
|
||||
await storageService.close();
|
||||
|
||||
return rimraf(testDir);
|
||||
}
|
||||
});
|
||||
|
||||
test('Migrate Data', async function () {
|
||||
const storage = new NativeStorageService(new InMemoryStorageDatabase(), { id: String(Date.now()) }, new NullLogService(), new StorageTestEnvironmentService(URI.file(testDir), testDir));
|
||||
await storage.initialize();
|
||||
|
||||
storage.store('bar', 'foo', StorageScope.WORKSPACE, StorageTarget.MACHINE);
|
||||
storage.store('barNumber', 55, StorageScope.WORKSPACE, StorageTarget.MACHINE);
|
||||
storage.store('barBoolean', true, StorageScope.GLOBAL, StorageTarget.MACHINE);
|
||||
|
||||
strictEqual(storage.get('bar', StorageScope.WORKSPACE), 'foo');
|
||||
strictEqual(storage.getNumber('barNumber', StorageScope.WORKSPACE), 55);
|
||||
strictEqual(storage.getBoolean('barBoolean', StorageScope.GLOBAL), true);
|
||||
|
||||
await storage.migrate({ id: String(Date.now() + 100) });
|
||||
|
||||
strictEqual(storage.get('bar', StorageScope.WORKSPACE), 'foo');
|
||||
strictEqual(storage.getNumber('barNumber', StorageScope.WORKSPACE), 55);
|
||||
strictEqual(storage.getBoolean('barBoolean', StorageScope.GLOBAL), true);
|
||||
|
||||
await storage.close();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user