64 lines
2.8 KiB
Diff
64 lines
2.8 KiB
Diff
|
Prevent state collisions
|
||
|
|
||
|
Previously if you opened different workspaces that had the same filesystem path
|
||
|
(for example if you have /home/coder on two different machines that are both
|
||
|
accessed through the same host) they would conflict with each other. This
|
||
|
ensures that different browser paths will be unique (for example /workspace1 and
|
||
|
/workspace2).
|
||
|
|
||
|
The easiest way to test is to open files in the same workspace using both / and
|
||
|
/vscode and make sure they are not interacting with each other.
|
||
|
|
||
|
It should also migrate old databases which can be tested by opening in an old
|
||
|
code-server.
|
||
|
|
||
|
This has e2e tests.
|
||
|
|
||
|
Index: code-server/lib/vscode/src/vs/platform/storage/browser/storageService.ts
|
||
|
===================================================================
|
||
|
--- code-server.orig/lib/vscode/src/vs/platform/storage/browser/storageService.ts
|
||
|
+++ code-server/lib/vscode/src/vs/platform/storage/browser/storageService.ts
|
||
|
@@ -13,6 +13,7 @@ import { InMemoryStorageDatabase, isStor
|
||
|
import { ILogService } from 'vs/platform/log/common/log';
|
||
|
import { AbstractStorageService, IS_NEW_KEY, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
|
||
|
import { IWorkspaceInitializationPayload } from 'vs/platform/workspaces/common/workspaces';
|
||
|
+import { hash } from 'vs/base/common/hash';
|
||
|
|
||
|
export class BrowserStorageService extends AbstractStorageService {
|
||
|
|
||
|
@@ -36,7 +37,11 @@ export class BrowserStorageService exten
|
||
|
}
|
||
|
|
||
|
private getId(scope: StorageScope): string {
|
||
|
- return scope === StorageScope.GLOBAL ? 'global' : this.payload.id;
|
||
|
+ // Add a unique ID based on the current path for per-workspace databases.
|
||
|
+ // This prevents workspaces on different machines that share the same domain
|
||
|
+ // and file path from colliding (since it does not appear IndexedDB can be
|
||
|
+ // scoped to a path) as long as they are hosted on different paths.
|
||
|
+ return scope === StorageScope.GLOBAL ? 'global' : (this.payload.id + '-' + hash(location.pathname.toString().replace(/\/$/, "")).toString(16));
|
||
|
}
|
||
|
|
||
|
protected async doInitialize(): Promise<void> {
|
||
|
@@ -75,6 +80,21 @@ export class BrowserStorageService exten
|
||
|
const firstWorkspaceOpen = this.workspaceStorage.getBoolean(IS_NEW_KEY);
|
||
|
if (firstWorkspaceOpen === undefined) {
|
||
|
this.workspaceStorage.set(IS_NEW_KEY, true);
|
||
|
+ // Migrate the old database.
|
||
|
+ let db: IIndexedDBStorageDatabase | undefined
|
||
|
+ try {
|
||
|
+ db = await IndexedDBStorageDatabase.create({ id: this.payload.id }, this.logService)
|
||
|
+ const items = await db.getItems()
|
||
|
+ for (const [key, value] of items) {
|
||
|
+ this.workspaceStorage.set(key, value);
|
||
|
+ }
|
||
|
+ } catch (error) {
|
||
|
+ this.logService.error(`[IndexedDB Storage ${this.payload.id}] migrate error: ${toErrorMessage(error)}`);
|
||
|
+ } finally {
|
||
|
+ if (db) {
|
||
|
+ db.close()
|
||
|
+ }
|
||
|
+ }
|
||
|
} else if (firstWorkspaceOpen) {
|
||
|
this.workspaceStorage.set(IS_NEW_KEY, false);
|
||
|
}
|