export function parseStorage(storage: IStorage): IParsedStorage {
const globalStorage = new Map<string, string>();
const folderWorkspacesStorage = new Map<string /* workspace file resource */, StorageObject>();
const emptyWorkspacesStorage = new Map<string /* empty workspace id */, StorageObject>();
const multiRootWorkspacesStorage = new Map<string /* multi root workspace id */, StorageObject>();
const workspaces: { prefix: string; resource: string; }[] = [];
for (let i = 0; i < storage.length; i++) {
const key = storage.key(i);
// Workspace Storage (storage://workspace/)
if (startsWith(key, StorageService.WORKSPACE_PREFIX)) {
// We are looking for key: storage://workspace/<folder>/workspaceIdentifier to be able to find all folder
// paths that are known to the storage. is the only way how to parse all folder paths known in storage.
if (endsWith(key, StorageService.WORKSPACE_IDENTIFIER)) {
// storage://workspace/<folder>/workspaceIdentifier => <folder>/
let workspace = key.substring(StorageService.WORKSPACE_PREFIX.length, key.length - StorageService.WORKSPACE_IDENTIFIER.length);
//Â macOS/Unix: Users/name/folder/
// Windows: c%3A/Users/name/folder/
if (!startsWith(workspace, 'file:')) {
workspace = `file:///${rtrim(workspace, '/')}`;
}
// Windows UNC path: file://localhost/c%3A/Users/name/folder/
else {
workspace = rtrim(workspace, '/');
}
// storage://workspace/<folder>/workspaceIdentifier => storage://workspace/<folder>/
const prefix = key.substr(0, key.length - StorageService.WORKSPACE_IDENTIFIER.length);
workspaces.push({ prefix, resource: workspace });
}
// Empty workspace key: storage://workspace/empty:<id>/<key>
else if (startsWith(key, EMPTY_WORKSPACE_PREFIX)) {
// storage://workspace/empty:<id>/<key> => <id>
const emptyWorkspaceId = key.substring(EMPTY_WORKSPACE_PREFIX.length, key.indexOf('/', EMPTY_WORKSPACE_PREFIX.length));
const emptyWorkspaceResource = URI.from({ path: emptyWorkspaceId, scheme: 'empty' }).toString();
let emptyWorkspaceStorage = emptyWorkspacesStorage.get(emptyWorkspaceResource);
if (!emptyWorkspaceStorage) {
emptyWorkspaceStorage = Object.create(null);
emptyWorkspacesStorage.set(emptyWorkspaceResource, emptyWorkspaceStorage);
}
// storage://workspace/empty:<id>/someKey => someKey
const storageKey = key.substr(EMPTY_WORKSPACE_PREFIX.length + emptyWorkspaceId.length + 1 /* trailing / */);
emptyWorkspaceStorage[storageKey] = storage.getItem(key);
}
// Multi root workspace key: storage://workspace/root:<id>/<key>
else if (startsWith(key, MULTI_ROOT_WORKSPACE_PREFIX)) {
// storage://workspace/root:<id>/<key> => <id>
const multiRootWorkspaceId = key.substring(MULTI_ROOT_WORKSPACE_PREFIX.length, key.indexOf('/', MULTI_ROOT_WORKSPACE_PREFIX.length));
const multiRootWorkspaceResource = URI.from({ path: multiRootWorkspaceId, scheme: 'root' }).toString();
let multiRootWorkspaceStorage = multiRootWorkspacesStorage.get(multiRootWorkspaceResource);
if (!multiRootWorkspaceStorage) {
multiRootWorkspaceStorage = Object.create(null);
multiRootWorkspacesStorage.set(multiRootWorkspaceResource, multiRootWorkspaceStorage);
}
// storage://workspace/root:<id>/someKey => someKey
const storageKey = key.substr(MULTI_ROOT_WORKSPACE_PREFIX.length + multiRootWorkspaceId.length + 1 /* trailing / */);
multiRootWorkspaceStorage[storageKey] = storage.getItem(key);
}
}
// Global Storage (storage://global)
else if (startsWith(key, StorageService.GLOBAL_PREFIX)) {
// storage://global/someKey => someKey
const globalStorageKey = key.substr(StorageService.GLOBAL_PREFIX.length);
if (startsWith(globalStorageKey, StorageService.COMMON_PREFIX)) {
continue; // filter out faulty keys that have the form storage://something/storage://
}
globalStorage.set(globalStorageKey, storage.getItem(key));
}
}
// With all the folder paths known we can now extract storage for each path. We have to go through all workspaces
// from the longest path first to reliably extract the storage. The reason is that one folder path can be a parent
// of another folder path and as such a simple indexOf check is not enough.
const workspacesByLength = workspaces.sort((w1, w2) => w1.prefix.length >= w2.prefix.length ? -1 : 1);
const handledKeys = new Map<string, boolean>();
workspacesByLength.forEach(workspace => {
for (let i = 0; i < storage.length; i++) {
const key = storage.key(i);
if (handledKeys.has(key) || !startsWith(key, workspace.prefix)) {
continue; // not part of workspace prefix or already handled
}
//.........这里部分代码省略.........
请发表评论