Skip to content

Commit

Permalink
restore history entries gracefully
Browse files Browse the repository at this point in the history
  • Loading branch information
aeschli committed Jul 11, 2019
1 parent 55737ac commit b1621c1
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 23 deletions.
36 changes: 22 additions & 14 deletions src/vs/platform/history/common/historyStorage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { UriComponents, URI } from 'vs/base/common/uri';
import { IRecentlyOpened, isRecentFolder } from 'vs/platform/history/common/history';
import { ILogService } from 'vs/platform/log/common/log';

interface ISerializedRecentlyOpened {
workspaces3: Array<ISerializedWorkspace | string>; // workspace or URI.toString() // added in 1.32
Expand Down Expand Up @@ -31,32 +32,41 @@ function isUriComponents(curr: any): curr is UriComponents {

export type RecentlyOpenedStorageData = object;

export function restoreRecentlyOpened(data: RecentlyOpenedStorageData | undefined): IRecentlyOpened {
export function restoreRecentlyOpened(data: RecentlyOpenedStorageData | undefined, logService: ILogService): IRecentlyOpened {
const result: IRecentlyOpened = { workspaces: [], files: [] };
if (data) {
const restoreGracefully = function <T>(entries: T[], func: (entry: T, index: number) => void) {
for (let i = 0; i < entries.length; i++) {
try {
func(entries[i], i);
} catch (e) {
logService.warn(`Error restoring recent entry ${JSON.stringify(entries[i])}: ${e.toString()}. Skip entry.`);
}
}
};

const storedRecents = data as ISerializedRecentlyOpened & ILegacySerializedRecentlyOpened;
if (Array.isArray(storedRecents.workspaces3)) {
for (let i = 0; i < storedRecents.workspaces3.length; i++) {
const workspace = storedRecents.workspaces3[i];
restoreGracefully(storedRecents.workspaces3, (workspace, i) => {
const label: string | undefined = (Array.isArray(storedRecents.workspaceLabels) && storedRecents.workspaceLabels[i]) || undefined;
if (typeof workspace === 'object' && typeof workspace.id === 'string' && typeof workspace.configURIPath === 'string') {
result.workspaces.push({ label, workspace: { id: workspace.id, configPath: URI.parse(workspace.configURIPath) } });
} else if (typeof workspace === 'string') {
result.workspaces.push({ label, folderUri: URI.parse(workspace) });
}
}
});
} else if (Array.isArray(storedRecents.workspaces2)) {
for (const workspace of storedRecents.workspaces2) {
restoreGracefully(storedRecents.workspaces2, workspace => {
if (typeof workspace === 'object' && typeof workspace.id === 'string' && typeof workspace.configPath === 'string') {
result.workspaces.push({ workspace: { id: workspace.id, configPath: URI.file(workspace.configPath) } });
} else if (typeof workspace === 'string') {
result.workspaces.push({ folderUri: URI.parse(workspace) });
}
}
});
} else if (Array.isArray(storedRecents.workspaces)) {
// TODO@martin legacy support can be removed at some point (6 month?)
// format of 1.25 and before
for (const workspace of storedRecents.workspaces) {
restoreGracefully(storedRecents.workspaces, workspace => {
if (typeof workspace === 'string') {
result.workspaces.push({ folderUri: URI.file(workspace) });
} else if (isLegacySerializedWorkspace(workspace)) {
Expand All @@ -65,23 +75,21 @@ export function restoreRecentlyOpened(data: RecentlyOpenedStorageData | undefine
// added by 1.26-insiders
result.workspaces.push({ folderUri: URI.revive(<UriComponents>workspace) });
}
}
});
}

if (Array.isArray(storedRecents.files2)) {
for (let i = 0; i < storedRecents.files2.length; i++) {
const file = storedRecents.files2[i];
restoreGracefully(storedRecents.files2, (file, i) => {
const label: string | undefined = (Array.isArray(storedRecents.fileLabels) && storedRecents.fileLabels[i]) || undefined;
if (typeof file === 'string') {
result.files.push({ label, fileUri: URI.parse(file) });
}
}
});
} else if (Array.isArray(storedRecents.files)) {
for (const file of storedRecents.files) {
restoreGracefully(storedRecents.files, file => {
if (typeof file === 'string') {
result.files.push({ fileUri: URI.file(file) });
}
}
});
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ export class HistoryMainService implements IHistoryMainService {
private getRecentlyOpenedFromStorage(): IRecentlyOpened {
const storedRecents = this.stateService.getItem<RecentlyOpenedStorageData>(HistoryMainService.recentlyOpenedStorageKey);

return restoreRecentlyOpened(storedRecents);
return restoreRecentlyOpened(storedRecents, this.logService);
}

private saveRecentlyOpened(recent: IRecentlyOpened): void {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { IWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
import { URI } from 'vs/base/common/uri';
import { IRecentlyOpened, isRecentFolder, IRecentFolder, IRecentWorkspace } from 'vs/platform/history/common/history';
import { toStoreData, restoreRecentlyOpened } from 'vs/platform/history/common/historyStorage';
import { NullLogService } from 'vs/platform/log/common/log';

function toWorkspace(uri: URI): IWorkspaceIdentifier {
return {
Expand Down Expand Up @@ -51,7 +52,7 @@ function assertEqualRecentlyOpened(actual: IRecentlyOpened, expected: IRecentlyO

function assertRestoring(state: IRecentlyOpened, message?: string) {
const stored = toStoreData(state);
const restored = restoreRecentlyOpened(stored);
const restored = restoreRecentlyOpened(stored, new NullLogService());
assertEqualRecentlyOpened(state, restored, message);
}

Expand Down Expand Up @@ -118,7 +119,7 @@ suite('History Storage', () => {
]
}`;

let actual = restoreRecentlyOpened(JSON.parse(v1_25_win));
let actual = restoreRecentlyOpened(JSON.parse(v1_25_win), new NullLogService());
let expected: IRecentlyOpened = {
files: [{ fileUri: URI.file('C:\\workspaces\\test.code-workspace') }, { fileUri: URI.file('C:\\workspaces\\testing\\test-ext\\.gitignore') }],
workspaces: [
Expand Down Expand Up @@ -146,7 +147,7 @@ suite('History Storage', () => {
]
}`;

let actual = restoreRecentlyOpened(JSON.parse(v1_31_win));
let actual = restoreRecentlyOpened(JSON.parse(v1_31_win), new NullLogService());
let expected: IRecentlyOpened = {
files: [{ fileUri: URI.parse('file:///c%3A/workspaces/vscode/.yarnrc') }],
workspaces: [
Expand All @@ -173,7 +174,7 @@ suite('History Storage', () => {
]
}`;

let windowsState = restoreRecentlyOpened(JSON.parse(v1_32));
let windowsState = restoreRecentlyOpened(JSON.parse(v1_32), new NullLogService());
let expected: IRecentlyOpened = {
files: [{ fileUri: URI.parse('file:///home/user/.config/code-oss-dev/storage.json') }],
workspaces: [
Expand Down Expand Up @@ -206,7 +207,7 @@ suite('History Storage', () => {
]
}`;

let windowsState = restoreRecentlyOpened(JSON.parse(v1_33));
let windowsState = restoreRecentlyOpened(JSON.parse(v1_33), new NullLogService());
let expected: IRecentlyOpened = {
files: [{ label: 'def', fileUri: URI.parse('file:///home/user/.config/code-oss-dev/storage.json') }],
workspaces: [
Expand Down
7 changes: 4 additions & 3 deletions src/vs/workbench/browser/web.simpleservices.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { IPager } from 'vs/base/common/paging';
import { IExtensionManifest, ExtensionType, ExtensionIdentifier, IExtension } from 'vs/platform/extensions/common/extensions';
import { IURLHandler, IURLService } from 'vs/platform/url/common/url';
import { ITelemetryService, ITelemetryData, ITelemetryInfo } from 'vs/platform/telemetry/common/telemetry';
import { ConsoleLogService } from 'vs/platform/log/common/log';
import { ConsoleLogService, ILogService } from 'vs/platform/log/common/log';
import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { IUpdateService, State } from 'vs/platform/update/common/update';
Expand Down Expand Up @@ -489,7 +489,8 @@ export class SimpleWindowService extends Disposable implements IWindowService {
@IFileService private readonly fileService: IFileService,
@IConfigurationService private readonly configurationService: IConfigurationService,
@IStorageService private readonly storageService: IStorageService,
@IWorkspaceContextService private readonly workspaceService: IWorkspaceContextService
@IWorkspaceContextService private readonly workspaceService: IWorkspaceContextService,
@ILogService private readonly logService: ILogService
) {
super();

Expand Down Expand Up @@ -617,7 +618,7 @@ export class SimpleWindowService extends Disposable implements IWindowService {
async getRecentlyOpened(): Promise<IRecentlyOpened> {
const recentlyOpenedRaw = this.storageService.get(SimpleWindowService.RECENTLY_OPENED_KEY, StorageScope.GLOBAL);
if (recentlyOpenedRaw) {
return restoreRecentlyOpened(JSON.parse(recentlyOpenedRaw));
return restoreRecentlyOpened(JSON.parse(recentlyOpenedRaw), this.logService);
}

return { workspaces: [], files: [] };
Expand Down

0 comments on commit b1621c1

Please sign in to comment.