globalStateSync.ts ×15

Frontier kind: Code frontier

unlabeled · c_66581065d4f0

133 tests · 25651 LOC · 133 files · introduces 0 tests · 103 LOC · 4 files

Introduces — evidence that enters the hierarchy at this concept

Code
19 ranges103 lines · 4 files
Tests
0 tests

Contains — complete concept membership

All code (extent)
4096 ranges25651 lines · 133 files · Browse complete extent
All tests (intent)
133 testsBrowse complete intent

Neighbourhood graph

The orange circle is the focus. Violet and green circles are every ancestor and descendant, broader and narrower, at any distance; blue squares and pink diamonds are the introduced files and exact introduced tests of every visible concept, not only the focus's. Arrows point from broader to narrower concepts and bridge only concepts omitted from this view. Undirected links show source or test introduction. Concept and file size follows LOC; exact test nodes use test-count units.

Introduced files, introduced tests, and structurally relevant concept specialization

In the embedded map, ordinary wheel input scrolls the page; use the visible controls to zoom and drag to pan. Open the full-screen map for canvas navigation: wheel pans, Ctrl/Command plus wheel zooms, and arrow keys pan when this region is focused. On touch screens, open the full-screen map to pan or pinch. If JavaScript or WebGL is unavailable, use the native relationship evidence on this page.

Graph controls are ready.

Interactive rendering requires JavaScript and WebGL. Use the native relationship evidence on this page while the interactive map is unavailable.

Native relationship evidence

Every exact file and test below is linked only from the concept that introduces it.

Introduced tests

Every collected test enters the hierarchy at exactly one concept.

No tests are introduced at this concept. Its intent tests are introduced by other concepts.

Introduced code

Every collected source range enters the hierarchy at exactly one concept.

4 files ranked by introduced lines: 103 introduced LOC across 19 ranges. Expand a file to inspect source; the > gutter marks introduced lines.

src/vs/platform/userDataSync/common/globalStateSync.ts 94 introduced LOC · 15 ranges

Open complete file

49
50 export function stringify(globalState: IGlobalState, format: boolean): string {
51 > const storageKeys = globalState.storage ? Object.keys(globalState.storage).sort() : []; globalStateSync.ts
52 > const storage: IStringDictionary<IStorageValue> = {};
53 > storageKeys.forEach(key => storage[key] = globalState.storage[key]);
54 > globalState.storage = storage;
55 > return format ? toFormattedString(globalState, {}) : JSON.stringify(globalState);
56 > }
57
58 const GLOBAL_STATE_DATA_VERSION = 1;
117
118 protected async generateSyncPreview(remoteUserData: IRemoteUserData, lastSyncUserData: IRemoteUserData | null, isRemoteDataFromCurrentMachine: boolean): Promise<IGlobalStateResourcePreview[]> {
119 > const remoteGlobalState: IGlobalState = remoteUserData.syncData ? JSON.parse(remoteUserData.syncData.content) : null; globalStateSync.ts
120 >
121 > // Use remote data as last sync data if last sync data does not exist and remote data is from same machine
122 > lastSyncUserData = lastSyncUserData === null && isRemoteDataFromCurrentMachine ? remoteUserData : lastSyncUserData;
123 > const lastSyncGlobalState: IGlobalState | null = lastSyncUserData && lastSyncUserData.syncData ? JSON.parse(lastSyncUserData.syncData.content) : null;
124 >
125 > const localGlobalState = await this.localGlobalStateProvider.getLocalGlobalState(this.syncResource.profile);
126 >
127 > if (remoteGlobalState) {
128 this.logService.trace(`${this.syncResourceLogLabel}: Merging remote ui state with local ui state...`);
129 > } else { globalStateSync.ts
130 > this.logService.trace(`${this.syncResourceLogLabel}: Remote ui state does not exist. Synchronizing ui state for the first time.`);
131 > }
132 >
133 > const storageKeys = await this.getStorageKeys(lastSyncGlobalState);
134 > const { local, remote } = merge(localGlobalState.storage, remoteGlobalState ? remoteGlobalState.storage : null, lastSyncGlobalState ? lastSyncGlobalState.storage : null, storageKeys, this.logService);
135 > const previewResult: IGlobalStateResourceMergeResult = {
136 > content: null,
137 > local,
138 > remote,
139 > localChange: Object.keys(local.added).length > 0 || Object.keys(local.updated).length > 0 || local.removed.length > 0 ? Change.Modified : Change.None,
140 > remoteChange: remote.all !== null ? Change.Modified : Change.None,
141 > };
142 >
143 > const localContent = stringify(localGlobalState, false);
144 > return [{
145 > baseResource: this.baseResource,
146 > baseContent: lastSyncGlobalState ? stringify(lastSyncGlobalState, false) : localContent,
147 > localResource: this.localResource,
148 > localContent,
149 > localUserData: localGlobalState,
150 > remoteResource: this.remoteResource,
151 > remoteContent: remoteGlobalState ? stringify(remoteGlobalState, false) : null,
152 > previewResource: this.previewResource,
153 > previewResult,
154 > localChange: previewResult.localChange,
155 > remoteChange: previewResult.remoteChange,
156 > acceptedResource: this.acceptedResource,
157 > storageKeys
158 > }];
159 > }
160
161 protected async hasRemoteChanged(lastSyncUserData: IRemoteUserData): Promise<boolean> {
239
240 protected async applyResult(remoteUserData: IRemoteUserData, lastSyncUserData: IRemoteUserData | null, resourcePreviews: [IGlobalStateResourcePreview, IGlobalStateResourceMergeResult][], force: boolean): Promise<void> {
241 > const { localUserData } = resourcePreviews[0][0]; globalStateSync.ts
242 > const { local, remote, localChange, remoteChange } = resourcePreviews[0][1];
243 >
244 > if (localChange === Change.None && remoteChange === Change.None) {
245 this.logService.info(`${this.syncResourceLogLabel}: No changes found during synchronizing ui state.`);
246 }
248 > if (localChange !== Change.None) {
249 // update local
250 this.logService.trace(`${this.syncResourceLogLabel}: Updating local ui state...`);
253 this.logService.info(`${this.syncResourceLogLabel}: Updated local ui state`);
254 }
256 > if (remoteChange !== Change.None) {
257 // update remote
258 this.logService.trace(`${this.syncResourceLogLabel}: Updating remote ui state...`);
261 this.logService.info(`${this.syncResourceLogLabel}: Updated remote ui state.${remote.added.length ? ` Added: ${remote.added}.` : ''}${remote.updated.length ? ` Updated: ${remote.updated}.` : ''}${remote.removed.length ? ` Removed: ${remote.removed}.` : ''}`);
262 }
264 > if (lastSyncUserData?.ref !== remoteUserData.ref) {
265 > // update last sync
266 > this.logService.trace(`${this.syncResourceLogLabel}: Updating last synchronized ui state...`);
267 > await this.updateLastSyncUserData(remoteUserData);
268 > this.logService.info(`${this.syncResourceLogLabel}: Updated last synchronized ui state`);
269 > }
270 > }
271
272 async resolveContent(uri: URI): Promise<string | null> {
295
296 private async getStorageKeys(lastSyncGlobalState: IGlobalState | null): Promise<StorageKeys> {
297 > const storageData = await this.userDataProfileStorageService.readStorageData(this.syncResource.profile); globalStateSync.ts
298 > const user: string[] = [], machine: string[] = [];
299 > for (const [key, value] of storageData) {
300 if (value.target === StorageTarget.USER) {
301 user.push(key);
304 }
305 }
306 > const registered = [...user, ...machine]; globalStateSync.ts
307 > const unregistered = lastSyncGlobalState?.storage ? Object.keys(lastSyncGlobalState.storage).filter(key => !key.startsWith(argvStoragePrefx) && !registered.includes(key) && storageData.get(key) !== undefined) : [];
308 >
309 > if (!isWeb) {
310 > // Following keys are synced only in web. Do not sync these keys in other platforms
311 > const keysSyncedOnlyInWeb = [...ALL_SYNC_RESOURCES.map(resource => getEnablementKey(resource)), SYNC_SERVICE_URL_TYPE];
312 > unregistered.push(...keysSyncedOnlyInWeb);
313 > machine.push(...keysSyncedOnlyInWeb);
314 > }
315 >
316 > return { user, machine, unregistered };
317 > }
318 }
319
327
328 async getLocalGlobalState(profile: IUserDataProfile): Promise<IGlobalState> {
329 > const storage: IStringDictionary<IStorageValue> = {}; globalStateSync.ts
330 > if (profile.isDefault) {
331 > const argvContent: string = await this.getLocalArgvContent();
332 > const argvValue: IStringDictionary<any> = parse(argvContent);
333 > for (const argvProperty of argvProperties) {
334 > if (argvValue[argvProperty] !== undefined) {
335 storage[`${argvStoragePrefx}${argvProperty}`] = { version: 1, value: argvValue[argvProperty] };
336 }
338 > }
339 > const storageData = await this.userDataProfileStorageService.readStorageData(profile);
340 > for (const [key, value] of storageData) {
341 if (value.value && value.target === StorageTarget.USER) {
342 storage[key] = { version: 1, value: value.value, scope: value.scope };
343 }
344 }
345 > return { storage }; globalStateSync.ts
346 > }
347
348 private async getLocalArgvContent(): Promise<string> {
349 > try { globalStateSync.ts
350 > this.logService.debug('GlobalStateSync#getLocalArgvContent', this.environmentService.argvResource);
351 > const content = await this.fileService.readFile(this.environmentService.argvResource);
352 this.logService.debug('GlobalStateSync#getLocalArgvContent - Resolved', this.environmentService.argvResource);
353 return content.value.toString();
354 > } catch (error) { globalStateSync.ts
355 this.logService.debug(getErrorMessage(error));
356 }
357 return '{}';
359
360 async writeLocalGlobalState({ added, removed, updated }: { added: IStringDictionary<IStorageValue>; updated: IStringDictionary<IStorageValue>; removed: string[] }, profile: IUserDataProfile): Promise<void> {
src/vs/platform/userDataProfile/common/userDataProfileStorageService.ts 5 introduced LOC · 2 ranges

Open complete file

88 async withProfileScopedStorageService<T>(profile: IUserDataProfile, fn: (storageService: IStorageService) => Promise<T>): Promise<T> {
89 if (this.storageService.hasScope(profile)) {
90 > return fn(this.storageService); userDataProfileStorageService.ts
91 > }
92
93 let storageService = this.storageServicesMap?.get(profile.id);
128 populate(StorageScope.PROFILE, StorageTarget.MACHINE);
129 if (profile.isDefault) {
130 > populate(StorageScope.APPLICATION_SHARED, StorageTarget.USER); userDataProfileStorageService.ts
131 > populate(StorageScope.APPLICATION_SHARED, StorageTarget.MACHINE);
132 > }
133 return result;
134 }
src/vs/platform/userDataSync/common/globalStateMerge.ts 2 introduced LOC · 1 range

Open complete file

16 export function merge(localStorage: IStringDictionary<IStorageValue>, remoteStorage: IStringDictionary<IStorageValue> | null, baseStorage: IStringDictionary<IStorageValue> | null, storageKeys: { machine: ReadonlyArray<string>; unregistered: ReadonlyArray<string> }, logService: ILogService): IMergeResult {
17 if (!remoteStorage) {
18 > return { remote: { added: Object.keys(localStorage), removed: [], updated: [], all: Object.keys(localStorage).length > 0 ? localStorage : null }, local: { added: {}, removed: [], updated: {} } }; globalStateMerge.ts
19 > }
20
21 const localToRemote = compare(localStorage, remoteStorage);
src/vs/platform/userDataSync/test/common/userDataSyncClient.ts 2 introduced LOC · 1 range

Open complete file

397 }
398 override hasScope(profile: IUserDataProfile): boolean {
399 > return this.profileStorageProfile.id === profile.id; userDataSyncClient.ts
400 > }
401 }