Skip to content

Commit

Permalink
Go through storage service for edit session payload
Browse files Browse the repository at this point in the history
  • Loading branch information
joyceerhl authored Apr 19, 2023
1 parent 0724039 commit 22523dd
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 22 deletions.
29 changes: 28 additions & 1 deletion src/vs/platform/storage/common/storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,14 @@ export const enum StorageScope {
/**
* The stored data will be scoped to the current workspace.
*/
WORKSPACE = 1
WORKSPACE = 1,

/**
* The stored data will be scoped to workspaces which share the same edit session identity.
* Note, this is actually represented by {@link StorageScope.WORKSPACE} and {@link StorageTarget.USER},
* but there are already adoptions of that pairing which need to be migrated.
*/
ROAMABLE_WORKSPACE = 2,
}

export const enum StorageTarget {
Expand Down Expand Up @@ -334,6 +341,9 @@ export abstract class AbstractStorageService extends Disposable implements IStor
case StorageScope.PROFILE:
this._profileKeyTargets = undefined;
break;
case StorageScope.ROAMABLE_WORKSPACE:
this._roamableWorkspaceKeyTargets = undefined;
break;
case StorageScope.WORKSPACE:
this._workspaceKeyTargets = undefined;
break;
Expand Down Expand Up @@ -462,6 +472,15 @@ export abstract class AbstractStorageService extends Disposable implements IStor
return this._workspaceKeyTargets;
}

private _roamableWorkspaceKeyTargets: IKeyTargets | undefined = undefined;
private get roamableWorkspaceKeyTargets(): IKeyTargets {
if (!this._roamableWorkspaceKeyTargets) {
this._roamableWorkspaceKeyTargets = this.loadKeyTargets(StorageScope.ROAMABLE_WORKSPACE);
}

return this._roamableWorkspaceKeyTargets;
}

private _profileKeyTargets: IKeyTargets | undefined = undefined;
private get profileKeyTargets(): IKeyTargets {
if (!this._profileKeyTargets) {
Expand All @@ -486,6 +505,8 @@ export abstract class AbstractStorageService extends Disposable implements IStor
return this.applicationKeyTargets;
case StorageScope.PROFILE:
return this.profileKeyTargets;
case StorageScope.ROAMABLE_WORKSPACE:
return this.roamableWorkspaceKeyTargets;
default:
return this.workspaceKeyTargets;
}
Expand Down Expand Up @@ -626,13 +647,15 @@ export class InMemoryStorageService extends AbstractStorageService {
private readonly applicationStorage = this._register(new Storage(new InMemoryStorageDatabase(), { hint: StorageHint.STORAGE_IN_MEMORY }));
private readonly profileStorage = this._register(new Storage(new InMemoryStorageDatabase(), { hint: StorageHint.STORAGE_IN_MEMORY }));
private readonly workspaceStorage = this._register(new Storage(new InMemoryStorageDatabase(), { hint: StorageHint.STORAGE_IN_MEMORY }));
private readonly roamableWorkspaceStorage = this._register(new Storage(new InMemoryStorageDatabase(), { hint: StorageHint.STORAGE_IN_MEMORY }));

constructor() {
super();

this._register(this.workspaceStorage.onDidChangeStorage(key => this.emitDidChangeValue(StorageScope.WORKSPACE, key)));
this._register(this.profileStorage.onDidChangeStorage(key => this.emitDidChangeValue(StorageScope.PROFILE, key)));
this._register(this.applicationStorage.onDidChangeStorage(key => this.emitDidChangeValue(StorageScope.APPLICATION, key)));
this._register(this.roamableWorkspaceStorage.onDidChangeStorage(key => this.emitDidChangeValue(StorageScope.ROAMABLE_WORKSPACE, key)));
}

protected getStorage(scope: StorageScope): IStorage {
Expand All @@ -641,6 +664,8 @@ export class InMemoryStorageService extends AbstractStorageService {
return this.applicationStorage;
case StorageScope.PROFILE:
return this.profileStorage;
case StorageScope.ROAMABLE_WORKSPACE:
return this.roamableWorkspaceStorage;
default:
return this.workspaceStorage;
}
Expand All @@ -652,6 +677,8 @@ export class InMemoryStorageService extends AbstractStorageService {
return 'inMemory (application)';
case StorageScope.PROFILE:
return 'inMemory (profile)';
case StorageScope.ROAMABLE_WORKSPACE:
return 'inMemory (roamable workspace)';
default:
return 'inMemory (workspace)';
}
Expand Down
3 changes: 3 additions & 0 deletions src/vs/workbench/common/memento.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ export class Memento {

return applicationMemento.getMemento();
}

case StorageScope.ROAMABLE_WORKSPACE:
throw new Error('Not implemented');
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ import { CancellationError } from 'vs/base/common/errors';
import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
import { IExtensionsViewPaneContainer, VIEWLET_ID } from 'vs/workbench/contrib/extensions/common/extensions';
import { IPaneCompositePartService } from 'vs/workbench/services/panecomposite/browser/panecomposite';
import { EditSessionRegistry } from 'vs/platform/workspace/browser/editSessionsStorageService';

registerSingleton(IEditSessionsLogService, EditSessionsLogService, InstantiationType.Delayed);
registerSingleton(IEditSessionsStorageService, EditSessionsWorkbenchService, InstantiationType.Delayed);
Expand Down Expand Up @@ -641,23 +640,29 @@ export class EditSessionsContribution extends Disposable implements IWorkbenchCo
}
}

EditSessionRegistry.getEditSessionContributions().forEach(([key, contrib]) => {
const state = editSession.state[key];
if (state) {
contributedStateHandlers.push(() => contrib.resumeState(state, (incomingUri: URI) => {
for (const absoluteUri of incomingFolderUrisToIdentifiers.keys()) {
if (isEqualOrParent(incomingUri, URI.parse(absoluteUri))) {
const [workspaceFolderUri, match] = incomingFolderUrisToIdentifiers.get(absoluteUri)!;
if (match === EditSessionIdentityMatch.Complete) {
const relativeFilePath = relativePath(URI.parse(absoluteUri), incomingUri);
return relativeFilePath ? joinPath(URI.parse(workspaceFolderUri), relativeFilePath) : incomingUri;
}

}
const resolveUri = (incomingUri: URI) => {
for (const absoluteUri of incomingFolderUrisToIdentifiers.keys()) {
if (isEqualOrParent(incomingUri, URI.parse(absoluteUri))) {
const [workspaceFolderUri, match] = incomingFolderUrisToIdentifiers.get(absoluteUri)!;
if (match === EditSessionIdentityMatch.Complete) {
const relativeFilePath = relativePath(URI.parse(absoluteUri), incomingUri);
return relativeFilePath ? joinPath(URI.parse(workspaceFolderUri), relativeFilePath) : incomingUri;
}
return incomingUri;
}));

}
}
return incomingUri;
};

Object.entries(editSession.state).forEach(([key, state]) => {
try {
const deserializedState = JSON.parse(state);
if (typeof deserializedState === 'object' && deserializedState && 'absoluteUris' in deserializedState) {
const convertedUris = deserializedState.absoluteUris.map((uri: string) => resolveUri(URI.parse(uri)));
state = JSON.stringify({ ...deserializedState, convertedUris });
}
this.storageService.store(key, state, StorageScope.ROAMABLE_WORKSPACE, StorageTarget.USER);
} catch (ex) { }
});

return { changes, conflictingChanges, contributedStateHandlers };
Expand Down Expand Up @@ -748,9 +753,12 @@ export class EditSessionsContribution extends Disposable implements IWorkbenchCo
}

// Look through all registered contributions to gather additional state
const contributedData: { [key: string]: unknown } = {};
EditSessionRegistry.getEditSessionContributions().forEach(([key, contrib]) => {
contributedData[key] = contrib.getStateToStore();
const contributedData: { [key: string]: string } = {};
this.storageService.keys(StorageScope.ROAMABLE_WORKSPACE, StorageTarget.USER).forEach((key) => {
const state = this.storageService.get(key, StorageScope.ROAMABLE_WORKSPACE);
if (typeof state === 'string') {
contributedData[key] = state;
}
});

if (!hasEdits) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ export interface EditSession {
version: number;
machine?: string;
folders: Folder[];
state: { [key: string]: unknown };
state: { [key: string]: string };
}

export const EDIT_SESSIONS_SIGNED_IN_KEY = 'editSessionsSignedIn';
Expand Down
29 changes: 28 additions & 1 deletion src/vs/workbench/contrib/scm/common/scmService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ class SCMInput implements ISCMInput {
private readonly _onDidChangeValidateInput = new Emitter<void>();
readonly onDidChangeValidateInput: Event<void> = this._onDidChangeValidateInput.event;

private static readonly roamableWorkspaceInputKey = 'scmInputHistory';

private historyNavigator: HistoryNavigator2<string>;
private didChangeHistory: boolean;

Expand Down Expand Up @@ -191,10 +193,35 @@ class SCMInput implements ISCMInput {
if (history.length === 0 || (history.length === 1 && history[0] === '')) {
storageService.remove(key, StorageScope.APPLICATION);
} else {
storageService.store(key, JSON.stringify({ timestamp: new Date().getTime(), history }), StorageScope.APPLICATION, StorageTarget.MACHINE);
const timestamp = new Date().getTime();
storageService.store(key, JSON.stringify({ timestamp: timestamp, history }), StorageScope.APPLICATION, StorageTarget.MACHINE);
storageService.store(SCMInput.roamableWorkspaceInputKey,
JSON.stringify({
absoluteUris: [this.repository.provider.rootUri!.toString()],
timestamp: timestamp,
history
}),
StorageScope.ROAMABLE_WORKSPACE,
StorageTarget.USER
);
}
this.didChangeHistory = false;
});

this.storageService.onDidChangeValue((e) => {
if (e.scope === StorageScope.ROAMABLE_WORKSPACE && e.target === StorageTarget.USER && e.key === SCMInput.roamableWorkspaceInputKey) {
const value = this.storageService.get(e.key, StorageScope.ROAMABLE_WORKSPACE);
if (value) {
const deserializedHistory = JSON.parse(value);
if (deserializedHistory.convertedUris[0] === this.repository.provider.rootUri!.toString()) {
for (const item of deserializedHistory.history) {
this.historyNavigator.add(item);
}
this._value = deserializedHistory.history[deserializedHistory.history.length - 1];
}
}
}
});
}
}

Expand Down

0 comments on commit 22523dd

Please sign in to comment.