55
66import { StorageLegacyService , IStorageLegacy } from 'vs/platform/storage/common/storageLegacyService' ;
77import { endsWith , startsWith , rtrim } from 'vs/base/common/strings' ;
8- import { URI } from 'vs/base/common/uri' ;
98
109/**
1110 * We currently store local storage with the following format:
@@ -28,154 +27,130 @@ import { URI } from 'vs/base/common/uri';
2827 * => no longer being used (used for empty workspaces previously)
2928 */
3029
31- const EMPTY_WORKSPACE_PREFIX = `${ StorageLegacyService . COMMON_PREFIX } workspace/empty:` ;
32- const MULTI_ROOT_WORKSPACE_PREFIX = `${ StorageLegacyService . COMMON_PREFIX } workspace/root:` ;
30+ const COMMON_WORKSPACE_PREFIX = `${ StorageLegacyService . COMMON_PREFIX } workspace/` ;
3331const NO_WORKSPACE_PREFIX = 'storage://workspace/__$noWorkspace__' ;
3432
3533export type StorageObject = { [ key : string ] : string } ;
3634
3735export interface IParsedStorage {
38- global : Map < string , string > ;
3936 multiRoot : Map < string , StorageObject > ;
4037 folder : Map < string , StorageObject > ;
4138 empty : Map < string , StorageObject > ;
4239 noWorkspace : StorageObject ;
4340}
4441
45- /**
46- * Parses the local storage implementation into global, multi root, folder and empty storage.
47- */
48- export function parseStorage ( storage : IStorageLegacy ) : IParsedStorage {
49- const globalStorage = new Map < string , string > ( ) ;
50- const noWorkspaceStorage : StorageObject = Object . create ( null ) ;
51- const folderWorkspacesStorage = new Map < string /* workspace file resource */ , StorageObject > ( ) ;
52- const emptyWorkspacesStorage = new Map < string /* empty workspace id */ , StorageObject > ( ) ;
53- const multiRootWorkspacesStorage = new Map < string /* multi root workspace id */ , StorageObject > ( ) ;
42+ export function parseFolderStorage ( storage : IStorageLegacy , folderId : string ) : StorageObject {
5443
5544 const workspaces : { prefix : string ; resource : string ; } [ ] = [ ] ;
45+ const activeKeys = new Set < string > ( ) ;
46+
5647 for ( let i = 0 ; i < storage . length ; i ++ ) {
5748 const key = storage . key ( i ) ;
5849
5950 // Workspace Storage (storage://workspace/)
60- if ( startsWith ( key , StorageLegacyService . WORKSPACE_PREFIX ) ) {
61-
62- // No Workspace key is for extension development windows
63- if ( key . indexOf ( '__$noWorkspace__' ) > 0 ) {
64-
65- // storage://workspace/__$noWorkspace__someKey => someKey
66- const noWorkspaceStorageKey = key . substr ( NO_WORKSPACE_PREFIX . length ) ;
51+ if ( ! startsWith ( key , StorageLegacyService . WORKSPACE_PREFIX ) ) {
52+ continue ;
53+ }
6754
68- noWorkspaceStorage [ noWorkspaceStorageKey ] = storage . getItem ( key ) ;
69- }
55+ activeKeys . add ( key ) ;
7056
71- // We are looking for key: storage://workspace/<folder>/workspaceIdentifier to be able to find all folder
72- // paths that are known to the storage. is the only way how to parse all folder paths known in storage.
73- else if ( endsWith ( key , StorageLegacyService . WORKSPACE_IDENTIFIER ) ) {
57+ // We are looking for key: storage://workspace/<folder>/workspaceIdentifier to be able to find all folder
58+ // paths that are known to the storage. is the only way how to parse all folder paths known in storage.
59+ if ( endsWith ( key , StorageLegacyService . WORKSPACE_IDENTIFIER ) ) {
7460
75- // storage://workspace/<folder>/workspaceIdentifier => <folder>/
76- let workspace = key . substring ( StorageLegacyService . WORKSPACE_PREFIX . length , key . length - StorageLegacyService . WORKSPACE_IDENTIFIER . length ) ;
61+ // storage://workspace/<folder>/workspaceIdentifier => <folder>/
62+ let workspace = key . substring ( StorageLegacyService . WORKSPACE_PREFIX . length , key . length - StorageLegacyService . WORKSPACE_IDENTIFIER . length ) ;
7763
78- // macOS/Unix: Users/name/folder/
79- // Windows: c%3A/Users/name/folder/
80- if ( ! startsWith ( workspace , 'file:' ) ) {
81- workspace = `file:///${ rtrim ( workspace , '/' ) } ` ;
82- }
64+ // macOS/Unix: Users/name/folder/
65+ // Windows: c%3A/Users/name/folder/
66+ if ( ! startsWith ( workspace , 'file:' ) ) {
67+ workspace = `file:///${ rtrim ( workspace , '/' ) } ` ;
68+ }
8369
84- // Windows UNC path: file://localhost/c%3A/Users/name/folder/
85- else {
86- workspace = rtrim ( workspace , '/' ) ;
87- }
70+ // Windows UNC path: file://localhost/c%3A/Users/name/folder/
71+ else {
72+ workspace = rtrim ( workspace , '/' ) ;
73+ }
8874
89- // storage://workspace/<folder>/workspaceIdentifier => storage://workspace/<folder>/
90- const prefix = key . substr ( 0 , key . length - StorageLegacyService . WORKSPACE_IDENTIFIER . length ) ;
75+ // storage://workspace/<folder>/workspaceIdentifier => storage://workspace/<folder>/
76+ const prefix = key . substr ( 0 , key . length - StorageLegacyService . WORKSPACE_IDENTIFIER . length ) ;
77+ if ( startsWith ( workspace , folderId ) ) {
9178 workspaces . push ( { prefix, resource : workspace } ) ;
9279 }
80+ }
81+ }
9382
94- // Empty workspace key: storage://workspace/empty:<id>/<key>
95- else if ( startsWith ( key , EMPTY_WORKSPACE_PREFIX ) ) {
83+ // With all the folder paths known we can now extract storage for each path. We have to go through all workspaces
84+ // from the longest path first to reliably extract the storage. The reason is that one folder path can be a parent
85+ // of another folder path and as such a simple indexOf check is not enough.
86+ const workspacesByLength = workspaces . sort ( ( w1 , w2 ) => w1 . prefix . length >= w2 . prefix . length ? - 1 : 1 ) ;
9687
97- // storage://workspace/empty:<id>/<key> => <id>
98- const emptyWorkspaceId = key . substring ( EMPTY_WORKSPACE_PREFIX . length , key . indexOf ( '/' , EMPTY_WORKSPACE_PREFIX . length ) ) ;
99- const emptyWorkspaceResource = URI . from ( { path : emptyWorkspaceId , scheme : 'empty' } ) . toString ( ) ;
88+ const folderWorkspaceStorage : StorageObject = Object . create ( null ) ;
10089
101- let emptyWorkspaceStorage = emptyWorkspacesStorage . get ( emptyWorkspaceResource ) ;
102- if ( ! emptyWorkspaceStorage ) {
103- emptyWorkspaceStorage = Object . create ( null ) ;
104- emptyWorkspacesStorage . set ( emptyWorkspaceResource , emptyWorkspaceStorage ) ;
105- }
90+ workspacesByLength . forEach ( workspace => {
91+ activeKeys . forEach ( key => {
92+ if ( ! startsWith ( key , workspace . prefix ) ) {
93+ return ; // not part of workspace prefix or already handled
94+ }
10695
107- // storage://workspace/empty:<id>/someKey => someKey
108- const storageKey = key . substr ( EMPTY_WORKSPACE_PREFIX . length + emptyWorkspaceId . length + 1 /* trailing / */ ) ;
96+ activeKeys . delete ( key ) ;
10997
110- emptyWorkspaceStorage [ storageKey ] = storage . getItem ( key ) ;
98+ if ( workspace . resource === folderId ) {
99+ // storage://workspace/<folder>/someKey => someKey
100+ const storageKey = key . substr ( workspace . prefix . length ) ;
101+ folderWorkspaceStorage [ storageKey ] = storage . getItem ( key ) ;
111102 }
103+ } ) ;
104+ } ) ;
112105
113- // Multi root workspace key: storage://workspace/root:<id>/<key>
114- else if ( startsWith ( key , MULTI_ROOT_WORKSPACE_PREFIX ) ) {
115-
116- // storage://workspace/root:<id>/<key> => <id>
117- const multiRootWorkspaceId = key . substring ( MULTI_ROOT_WORKSPACE_PREFIX . length , key . indexOf ( '/' , MULTI_ROOT_WORKSPACE_PREFIX . length ) ) ;
118- const multiRootWorkspaceResource = URI . from ( { path : multiRootWorkspaceId , scheme : 'root' } ) . toString ( ) ;
106+ return folderWorkspaceStorage ;
107+ }
119108
120- let multiRootWorkspaceStorage = multiRootWorkspacesStorage . get ( multiRootWorkspaceResource ) ;
121- if ( ! multiRootWorkspaceStorage ) {
122- multiRootWorkspaceStorage = Object . create ( null ) ;
123- multiRootWorkspacesStorage . set ( multiRootWorkspaceResource , multiRootWorkspaceStorage ) ;
124- }
109+ export function parseNoWorkspaceStorage ( storage : IStorageLegacy ) {
110+ const noWorkspacePrefix = `${ StorageLegacyService . WORKSPACE_PREFIX } __$noWorkspace__` ;
125111
126- // storage://workspace/root:<id>/someKey => someKey
127- const storageKey = key . substr ( MULTI_ROOT_WORKSPACE_PREFIX . length + multiRootWorkspaceId . length + 1 /* trailing / */ ) ;
112+ const noWorkspaceStorage : StorageObject = Object . create ( null ) ;
113+ for ( let i = 0 ; i < storage . length ; i ++ ) {
114+ const key = storage . key ( i ) ;
128115
129- multiRootWorkspaceStorage [ storageKey ] = storage . getItem ( key ) ;
130- }
116+ // No Workspace key is for extension development windows
117+ if ( startsWith ( key , noWorkspacePrefix ) && ! endsWith ( key , StorageLegacyService . WORKSPACE_IDENTIFIER ) ) {
118+ // storage://workspace/__$noWorkspace__someKey => someKey
119+ noWorkspaceStorage [ key . substr ( NO_WORKSPACE_PREFIX . length ) ] = storage . getItem ( key ) ;
131120 }
121+ }
132122
133- // Global Storage (storage://global)
134- else if ( startsWith ( key , StorageLegacyService . GLOBAL_PREFIX ) ) {
123+ return noWorkspaceStorage ;
124+ }
135125
136- // storage://global/someKey => someKey
137- const globalStorageKey = key . substr ( StorageLegacyService . GLOBAL_PREFIX . length ) ;
138- if ( startsWith ( globalStorageKey , StorageLegacyService . COMMON_PREFIX ) ) {
139- continue ; // filter out faulty keys that have the form storage://something/storage://
140- }
126+ export function parseEmptyStorage ( storage : IStorageLegacy , targetWorkspaceId : string ) : StorageObject {
127+ const emptyStoragePrefix = `${ COMMON_WORKSPACE_PREFIX } ${ targetWorkspaceId } /` ;
128+
129+ const emptyWorkspaceStorage : StorageObject = Object . create ( null ) ;
130+ for ( let i = 0 ; i < storage . length ; i ++ ) {
131+ const key = storage . key ( i ) ;
141132
142- globalStorage . set ( globalStorageKey , storage . getItem ( key ) ) ;
133+ if ( startsWith ( key , emptyStoragePrefix ) && ! endsWith ( key , StorageLegacyService . WORKSPACE_IDENTIFIER ) ) {
134+ // storage://workspace/empty:<id>/someKey => someKey
135+ emptyWorkspaceStorage [ key . substr ( emptyStoragePrefix . length ) ] = storage . getItem ( key ) ;
143136 }
144137 }
145138
146- // With all the folder paths known we can now extract storage for each path. We have to go through all workspaces
147- // from the longest path first to reliably extract the storage. The reason is that one folder path can be a parent
148- // of another folder path and as such a simple indexOf check is not enough.
149- const workspacesByLength = workspaces . sort ( ( w1 , w2 ) => w1 . prefix . length >= w2 . prefix . length ? - 1 : 1 ) ;
150- const handledKeys = new Map < string , boolean > ( ) ;
151- workspacesByLength . forEach ( workspace => {
152- for ( let i = 0 ; i < storage . length ; i ++ ) {
153- const key = storage . key ( i ) ;
154-
155- if ( handledKeys . has ( key ) || ! startsWith ( key , workspace . prefix ) ) {
156- continue ; // not part of workspace prefix or already handled
157- }
158-
159- handledKeys . set ( key , true ) ;
139+ return emptyWorkspaceStorage ;
140+ }
160141
161- let folderWorkspaceStorage = folderWorkspacesStorage . get ( workspace . resource ) ;
162- if ( ! folderWorkspaceStorage ) {
163- folderWorkspaceStorage = Object . create ( null ) ;
164- folderWorkspacesStorage . set ( workspace . resource , folderWorkspaceStorage ) ;
165- }
142+ export function parseMultiRootStorage ( storage : IStorageLegacy , targetWorkspaceId : string ) : StorageObject {
143+ const multiRootStoragePrefix = `${ COMMON_WORKSPACE_PREFIX } ${ targetWorkspaceId } /` ;
166144
167- // storage://workspace/<folder>/someKey => someKey
168- const storageKey = key . substr ( workspace . prefix . length ) ;
145+ const multiRootWorkspaceStorage : StorageObject = Object . create ( null ) ;
146+ for ( let i = 0 ; i < storage . length ; i ++ ) {
147+ const key = storage . key ( i ) ;
169148
170- folderWorkspaceStorage [ storageKey ] = storage . getItem ( key ) ;
149+ if ( startsWith ( key , multiRootStoragePrefix ) && ! endsWith ( key , StorageLegacyService . WORKSPACE_IDENTIFIER ) ) {
150+ // storage://workspace/root:<id>/someKey => someKey
151+ multiRootWorkspaceStorage [ key . substr ( multiRootStoragePrefix . length ) ] = storage . getItem ( key ) ;
171152 }
172- } ) ;
153+ }
173154
174- return {
175- global : globalStorage ,
176- multiRoot : multiRootWorkspacesStorage ,
177- folder : folderWorkspacesStorage ,
178- empty : emptyWorkspacesStorage ,
179- noWorkspace : noWorkspaceStorage
180- } ;
181- }
155+ return multiRootWorkspaceStorage ;
156+ }
0 commit comments