@codingame/monaco-vscode-user-data-sync-service-override 1.85.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/external/rollup-plugin-styles/dist/runtime/inject-css.js +3 -0
  2. package/external/tslib/tslib.es6.js +11 -0
  3. package/index.d.ts +1 -0
  4. package/index.js +1 -0
  5. package/override/vs/platform/dialogs/common/dialogs.js +8 -0
  6. package/override/vs/platform/userDataSync/common/extensionsSync.js +4 -0
  7. package/override/vs/platform/userDataSync/common/globalStateSync.js +5 -0
  8. package/package.json +24 -0
  9. package/userDataSync.d.ts +5 -0
  10. package/userDataSync.js +106 -0
  11. package/vscode/src/vs/base/browser/ui/icons/iconSelectBox.css.js +6 -0
  12. package/vscode/src/vs/base/browser/ui/icons/iconSelectBox.js +248 -0
  13. package/vscode/src/vs/platform/userDataProfile/browser/userDataProfile.js +95 -0
  14. package/vscode/src/vs/platform/userDataProfile/common/userDataProfileStorageService.js +5 -0
  15. package/vscode/src/vs/platform/userDataSync/common/abstractSynchronizer.js +774 -0
  16. package/vscode/src/vs/platform/userDataSync/common/extensionsSync.js +251 -0
  17. package/vscode/src/vs/platform/userDataSync/common/globalStateSync.js +115 -0
  18. package/vscode/src/vs/platform/userDataSync/common/keybindingsMerge.js +277 -0
  19. package/vscode/src/vs/platform/userDataSync/common/keybindingsSync.js +318 -0
  20. package/vscode/src/vs/platform/userDataSync/common/settingsSync.js +316 -0
  21. package/vscode/src/vs/platform/userDataSync/common/snippetsMerge.js +126 -0
  22. package/vscode/src/vs/platform/userDataSync/common/snippetsSync.js +476 -0
  23. package/vscode/src/vs/platform/userDataSync/common/tasksSync.js +244 -0
  24. package/vscode/src/vs/platform/userDataSync/common/userDataAutoSyncService.js +466 -0
  25. package/vscode/src/vs/platform/userDataSync/common/userDataProfilesManifestMerge.js +92 -0
  26. package/vscode/src/vs/platform/userDataSync/common/userDataProfilesManifestSync.js +261 -0
  27. package/vscode/src/vs/platform/userDataSync/common/userDataSyncEnablementService.js +77 -0
  28. package/vscode/src/vs/platform/userDataSync/common/userDataSyncLocalStoreService.js +150 -0
  29. package/vscode/src/vs/platform/userDataSync/common/userDataSyncLog.js +41 -0
  30. package/vscode/src/vs/platform/userDataSync/common/userDataSyncResourceProvider.js +449 -0
  31. package/vscode/src/vs/platform/userDataSync/common/userDataSyncService.js +783 -0
  32. package/vscode/src/vs/platform/userDataSync/common/userDataSyncStoreService.js +553 -0
  33. package/vscode/src/vs/workbench/browser/iconSelectBox.js +98 -0
  34. package/vscode/src/vs/workbench/contrib/userDataSync/browser/userDataSync.contribution.js +111 -0
  35. package/vscode/src/vs/workbench/contrib/userDataSync/browser/userDataSync.js +1467 -0
  36. package/vscode/src/vs/workbench/contrib/userDataSync/browser/userDataSyncConflictsView.js +225 -0
  37. package/vscode/src/vs/workbench/contrib/userDataSync/browser/userDataSyncTrigger.js +61 -0
  38. package/vscode/src/vs/workbench/contrib/userDataSync/browser/userDataSyncViews.js +860 -0
  39. package/vscode/src/vs/workbench/services/userDataProfile/browser/extensionsResource.js +342 -0
  40. package/vscode/src/vs/workbench/services/userDataProfile/browser/globalStateResource.js +147 -0
  41. package/vscode/src/vs/workbench/services/userDataProfile/browser/keybindingsResource.js +119 -0
  42. package/vscode/src/vs/workbench/services/userDataProfile/browser/media/userDataProfileView.css.js +6 -0
  43. package/vscode/src/vs/workbench/services/userDataProfile/browser/settingsResource.js +140 -0
  44. package/vscode/src/vs/workbench/services/userDataProfile/browser/snippetsResource.js +155 -0
  45. package/vscode/src/vs/workbench/services/userDataProfile/browser/tasksResource.js +118 -0
  46. package/vscode/src/vs/workbench/services/userDataProfile/browser/userDataProfileImportExportService.js +1753 -0
  47. package/vscode/src/vs/workbench/services/userDataProfile/browser/userDataProfileInit.js +150 -0
  48. package/vscode/src/vs/workbench/services/userDataProfile/browser/userDataProfileManagement.js +190 -0
  49. package/vscode/src/vs/workbench/services/userDataSync/browser/userDataSyncEnablementService.js +10 -0
  50. package/vscode/src/vs/workbench/services/userDataSync/browser/userDataSyncInit.js +447 -0
  51. package/vscode/src/vs/workbench/services/userDataSync/browser/userDataSyncWorkbenchService.js +786 -0
  52. package/vscode/src/vs/workbench/services/userDataSync/browser/webUserDataSyncEnablementService.js +40 -0
  53. package/vscode/src/vs/workbench/services/userDataSync/common/userDataSyncUtil.js +48 -0
@@ -0,0 +1,774 @@
1
+ import { __decorate, __param } from '../../../../../../external/tslib/tslib.es6.js';
2
+ import { equals } from 'monaco-editor/esm/vs/base/common/arrays.js';
3
+ import { ThrottledDelayer, createCancelablePromise } from 'monaco-editor/esm/vs/base/common/async.js';
4
+ import { VSBuffer } from 'monaco-editor/esm/vs/base/common/buffer.js';
5
+ import { CancellationToken } from 'monaco-editor/esm/vs/base/common/cancellation.js';
6
+ import { Emitter } from 'monaco-editor/esm/vs/base/common/event.js';
7
+ import { parse } from 'monaco-editor/esm/vs/base/common/json.js';
8
+ import { Disposable } from 'monaco-editor/esm/vs/base/common/lifecycle.js';
9
+ import { uppercaseFirstLetter } from 'monaco-editor/esm/vs/base/common/strings.js';
10
+ import { isUndefined } from 'monaco-editor/esm/vs/base/common/types.js';
11
+ import { localizeWithPath } from 'monaco-editor/esm/vs/nls.js';
12
+ import { IConfigurationService } from 'monaco-editor/esm/vs/platform/configuration/common/configuration.js';
13
+ import { IEnvironmentService } from 'monaco-editor/esm/vs/platform/environment/common/environment.js';
14
+ import { toFileOperationResult, FileOperationError, IFileService } from 'monaco-editor/esm/vs/platform/files/common/files.js';
15
+ import { ILogService } from 'monaco-editor/esm/vs/platform/log/common/log.js';
16
+ import { getServiceMachineId } from 'vscode/vscode/vs/platform/externalServices/common/serviceMachineId';
17
+ import { IStorageService } from 'monaco-editor/esm/vs/platform/storage/common/storage.js';
18
+ import { ITelemetryService } from 'monaco-editor/esm/vs/platform/telemetry/common/telemetry.js';
19
+ import { IUriIdentityService } from 'monaco-editor/esm/vs/platform/uriIdentity/common/uriIdentity.js';
20
+ import { getPathSegments, PREVIEW_DIR_NAME, getLastSyncResourceUri, UserDataSyncError, USER_DATA_SYNC_SCHEME, USER_DATA_SYNC_CONFIGURATION_SCOPE, IUserDataSyncStoreService, IUserDataSyncLocalStoreService, IUserDataSyncEnablementService, IUserDataSyncLogService, IUserDataSyncUtilService } from 'vscode/vscode/vs/platform/userDataSync/common/userDataSync';
21
+ import { IUserDataProfilesService } from 'monaco-editor/esm/vs/platform/userDataProfile/common/userDataProfile.js';
22
+
23
+ function isRemoteUserData(thing) {
24
+ if (thing
25
+ && (thing.ref !== undefined && typeof thing.ref === 'string' && thing.ref !== '')
26
+ && (thing.syncData !== undefined && (thing.syncData === null || isSyncData(thing.syncData)))) {
27
+ return true;
28
+ }
29
+ return false;
30
+ }
31
+ function isSyncData(thing) {
32
+ if (thing
33
+ && (thing.version !== undefined && typeof thing.version === 'number')
34
+ && (thing.content !== undefined && typeof thing.content === 'string')) {
35
+ if (( Object.keys(thing)).length === 2) {
36
+ return true;
37
+ }
38
+ if (( Object.keys(thing)).length === 3
39
+ && (thing.machineId !== undefined && typeof thing.machineId === 'string')) {
40
+ return true;
41
+ }
42
+ }
43
+ return false;
44
+ }
45
+ function getSyncResourceLogLabel(syncResource, profile) {
46
+ return `${uppercaseFirstLetter(syncResource)}${profile.isDefault ? '' : ` (${profile.name})`}`;
47
+ }
48
+ let AbstractSynchroniser = class AbstractSynchroniser extends Disposable {
49
+ get status() { return this._status; }
50
+ get conflicts() { return { ...this.syncResource, conflicts: this._conflicts }; }
51
+ constructor(syncResource, collection, fileService, environmentService, storageService, userDataSyncStoreService, userDataSyncLocalStoreService, userDataSyncEnablementService, telemetryService, logService, configurationService, uriIdentityService) {
52
+ super();
53
+ this.syncResource = syncResource;
54
+ this.collection = collection;
55
+ this.fileService = fileService;
56
+ this.environmentService = environmentService;
57
+ this.storageService = storageService;
58
+ this.userDataSyncStoreService = userDataSyncStoreService;
59
+ this.userDataSyncLocalStoreService = userDataSyncLocalStoreService;
60
+ this.userDataSyncEnablementService = userDataSyncEnablementService;
61
+ this.telemetryService = telemetryService;
62
+ this.logService = logService;
63
+ this.configurationService = configurationService;
64
+ this.syncPreviewPromise = null;
65
+ this._status = "idle" ;
66
+ this._onDidChangStatus = this._register(( new Emitter()));
67
+ this.onDidChangeStatus = this._onDidChangStatus.event;
68
+ this._conflicts = [];
69
+ this._onDidChangeConflicts = this._register(( new Emitter()));
70
+ this.onDidChangeConflicts = this._onDidChangeConflicts.event;
71
+ this.localChangeTriggerThrottler = this._register(( new ThrottledDelayer(50)));
72
+ this._onDidChangeLocal = this._register(( new Emitter()));
73
+ this.onDidChangeLocal = this._onDidChangeLocal.event;
74
+ this.lastSyncUserDataStateKey = `${this.collection ? `${this.collection}.` : ''}${this.syncResource.syncResource}.lastSyncUserData`;
75
+ this.hasSyncResourceStateVersionChanged = false;
76
+ this.syncHeaders = {};
77
+ this.resource = this.syncResource.syncResource;
78
+ this.syncResourceLogLabel = getSyncResourceLogLabel(syncResource.syncResource, syncResource.profile);
79
+ this.extUri = uriIdentityService.extUri;
80
+ this.syncFolder = this.extUri.joinPath(environmentService.userDataSyncHome, ...getPathSegments(syncResource.profile.isDefault ? undefined : syncResource.profile.id, syncResource.syncResource));
81
+ this.syncPreviewFolder = this.extUri.joinPath(this.syncFolder, PREVIEW_DIR_NAME);
82
+ this.lastSyncResource = getLastSyncResourceUri(syncResource.profile.isDefault ? undefined : syncResource.profile.id, syncResource.syncResource, environmentService, this.extUri);
83
+ this.currentMachineIdPromise = getServiceMachineId(environmentService, fileService, storageService);
84
+ }
85
+ triggerLocalChange() {
86
+ this.localChangeTriggerThrottler.trigger(() => this.doTriggerLocalChange());
87
+ }
88
+ async doTriggerLocalChange() {
89
+ if (this.status === "hasConflicts" ) {
90
+ this.logService.info(`${this.syncResourceLogLabel}: In conflicts state and local change detected. Syncing again...`);
91
+ const preview = await this.syncPreviewPromise;
92
+ this.syncPreviewPromise = null;
93
+ const status = await this.performSync(preview.remoteUserData, preview.lastSyncUserData, true, this.getUserDataSyncConfiguration());
94
+ this.setStatus(status);
95
+ }
96
+ else {
97
+ this.logService.trace(`${this.syncResourceLogLabel}: Checking for local changes...`);
98
+ const lastSyncUserData = await this.getLastSyncUserData();
99
+ const hasRemoteChanged = lastSyncUserData ? await this.hasRemoteChanged(lastSyncUserData) : true;
100
+ if (hasRemoteChanged) {
101
+ this._onDidChangeLocal.fire();
102
+ }
103
+ }
104
+ }
105
+ setStatus(status) {
106
+ if (this._status !== status) {
107
+ this._status = status;
108
+ this._onDidChangStatus.fire(status);
109
+ }
110
+ }
111
+ async sync(manifest, headers = {}) {
112
+ await this._sync(manifest, true, this.getUserDataSyncConfiguration(), headers);
113
+ }
114
+ async preview(manifest, userDataSyncConfiguration, headers = {}) {
115
+ return this._sync(manifest, false, userDataSyncConfiguration, headers);
116
+ }
117
+ async apply(force, headers = {}) {
118
+ try {
119
+ this.syncHeaders = { ...headers };
120
+ const status = await this.doApply(force);
121
+ this.setStatus(status);
122
+ return this.syncPreviewPromise;
123
+ }
124
+ finally {
125
+ this.syncHeaders = {};
126
+ }
127
+ }
128
+ async _sync(manifest, apply, userDataSyncConfiguration, headers) {
129
+ try {
130
+ this.syncHeaders = { ...headers };
131
+ if (this.status === "hasConflicts" ) {
132
+ this.logService.info(`${this.syncResourceLogLabel}: Skipped synchronizing ${this.resource.toLowerCase()} as there are conflicts.`);
133
+ return this.syncPreviewPromise;
134
+ }
135
+ if (this.status === "syncing" ) {
136
+ this.logService.info(`${this.syncResourceLogLabel}: Skipped synchronizing ${this.resource.toLowerCase()} as it is running already.`);
137
+ return this.syncPreviewPromise;
138
+ }
139
+ this.logService.trace(`${this.syncResourceLogLabel}: Started synchronizing ${this.resource.toLowerCase()}...`);
140
+ this.setStatus("syncing" );
141
+ let status = "idle" ;
142
+ try {
143
+ const lastSyncUserData = await this.getLastSyncUserData();
144
+ const remoteUserData = await this.getLatestRemoteUserData(manifest, lastSyncUserData);
145
+ status = await this.performSync(remoteUserData, lastSyncUserData, apply, userDataSyncConfiguration);
146
+ if (status === "hasConflicts" ) {
147
+ this.logService.info(`${this.syncResourceLogLabel}: Detected conflicts while synchronizing ${this.resource.toLowerCase()}.`);
148
+ }
149
+ else if (status === "idle" ) {
150
+ this.logService.trace(`${this.syncResourceLogLabel}: Finished synchronizing ${this.resource.toLowerCase()}.`);
151
+ }
152
+ return this.syncPreviewPromise || null;
153
+ }
154
+ finally {
155
+ this.setStatus(status);
156
+ }
157
+ }
158
+ finally {
159
+ this.syncHeaders = {};
160
+ }
161
+ }
162
+ async replace(content) {
163
+ const syncData = this.parseSyncData(content);
164
+ if (!syncData) {
165
+ return false;
166
+ }
167
+ await this.stop();
168
+ try {
169
+ this.logService.trace(`${this.syncResourceLogLabel}: Started resetting ${this.resource.toLowerCase()}...`);
170
+ this.setStatus("syncing" );
171
+ const lastSyncUserData = await this.getLastSyncUserData();
172
+ const remoteUserData = await this.getLatestRemoteUserData(null, lastSyncUserData);
173
+ const isRemoteDataFromCurrentMachine = await this.isRemoteDataFromCurrentMachine(remoteUserData);
174
+ const resourcePreviewResults = await this.generateSyncPreview({ ref: remoteUserData.ref, syncData }, lastSyncUserData, isRemoteDataFromCurrentMachine, this.getUserDataSyncConfiguration(), CancellationToken.None);
175
+ const resourcePreviews = [];
176
+ for (const resourcePreviewResult of resourcePreviewResults) {
177
+ const acceptResult = await this.getAcceptResult(resourcePreviewResult, resourcePreviewResult.remoteResource, undefined, CancellationToken.None);
178
+ const { remoteChange } = await this.getAcceptResult(resourcePreviewResult, resourcePreviewResult.previewResource, resourcePreviewResult.remoteContent, CancellationToken.None);
179
+ resourcePreviews.push([resourcePreviewResult, { ...acceptResult, remoteChange: remoteChange !== 0 ? remoteChange : 2 }]);
180
+ }
181
+ await this.applyResult(remoteUserData, lastSyncUserData, resourcePreviews, false);
182
+ this.logService.info(`${this.syncResourceLogLabel}: Finished resetting ${this.resource.toLowerCase()}.`);
183
+ }
184
+ finally {
185
+ this.setStatus("idle" );
186
+ }
187
+ return true;
188
+ }
189
+ async isRemoteDataFromCurrentMachine(remoteUserData) {
190
+ const machineId = await this.currentMachineIdPromise;
191
+ return !!remoteUserData.syncData?.machineId && remoteUserData.syncData.machineId === machineId;
192
+ }
193
+ async getLatestRemoteUserData(manifest, lastSyncUserData) {
194
+ if (lastSyncUserData) {
195
+ const latestRef = manifest ? manifest[this.resource] : undefined;
196
+ if (lastSyncUserData.ref === latestRef) {
197
+ return lastSyncUserData;
198
+ }
199
+ if (latestRef === undefined && lastSyncUserData.syncData === null) {
200
+ return lastSyncUserData;
201
+ }
202
+ }
203
+ return this.getRemoteUserData(lastSyncUserData);
204
+ }
205
+ async performSync(remoteUserData, lastSyncUserData, apply, userDataSyncConfiguration) {
206
+ if (remoteUserData.syncData && remoteUserData.syncData.version > this.version) {
207
+ this.telemetryService.publicLog2('sync/incompatible', { source: this.resource });
208
+ throw new UserDataSyncError(localizeWithPath('vs/platform/userDataSync/common/abstractSynchronizer', { key: 'incompatible', comment: ['This is an error while syncing a resource that its local version is not compatible with its remote version.'] }, "Cannot sync {0} as its local version {1} is not compatible with its remote version {2}", this.resource, this.version, remoteUserData.syncData.version), "IncompatibleLocalContent" , this.resource);
209
+ }
210
+ try {
211
+ return await this.doSync(remoteUserData, lastSyncUserData, apply, userDataSyncConfiguration);
212
+ }
213
+ catch (e) {
214
+ if (e instanceof UserDataSyncError) {
215
+ switch (e.code) {
216
+ case "LocalPreconditionFailed" :
217
+ this.logService.info(`${this.syncResourceLogLabel}: Failed to synchronize ${this.syncResourceLogLabel} as there is a new local version available. Synchronizing again...`);
218
+ return this.performSync(remoteUserData, lastSyncUserData, apply, userDataSyncConfiguration);
219
+ case "Conflict" :
220
+ case "PreconditionFailed" :
221
+ this.logService.info(`${this.syncResourceLogLabel}: Failed to synchronize as there is a new remote version available. Synchronizing again...`);
222
+ remoteUserData = await this.getRemoteUserData(null);
223
+ lastSyncUserData = await this.getLastSyncUserData();
224
+ return this.performSync(remoteUserData, lastSyncUserData, apply, userDataSyncConfiguration);
225
+ }
226
+ }
227
+ throw e;
228
+ }
229
+ }
230
+ async doSync(remoteUserData, lastSyncUserData, apply, userDataSyncConfiguration) {
231
+ try {
232
+ const isRemoteDataFromCurrentMachine = await this.isRemoteDataFromCurrentMachine(remoteUserData);
233
+ const acceptRemote = !isRemoteDataFromCurrentMachine && lastSyncUserData === null && this.getStoredLastSyncUserDataStateContent() !== undefined;
234
+ const merge = apply && !acceptRemote;
235
+ if (!this.syncPreviewPromise) {
236
+ this.syncPreviewPromise = createCancelablePromise(token => this.doGenerateSyncResourcePreview(remoteUserData, lastSyncUserData, isRemoteDataFromCurrentMachine, merge, userDataSyncConfiguration, token));
237
+ }
238
+ let preview = await this.syncPreviewPromise;
239
+ if (apply && acceptRemote) {
240
+ this.logService.info(`${this.syncResourceLogLabel}: Accepting remote because it was synced before and the last sync data is not available.`);
241
+ for (const resourcePreview of preview.resourcePreviews) {
242
+ preview = (await this.accept(resourcePreview.remoteResource)) || preview;
243
+ }
244
+ }
245
+ this.updateConflicts(preview.resourcePreviews);
246
+ if (( preview.resourcePreviews.some(({ mergeState }) => mergeState === "conflict" ))) {
247
+ return "hasConflicts" ;
248
+ }
249
+ if (apply) {
250
+ return await this.doApply(false);
251
+ }
252
+ return "syncing" ;
253
+ }
254
+ catch (error) {
255
+ this.syncPreviewPromise = null;
256
+ throw error;
257
+ }
258
+ }
259
+ async merge(resource) {
260
+ await this.updateSyncResourcePreview(resource, async (resourcePreview) => {
261
+ const mergeResult = await this.getMergeResult(resourcePreview, CancellationToken.None);
262
+ await this.fileService.writeFile(resourcePreview.previewResource, VSBuffer.fromString(mergeResult?.content || ''));
263
+ const acceptResult = mergeResult && !mergeResult.hasConflicts
264
+ ? await this.getAcceptResult(resourcePreview, resourcePreview.previewResource, undefined, CancellationToken.None)
265
+ : undefined;
266
+ resourcePreview.acceptResult = acceptResult;
267
+ resourcePreview.mergeState = mergeResult.hasConflicts ? "conflict" : acceptResult ? "accepted" : "preview" ;
268
+ resourcePreview.localChange = acceptResult ? acceptResult.localChange : mergeResult.localChange;
269
+ resourcePreview.remoteChange = acceptResult ? acceptResult.remoteChange : mergeResult.remoteChange;
270
+ return resourcePreview;
271
+ });
272
+ return this.syncPreviewPromise;
273
+ }
274
+ async accept(resource, content) {
275
+ await this.updateSyncResourcePreview(resource, async (resourcePreview) => {
276
+ const acceptResult = await this.getAcceptResult(resourcePreview, resource, content, CancellationToken.None);
277
+ resourcePreview.acceptResult = acceptResult;
278
+ resourcePreview.mergeState = "accepted" ;
279
+ resourcePreview.localChange = acceptResult.localChange;
280
+ resourcePreview.remoteChange = acceptResult.remoteChange;
281
+ return resourcePreview;
282
+ });
283
+ return this.syncPreviewPromise;
284
+ }
285
+ async discard(resource) {
286
+ await this.updateSyncResourcePreview(resource, async (resourcePreview) => {
287
+ const mergeResult = await this.getMergeResult(resourcePreview, CancellationToken.None);
288
+ await this.fileService.writeFile(resourcePreview.previewResource, VSBuffer.fromString(mergeResult.content || ''));
289
+ resourcePreview.acceptResult = undefined;
290
+ resourcePreview.mergeState = "preview" ;
291
+ resourcePreview.localChange = mergeResult.localChange;
292
+ resourcePreview.remoteChange = mergeResult.remoteChange;
293
+ return resourcePreview;
294
+ });
295
+ return this.syncPreviewPromise;
296
+ }
297
+ async updateSyncResourcePreview(resource, updateResourcePreview) {
298
+ if (!this.syncPreviewPromise) {
299
+ return;
300
+ }
301
+ let preview = await this.syncPreviewPromise;
302
+ const index = preview.resourcePreviews.findIndex(({ localResource, remoteResource, previewResource }) => this.extUri.isEqual(localResource, resource) || this.extUri.isEqual(remoteResource, resource) || this.extUri.isEqual(previewResource, resource));
303
+ if (index === -1) {
304
+ return;
305
+ }
306
+ this.syncPreviewPromise = createCancelablePromise(async (token) => {
307
+ const resourcePreviews = [...preview.resourcePreviews];
308
+ resourcePreviews[index] = await updateResourcePreview(resourcePreviews[index]);
309
+ return {
310
+ ...preview,
311
+ resourcePreviews
312
+ };
313
+ });
314
+ preview = await this.syncPreviewPromise;
315
+ this.updateConflicts(preview.resourcePreviews);
316
+ if (( preview.resourcePreviews.some(({ mergeState }) => mergeState === "conflict" ))) {
317
+ this.setStatus("hasConflicts" );
318
+ }
319
+ else {
320
+ this.setStatus("syncing" );
321
+ }
322
+ }
323
+ async doApply(force) {
324
+ if (!this.syncPreviewPromise) {
325
+ return "idle" ;
326
+ }
327
+ const preview = await this.syncPreviewPromise;
328
+ if (( preview.resourcePreviews.some(({ mergeState }) => mergeState === "conflict" ))) {
329
+ return "hasConflicts" ;
330
+ }
331
+ if (( preview.resourcePreviews.some(({ mergeState }) => mergeState !== "accepted" ))) {
332
+ return "syncing" ;
333
+ }
334
+ await this.applyResult(preview.remoteUserData, preview.lastSyncUserData, ( preview.resourcePreviews.map(resourcePreview => ([resourcePreview, resourcePreview.acceptResult]))), force);
335
+ this.syncPreviewPromise = null;
336
+ await this.clearPreviewFolder();
337
+ return "idle" ;
338
+ }
339
+ async clearPreviewFolder() {
340
+ try {
341
+ await this.fileService.del(this.syncPreviewFolder, { recursive: true });
342
+ }
343
+ catch (error) { }
344
+ }
345
+ updateConflicts(resourcePreviews) {
346
+ const conflicts = resourcePreviews.filter(({ mergeState }) => mergeState === "conflict" );
347
+ if (!equals(this._conflicts, conflicts, (a, b) => this.extUri.isEqual(a.previewResource, b.previewResource))) {
348
+ this._conflicts = conflicts;
349
+ this._onDidChangeConflicts.fire(this.conflicts);
350
+ }
351
+ }
352
+ async hasPreviouslySynced() {
353
+ const lastSyncData = await this.getLastSyncUserData();
354
+ return !!lastSyncData && lastSyncData.syncData !== null ;
355
+ }
356
+ async resolvePreviewContent(uri) {
357
+ const syncPreview = this.syncPreviewPromise ? await this.syncPreviewPromise : null;
358
+ if (syncPreview) {
359
+ for (const resourcePreview of syncPreview.resourcePreviews) {
360
+ if (this.extUri.isEqual(resourcePreview.acceptedResource, uri)) {
361
+ return resourcePreview.acceptResult ? resourcePreview.acceptResult.content : null;
362
+ }
363
+ if (this.extUri.isEqual(resourcePreview.remoteResource, uri)) {
364
+ return resourcePreview.remoteContent;
365
+ }
366
+ if (this.extUri.isEqual(resourcePreview.localResource, uri)) {
367
+ return resourcePreview.localContent;
368
+ }
369
+ if (this.extUri.isEqual(resourcePreview.baseResource, uri)) {
370
+ return resourcePreview.baseContent;
371
+ }
372
+ }
373
+ }
374
+ return null;
375
+ }
376
+ async resetLocal() {
377
+ this.storageService.remove(this.lastSyncUserDataStateKey, -1 );
378
+ try {
379
+ await this.fileService.del(this.lastSyncResource);
380
+ }
381
+ catch (error) {
382
+ if (toFileOperationResult(error) !== 1 ) {
383
+ this.logService.error(error);
384
+ }
385
+ }
386
+ }
387
+ async doGenerateSyncResourcePreview(remoteUserData, lastSyncUserData, isRemoteDataFromCurrentMachine, merge, userDataSyncConfiguration, token) {
388
+ const resourcePreviewResults = await this.generateSyncPreview(remoteUserData, lastSyncUserData, isRemoteDataFromCurrentMachine, userDataSyncConfiguration, token);
389
+ const resourcePreviews = [];
390
+ for (const resourcePreviewResult of resourcePreviewResults) {
391
+ const acceptedResource = resourcePreviewResult.previewResource.with({ scheme: USER_DATA_SYNC_SCHEME, authority: 'accepted' });
392
+ if (resourcePreviewResult.localChange === 0 && resourcePreviewResult.remoteChange === 0 ) {
393
+ resourcePreviews.push({
394
+ ...resourcePreviewResult,
395
+ acceptedResource,
396
+ acceptResult: { content: null, localChange: 0 , remoteChange: 0 },
397
+ mergeState: "accepted"
398
+ });
399
+ }
400
+ else {
401
+ const mergeResult = merge ? await this.getMergeResult(resourcePreviewResult, token) : undefined;
402
+ if (token.isCancellationRequested) {
403
+ break;
404
+ }
405
+ await this.fileService.writeFile(resourcePreviewResult.previewResource, VSBuffer.fromString(mergeResult?.content || ''));
406
+ const acceptResult = mergeResult && !mergeResult.hasConflicts
407
+ ? await this.getAcceptResult(resourcePreviewResult, resourcePreviewResult.previewResource, undefined, token)
408
+ : undefined;
409
+ resourcePreviews.push({
410
+ ...resourcePreviewResult,
411
+ acceptResult,
412
+ mergeState: mergeResult?.hasConflicts ? "conflict" : acceptResult ? "accepted" : "preview" ,
413
+ localChange: acceptResult ? acceptResult.localChange : mergeResult ? mergeResult.localChange : resourcePreviewResult.localChange,
414
+ remoteChange: acceptResult ? acceptResult.remoteChange : mergeResult ? mergeResult.remoteChange : resourcePreviewResult.remoteChange
415
+ });
416
+ }
417
+ }
418
+ return { syncResource: this.resource, profile: this.syncResource.profile, remoteUserData, lastSyncUserData, resourcePreviews, isLastSyncFromCurrentMachine: isRemoteDataFromCurrentMachine };
419
+ }
420
+ async getLastSyncUserData() {
421
+ let storedLastSyncUserDataStateContent = this.getStoredLastSyncUserDataStateContent();
422
+ if (!storedLastSyncUserDataStateContent) {
423
+ storedLastSyncUserDataStateContent = await this.migrateLastSyncUserData();
424
+ }
425
+ if (!storedLastSyncUserDataStateContent) {
426
+ this.logService.info(`${this.syncResourceLogLabel}: Last sync data state does not exist.`);
427
+ return null;
428
+ }
429
+ const lastSyncUserDataState = JSON.parse(storedLastSyncUserDataStateContent);
430
+ const resourceSyncStateVersion = this.userDataSyncEnablementService.getResourceSyncStateVersion(this.resource);
431
+ this.hasSyncResourceStateVersionChanged = !!lastSyncUserDataState.version && !!resourceSyncStateVersion && lastSyncUserDataState.version !== resourceSyncStateVersion;
432
+ if (this.hasSyncResourceStateVersionChanged) {
433
+ this.logService.info(`${this.syncResourceLogLabel}: Reset last sync state because last sync state version ${lastSyncUserDataState.version} is not compatible with current sync state version ${resourceSyncStateVersion}.`);
434
+ await this.resetLocal();
435
+ return null;
436
+ }
437
+ let syncData = undefined;
438
+ let retrial = 1;
439
+ while (syncData === undefined && retrial++ < 6 ) {
440
+ try {
441
+ const lastSyncStoredRemoteUserData = await this.readLastSyncStoredRemoteUserData();
442
+ if (lastSyncStoredRemoteUserData) {
443
+ if (lastSyncStoredRemoteUserData.ref === lastSyncUserDataState.ref) {
444
+ syncData = lastSyncStoredRemoteUserData.syncData;
445
+ }
446
+ else {
447
+ this.logService.info(`${this.syncResourceLogLabel}: Last sync data stored locally is not same as the last sync state.`);
448
+ }
449
+ }
450
+ break;
451
+ }
452
+ catch (error) {
453
+ if (error instanceof FileOperationError && error.fileOperationResult === 1 ) {
454
+ this.logService.info(`${this.syncResourceLogLabel}: Last sync resource does not exist locally.`);
455
+ break;
456
+ }
457
+ else if (error instanceof UserDataSyncError) {
458
+ throw error;
459
+ }
460
+ else {
461
+ this.logService.error(error, retrial);
462
+ }
463
+ }
464
+ }
465
+ if (syncData === undefined) {
466
+ try {
467
+ const content = await this.userDataSyncStoreService.resolveResourceContent(this.resource, lastSyncUserDataState.ref, this.collection, this.syncHeaders);
468
+ syncData = content === null ? null : this.parseSyncData(content);
469
+ await this.writeLastSyncStoredRemoteUserData({ ref: lastSyncUserDataState.ref, syncData });
470
+ }
471
+ catch (error) {
472
+ if (error instanceof UserDataSyncError && error.code === "NotFound" ) {
473
+ this.logService.info(`${this.syncResourceLogLabel}: Last sync resource does not exist remotely.`);
474
+ }
475
+ else {
476
+ throw error;
477
+ }
478
+ }
479
+ }
480
+ if (syncData === undefined) {
481
+ return null;
482
+ }
483
+ return {
484
+ ...lastSyncUserDataState,
485
+ syncData,
486
+ };
487
+ }
488
+ async updateLastSyncUserData(lastSyncRemoteUserData, additionalProps = {}) {
489
+ if (additionalProps['ref'] || additionalProps['version']) {
490
+ throw new Error('Cannot have core properties as additional');
491
+ }
492
+ const version = this.userDataSyncEnablementService.getResourceSyncStateVersion(this.resource);
493
+ const lastSyncUserDataState = {
494
+ ref: lastSyncRemoteUserData.ref,
495
+ version,
496
+ ...additionalProps
497
+ };
498
+ this.storageService.store(this.lastSyncUserDataStateKey, JSON.stringify(lastSyncUserDataState), -1 , 1 );
499
+ await this.writeLastSyncStoredRemoteUserData(lastSyncRemoteUserData);
500
+ }
501
+ getStoredLastSyncUserDataStateContent() {
502
+ return this.storageService.get(this.lastSyncUserDataStateKey, -1 );
503
+ }
504
+ async readLastSyncStoredRemoteUserData() {
505
+ const content = ( (await this.fileService.readFile(this.lastSyncResource)).value.toString());
506
+ try {
507
+ const lastSyncStoredRemoteUserData = content ? JSON.parse(content) : undefined;
508
+ if (isRemoteUserData(lastSyncStoredRemoteUserData)) {
509
+ return lastSyncStoredRemoteUserData;
510
+ }
511
+ }
512
+ catch (e) {
513
+ this.logService.error(e);
514
+ }
515
+ return undefined;
516
+ }
517
+ async writeLastSyncStoredRemoteUserData(lastSyncRemoteUserData) {
518
+ await this.fileService.writeFile(this.lastSyncResource, VSBuffer.fromString(JSON.stringify(lastSyncRemoteUserData)));
519
+ }
520
+ async migrateLastSyncUserData() {
521
+ try {
522
+ const content = await this.fileService.readFile(this.lastSyncResource);
523
+ const userData = JSON.parse(( content.value.toString()));
524
+ await this.fileService.del(this.lastSyncResource);
525
+ if (userData.ref && userData.content !== undefined) {
526
+ this.storageService.store(this.lastSyncUserDataStateKey, JSON.stringify({
527
+ ...userData,
528
+ content: undefined,
529
+ }), -1 , 1 );
530
+ await this.writeLastSyncStoredRemoteUserData({ ref: userData.ref, syncData: userData.content === null ? null : JSON.parse(userData.content) });
531
+ }
532
+ else {
533
+ this.logService.info(`${this.syncResourceLogLabel}: Migrating last sync user data. Invalid data.`, userData);
534
+ }
535
+ }
536
+ catch (error) {
537
+ if (error instanceof FileOperationError && error.fileOperationResult === 1 ) {
538
+ this.logService.info(`${this.syncResourceLogLabel}: Migrating last sync user data. Resource does not exist.`);
539
+ }
540
+ else {
541
+ this.logService.error(error);
542
+ }
543
+ }
544
+ return this.storageService.get(this.lastSyncUserDataStateKey, -1 );
545
+ }
546
+ async getRemoteUserData(lastSyncData) {
547
+ const { ref, content } = await this.getUserData(lastSyncData);
548
+ let syncData = null;
549
+ if (content !== null) {
550
+ syncData = this.parseSyncData(content);
551
+ }
552
+ return { ref, syncData };
553
+ }
554
+ parseSyncData(content) {
555
+ try {
556
+ const syncData = JSON.parse(content);
557
+ if (isSyncData(syncData)) {
558
+ return syncData;
559
+ }
560
+ }
561
+ catch (error) {
562
+ this.logService.error(error);
563
+ }
564
+ throw new UserDataSyncError(localizeWithPath('vs/platform/userDataSync/common/abstractSynchronizer', 'incompatible sync data', "Cannot parse sync data as it is not compatible with the current version."), "IncompatibleRemoteContent" , this.resource);
565
+ }
566
+ async getUserData(lastSyncData) {
567
+ const lastSyncUserData = lastSyncData ? { ref: lastSyncData.ref, content: lastSyncData.syncData ? JSON.stringify(lastSyncData.syncData) : null } : null;
568
+ return this.userDataSyncStoreService.readResource(this.resource, lastSyncUserData, this.collection, this.syncHeaders);
569
+ }
570
+ async updateRemoteUserData(content, ref) {
571
+ const machineId = await this.currentMachineIdPromise;
572
+ const syncData = { version: this.version, machineId, content };
573
+ try {
574
+ ref = await this.userDataSyncStoreService.writeResource(this.resource, JSON.stringify(syncData), ref, this.collection, this.syncHeaders);
575
+ return { ref, syncData };
576
+ }
577
+ catch (error) {
578
+ if (error instanceof UserDataSyncError && error.code === "TooLarge" ) {
579
+ error = ( new UserDataSyncError(error.message, error.code, this.resource));
580
+ }
581
+ throw error;
582
+ }
583
+ }
584
+ async backupLocal(content) {
585
+ const syncData = { version: this.version, content };
586
+ return this.userDataSyncLocalStoreService.writeResource(this.resource, JSON.stringify(syncData), ( new Date()), this.syncResource.profile.isDefault ? undefined : this.syncResource.profile.id);
587
+ }
588
+ async stop() {
589
+ if (this.status === "idle" ) {
590
+ return;
591
+ }
592
+ this.logService.trace(`${this.syncResourceLogLabel}: Stopping synchronizing ${this.resource.toLowerCase()}.`);
593
+ if (this.syncPreviewPromise) {
594
+ this.syncPreviewPromise.cancel();
595
+ this.syncPreviewPromise = null;
596
+ }
597
+ this.updateConflicts([]);
598
+ await this.clearPreviewFolder();
599
+ this.setStatus("idle" );
600
+ this.logService.info(`${this.syncResourceLogLabel}: Stopped synchronizing ${this.resource.toLowerCase()}.`);
601
+ }
602
+ getUserDataSyncConfiguration() {
603
+ return this.configurationService.getValue(USER_DATA_SYNC_CONFIGURATION_SCOPE);
604
+ }
605
+ };
606
+ AbstractSynchroniser = ( __decorate([
607
+ ( __param(2, IFileService)),
608
+ ( __param(3, IEnvironmentService)),
609
+ ( __param(4, IStorageService)),
610
+ ( __param(5, IUserDataSyncStoreService)),
611
+ ( __param(6, IUserDataSyncLocalStoreService)),
612
+ ( __param(7, IUserDataSyncEnablementService)),
613
+ ( __param(8, ITelemetryService)),
614
+ ( __param(9, IUserDataSyncLogService)),
615
+ ( __param(10, IConfigurationService)),
616
+ ( __param(11, IUriIdentityService))
617
+ ], AbstractSynchroniser));
618
+ let AbstractFileSynchroniser = class AbstractFileSynchroniser extends AbstractSynchroniser {
619
+ constructor(file, syncResource, collection, fileService, environmentService, storageService, userDataSyncStoreService, userDataSyncLocalStoreService, userDataSyncEnablementService, telemetryService, logService, configurationService, uriIdentityService) {
620
+ super(syncResource, collection, fileService, environmentService, storageService, userDataSyncStoreService, userDataSyncLocalStoreService, userDataSyncEnablementService, telemetryService, logService, configurationService, uriIdentityService);
621
+ this.file = file;
622
+ this._register(this.fileService.watch(this.extUri.dirname(file)));
623
+ this._register(this.fileService.onDidFilesChange(e => this.onFileChanges(e)));
624
+ }
625
+ async getLocalFileContent() {
626
+ try {
627
+ return await this.fileService.readFile(this.file);
628
+ }
629
+ catch (error) {
630
+ return null;
631
+ }
632
+ }
633
+ async updateLocalFileContent(newContent, oldContent, force) {
634
+ try {
635
+ if (oldContent) {
636
+ await this.fileService.writeFile(this.file, VSBuffer.fromString(newContent), force ? undefined : oldContent);
637
+ }
638
+ else {
639
+ await this.fileService.createFile(this.file, VSBuffer.fromString(newContent), { overwrite: force });
640
+ }
641
+ }
642
+ catch (e) {
643
+ if (((e instanceof FileOperationError && e.fileOperationResult === 1) ) ||
644
+ ((e instanceof FileOperationError && e.fileOperationResult === 3) )) {
645
+ throw new UserDataSyncError(e.message, "LocalPreconditionFailed" );
646
+ }
647
+ else {
648
+ throw e;
649
+ }
650
+ }
651
+ }
652
+ async deleteLocalFile() {
653
+ try {
654
+ await this.fileService.del(this.file);
655
+ }
656
+ catch (e) {
657
+ if (!((e instanceof FileOperationError && e.fileOperationResult === 1) )) {
658
+ throw e;
659
+ }
660
+ }
661
+ }
662
+ onFileChanges(e) {
663
+ if (!e.contains(this.file)) {
664
+ return;
665
+ }
666
+ this.triggerLocalChange();
667
+ }
668
+ };
669
+ AbstractFileSynchroniser = ( __decorate([
670
+ ( __param(3, IFileService)),
671
+ ( __param(4, IEnvironmentService)),
672
+ ( __param(5, IStorageService)),
673
+ ( __param(6, IUserDataSyncStoreService)),
674
+ ( __param(7, IUserDataSyncLocalStoreService)),
675
+ ( __param(8, IUserDataSyncEnablementService)),
676
+ ( __param(9, ITelemetryService)),
677
+ ( __param(10, IUserDataSyncLogService)),
678
+ ( __param(11, IConfigurationService)),
679
+ ( __param(12, IUriIdentityService))
680
+ ], AbstractFileSynchroniser));
681
+ let AbstractJsonFileSynchroniser = class AbstractJsonFileSynchroniser extends AbstractFileSynchroniser {
682
+ constructor(file, syncResource, collection, fileService, environmentService, storageService, userDataSyncStoreService, userDataSyncLocalStoreService, userDataSyncEnablementService, telemetryService, logService, userDataSyncUtilService, configurationService, uriIdentityService) {
683
+ super(file, syncResource, collection, fileService, environmentService, storageService, userDataSyncStoreService, userDataSyncLocalStoreService, userDataSyncEnablementService, telemetryService, logService, configurationService, uriIdentityService);
684
+ this.userDataSyncUtilService = userDataSyncUtilService;
685
+ this._formattingOptions = undefined;
686
+ }
687
+ hasErrors(content, isArray) {
688
+ const parseErrors = [];
689
+ const result = parse(content, parseErrors, { allowEmptyContent: true, allowTrailingComma: true });
690
+ return parseErrors.length > 0 || (!isUndefined(result) && isArray !== Array.isArray(result));
691
+ }
692
+ getFormattingOptions() {
693
+ if (!this._formattingOptions) {
694
+ this._formattingOptions = this.userDataSyncUtilService.resolveFormattingOptions(this.file);
695
+ }
696
+ return this._formattingOptions;
697
+ }
698
+ };
699
+ AbstractJsonFileSynchroniser = ( __decorate([
700
+ ( __param(3, IFileService)),
701
+ ( __param(4, IEnvironmentService)),
702
+ ( __param(5, IStorageService)),
703
+ ( __param(6, IUserDataSyncStoreService)),
704
+ ( __param(7, IUserDataSyncLocalStoreService)),
705
+ ( __param(8, IUserDataSyncEnablementService)),
706
+ ( __param(9, ITelemetryService)),
707
+ ( __param(10, IUserDataSyncLogService)),
708
+ ( __param(11, IUserDataSyncUtilService)),
709
+ ( __param(12, IConfigurationService)),
710
+ ( __param(13, IUriIdentityService))
711
+ ], AbstractJsonFileSynchroniser));
712
+ let AbstractInitializer = class AbstractInitializer {
713
+ constructor(resource, userDataProfilesService, environmentService, logService, fileService, storageService, uriIdentityService) {
714
+ this.resource = resource;
715
+ this.userDataProfilesService = userDataProfilesService;
716
+ this.environmentService = environmentService;
717
+ this.logService = logService;
718
+ this.fileService = fileService;
719
+ this.storageService = storageService;
720
+ this.extUri = uriIdentityService.extUri;
721
+ this.lastSyncResource = getLastSyncResourceUri(undefined, this.resource, environmentService, this.extUri);
722
+ }
723
+ async initialize({ ref, content }) {
724
+ if (!content) {
725
+ this.logService.info('Remote content does not exist.', this.resource);
726
+ return;
727
+ }
728
+ const syncData = this.parseSyncData(content);
729
+ if (!syncData) {
730
+ return;
731
+ }
732
+ try {
733
+ await this.doInitialize({ ref, syncData });
734
+ }
735
+ catch (error) {
736
+ this.logService.error(error);
737
+ }
738
+ }
739
+ parseSyncData(content) {
740
+ try {
741
+ const syncData = JSON.parse(content);
742
+ if (isSyncData(syncData)) {
743
+ return syncData;
744
+ }
745
+ }
746
+ catch (error) {
747
+ this.logService.error(error);
748
+ }
749
+ this.logService.info('Cannot parse sync data as it is not compatible with the current version.', this.resource);
750
+ return undefined;
751
+ }
752
+ async updateLastSyncUserData(lastSyncRemoteUserData, additionalProps = {}) {
753
+ if (additionalProps['ref'] || additionalProps['version']) {
754
+ throw new Error('Cannot have core properties as additional');
755
+ }
756
+ const lastSyncUserDataState = {
757
+ ref: lastSyncRemoteUserData.ref,
758
+ version: undefined,
759
+ ...additionalProps
760
+ };
761
+ this.storageService.store(`${this.resource}.lastSyncUserData`, JSON.stringify(lastSyncUserDataState), -1 , 1 );
762
+ await this.fileService.writeFile(this.lastSyncResource, VSBuffer.fromString(JSON.stringify(lastSyncRemoteUserData)));
763
+ }
764
+ };
765
+ AbstractInitializer = ( __decorate([
766
+ ( __param(1, IUserDataProfilesService)),
767
+ ( __param(2, IEnvironmentService)),
768
+ ( __param(3, ILogService)),
769
+ ( __param(4, IFileService)),
770
+ ( __param(5, IStorageService)),
771
+ ( __param(6, IUriIdentityService))
772
+ ], AbstractInitializer));
773
+
774
+ export { AbstractFileSynchroniser, AbstractInitializer, AbstractJsonFileSynchroniser, AbstractSynchroniser, getSyncResourceLogLabel, isRemoteUserData, isSyncData };