Skip to content

Commit 49dec73

Browse files
authored
Revert "disable initializing user data (microsoft#173560)" (microsoft#175134)
This reverts commit ca480b0.
1 parent 074090c commit 49dec73

File tree

15 files changed

+1029
-17
lines changed

15 files changed

+1029
-17
lines changed

src/vs/platform/userDataSync/common/abstractSynchronizer.ts

Lines changed: 71 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,13 @@ import { localize } from 'vs/nls';
2121
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
2222
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
2323
import { FileChangesEvent, FileOperationError, FileOperationResult, IFileContent, IFileService, toFileOperationResult } from 'vs/platform/files/common/files';
24+
import { ILogService } from 'vs/platform/log/common/log';
2425
import { getServiceMachineId } from 'vs/platform/externalServices/common/serviceMachineId';
2526
import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
2627
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
2728
import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity';
28-
import { Change, getLastSyncResourceUri, IRemoteUserData, IResourcePreview as IBaseResourcePreview, ISyncData, IUserDataSyncResourcePreview as IBaseSyncResourcePreview, IUserData, IUserDataSyncBackupStoreService, IUserDataSyncConfiguration, IUserDataSynchroniser, IUserDataSyncLogService, IUserDataSyncEnablementService, IUserDataSyncStoreService, IUserDataSyncUtilService, MergeState, PREVIEW_DIR_NAME, SyncResource, SyncStatus, UserDataSyncError, UserDataSyncErrorCode, USER_DATA_SYNC_CONFIGURATION_SCOPE, USER_DATA_SYNC_SCHEME, IUserDataResourceManifest, getPathSegments, IUserDataSyncResourceConflicts, IUserDataSyncResource } from 'vs/platform/userDataSync/common/userDataSync';
29-
import { IUserDataProfile } from 'vs/platform/userDataProfile/common/userDataProfile';
29+
import { Change, getLastSyncResourceUri, IRemoteUserData, IResourcePreview as IBaseResourcePreview, ISyncData, IUserDataSyncResourcePreview as IBaseSyncResourcePreview, IUserData, IUserDataInitializer, IUserDataSyncBackupStoreService, IUserDataSyncConfiguration, IUserDataSynchroniser, IUserDataSyncLogService, IUserDataSyncEnablementService, IUserDataSyncStoreService, IUserDataSyncUtilService, MergeState, PREVIEW_DIR_NAME, SyncResource, SyncStatus, UserDataSyncError, UserDataSyncErrorCode, USER_DATA_SYNC_CONFIGURATION_SCOPE, USER_DATA_SYNC_SCHEME, IUserDataResourceManifest, getPathSegments, IUserDataSyncResourceConflicts, IUserDataSyncResource } from 'vs/platform/userDataSync/common/userDataSync';
30+
import { IUserDataProfile, IUserDataProfilesService } from 'vs/platform/userDataProfile/common/userDataProfile';
3031

3132
type IncompatibleSyncSourceClassification = {
3233
owner: 'sandy081';
@@ -913,3 +914,71 @@ export abstract class AbstractJsonFileSynchroniser extends AbstractFileSynchroni
913914
}
914915

915916
}
917+
918+
export abstract class AbstractInitializer implements IUserDataInitializer {
919+
920+
protected readonly extUri: IExtUri;
921+
private readonly lastSyncResource: URI;
922+
923+
constructor(
924+
readonly resource: SyncResource,
925+
@IUserDataProfilesService protected readonly userDataProfilesService: IUserDataProfilesService,
926+
@IEnvironmentService protected readonly environmentService: IEnvironmentService,
927+
@ILogService protected readonly logService: ILogService,
928+
@IFileService protected readonly fileService: IFileService,
929+
@IStorageService protected readonly storageService: IStorageService,
930+
@IUriIdentityService uriIdentityService: IUriIdentityService,
931+
) {
932+
this.extUri = uriIdentityService.extUri;
933+
this.lastSyncResource = getLastSyncResourceUri(undefined, this.resource, environmentService, this.extUri);
934+
}
935+
936+
async initialize({ ref, content }: IUserData): Promise<void> {
937+
if (!content) {
938+
this.logService.info('Remote content does not exist.', this.resource);
939+
return;
940+
}
941+
942+
const syncData = this.parseSyncData(content);
943+
if (!syncData) {
944+
return;
945+
}
946+
947+
try {
948+
await this.doInitialize({ ref, syncData });
949+
} catch (error) {
950+
this.logService.error(error);
951+
}
952+
}
953+
954+
private parseSyncData(content: string): ISyncData | undefined {
955+
try {
956+
const syncData: ISyncData = JSON.parse(content);
957+
if (isSyncData(syncData)) {
958+
return syncData;
959+
}
960+
} catch (error) {
961+
this.logService.error(error);
962+
}
963+
this.logService.info('Cannot parse sync data as it is not compatible with the current version.', this.resource);
964+
return undefined;
965+
}
966+
967+
protected async updateLastSyncUserData(lastSyncRemoteUserData: IRemoteUserData, additionalProps: IStringDictionary<any> = {}): Promise<void> {
968+
if (additionalProps['ref'] || additionalProps['version']) {
969+
throw new Error('Cannot have core properties as additional');
970+
}
971+
972+
const lastSyncUserDataState: ILastSyncUserDataState = {
973+
ref: lastSyncRemoteUserData.ref,
974+
version: undefined,
975+
...additionalProps
976+
};
977+
978+
this.storageService.store(`${this.resource}.lastSyncUserData`, JSON.stringify(lastSyncUserDataState), StorageScope.APPLICATION, StorageTarget.MACHINE);
979+
await this.fileService.writeFile(this.lastSyncResource, VSBuffer.fromString(JSON.stringify(lastSyncRemoteUserData)));
980+
}
981+
982+
protected abstract doInitialize(remoteUserData: IRemoteUserData): Promise<void>;
983+
984+
}

src/vs/platform/userDataSync/common/extensionsSync.ts

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,12 @@ import { ExtensionType, IExtensionIdentifier } from 'vs/platform/extensions/comm
2222
import { IFileService } from 'vs/platform/files/common/files';
2323
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
2424
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
25+
import { ILogService } from 'vs/platform/log/common/log';
2526
import { IStorageService } from 'vs/platform/storage/common/storage';
2627
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
2728
import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity';
28-
import { IUserDataProfile } from 'vs/platform/userDataProfile/common/userDataProfile';
29-
import { AbstractSynchroniser, getSyncResourceLogLabel, IAcceptResult, IMergeResult, IResourcePreview } from 'vs/platform/userDataSync/common/abstractSynchronizer';
29+
import { IUserDataProfile, IUserDataProfilesService } from 'vs/platform/userDataProfile/common/userDataProfile';
30+
import { AbstractInitializer, AbstractSynchroniser, getSyncResourceLogLabel, IAcceptResult, IMergeResult, IResourcePreview } from 'vs/platform/userDataSync/common/abstractSynchronizer';
3031
import { IMergeResult as IExtensionMergeResult, merge } from 'vs/platform/userDataSync/common/extensionsMerge';
3132
import { IIgnoredExtensionsManagementService } from 'vs/platform/userDataSync/common/ignoredExtensions';
3233
import { Change, IRemoteUserData, ISyncData, ISyncExtension, IUserDataSyncBackupStoreService, IUserDataSynchroniser, IUserDataSyncLogService, IUserDataSyncEnablementService, IUserDataSyncStoreService, SyncResource, USER_DATA_SYNC_SCHEME, ILocalSyncExtension } from 'vs/platform/userDataSync/common/userDataSync';
@@ -568,3 +569,57 @@ export class LocalExtensionsProvider {
568569
}
569570

570571
}
572+
573+
export interface IExtensionsInitializerPreviewResult {
574+
readonly installedExtensions: ILocalExtension[];
575+
readonly disabledExtensions: IExtensionIdentifier[];
576+
readonly newExtensions: (IExtensionIdentifier & { preRelease: boolean })[];
577+
readonly remoteExtensions: ISyncExtension[];
578+
}
579+
580+
export abstract class AbstractExtensionsInitializer extends AbstractInitializer {
581+
582+
constructor(
583+
@IExtensionManagementService protected readonly extensionManagementService: IExtensionManagementService,
584+
@IIgnoredExtensionsManagementService private readonly ignoredExtensionsManagementService: IIgnoredExtensionsManagementService,
585+
@IFileService fileService: IFileService,
586+
@IUserDataProfilesService userDataProfilesService: IUserDataProfilesService,
587+
@IEnvironmentService environmentService: IEnvironmentService,
588+
@ILogService logService: ILogService,
589+
@IStorageService storageService: IStorageService,
590+
@IUriIdentityService uriIdentityService: IUriIdentityService,
591+
) {
592+
super(SyncResource.Extensions, userDataProfilesService, environmentService, logService, fileService, storageService, uriIdentityService);
593+
}
594+
595+
protected async parseExtensions(remoteUserData: IRemoteUserData): Promise<ISyncExtension[] | null> {
596+
return remoteUserData.syncData ? await parseAndMigrateExtensions(remoteUserData.syncData, this.extensionManagementService) : null;
597+
}
598+
599+
protected generatePreview(remoteExtensions: ISyncExtension[], localExtensions: ILocalExtension[]): IExtensionsInitializerPreviewResult {
600+
const installedExtensions: ILocalExtension[] = [];
601+
const newExtensions: (IExtensionIdentifier & { preRelease: boolean })[] = [];
602+
const disabledExtensions: IExtensionIdentifier[] = [];
603+
for (const extension of remoteExtensions) {
604+
if (this.ignoredExtensionsManagementService.hasToNeverSyncExtension(extension.identifier.id)) {
605+
// Skip extension ignored to sync
606+
continue;
607+
}
608+
609+
const installedExtension = localExtensions.find(i => areSameExtensions(i.identifier, extension.identifier));
610+
if (installedExtension) {
611+
installedExtensions.push(installedExtension);
612+
if (extension.disabled) {
613+
disabledExtensions.push(extension.identifier);
614+
}
615+
} else if (extension.installed) {
616+
newExtensions.push({ ...extension.identifier, preRelease: !!extension.preRelease });
617+
if (extension.disabled) {
618+
disabledExtensions.push(extension.identifier);
619+
}
620+
}
621+
}
622+
return { installedExtensions, newExtensions, disabledExtensions, remoteExtensions };
623+
}
624+
625+
}

src/vs/platform/userDataSync/common/globalStateSync.ts

Lines changed: 56 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,15 @@ import { IEnvironmentService } from 'vs/platform/environment/common/environment'
1919
import { IFileService } from 'vs/platform/files/common/files';
2020
import { ILogService } from 'vs/platform/log/common/log';
2121
import { getServiceMachineId } from 'vs/platform/externalServices/common/serviceMachineId';
22-
import { IStorageService, StorageTarget } from 'vs/platform/storage/common/storage';
22+
import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
2323
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
2424
import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity';
25-
import { AbstractSynchroniser, getSyncResourceLogLabel, IAcceptResult, IMergeResult, IResourcePreview, isSyncData } from 'vs/platform/userDataSync/common/abstractSynchronizer';
25+
import { AbstractInitializer, AbstractSynchroniser, getSyncResourceLogLabel, IAcceptResult, IMergeResult, IResourcePreview, isSyncData } from 'vs/platform/userDataSync/common/abstractSynchronizer';
2626
import { edit } from 'vs/platform/userDataSync/common/content';
2727
import { merge } from 'vs/platform/userDataSync/common/globalStateMerge';
2828
import { ALL_SYNC_RESOURCES, Change, createSyncHeaders, getEnablementKey, IGlobalState, IRemoteUserData, IStorageValue, ISyncData, IUserData, IUserDataSyncBackupStoreService, IUserDataSynchroniser, IUserDataSyncLogService, IUserDataSyncEnablementService, IUserDataSyncStoreService, SyncResource, SYNC_SERVICE_URL_TYPE, UserDataSyncError, UserDataSyncErrorCode, UserDataSyncStoreType, USER_DATA_SYNC_SCHEME } from 'vs/platform/userDataSync/common/userDataSync';
2929
import { UserDataSyncStoreClient } from 'vs/platform/userDataSync/common/userDataSyncStoreService';
30-
import { IUserDataProfile } from 'vs/platform/userDataProfile/common/userDataProfile';
30+
import { IUserDataProfile, IUserDataProfilesService } from 'vs/platform/userDataProfile/common/userDataProfile';
3131
import { IUserDataProfileStorageService } from 'vs/platform/userDataProfile/common/userDataProfileStorageService';
3232
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
3333

@@ -395,6 +395,59 @@ export class LocalGlobalStateProvider {
395395
}
396396
}
397397

398+
export class GlobalStateInitializer extends AbstractInitializer {
399+
400+
constructor(
401+
@IStorageService storageService: IStorageService,
402+
@IFileService fileService: IFileService,
403+
@IUserDataProfilesService userDataProfilesService: IUserDataProfilesService,
404+
@IEnvironmentService environmentService: IEnvironmentService,
405+
@IUserDataSyncLogService logService: IUserDataSyncLogService,
406+
@IUriIdentityService uriIdentityService: IUriIdentityService,
407+
) {
408+
super(SyncResource.GlobalState, userDataProfilesService, environmentService, logService, fileService, storageService, uriIdentityService);
409+
}
410+
411+
protected async doInitialize(remoteUserData: IRemoteUserData): Promise<void> {
412+
const remoteGlobalState: IGlobalState = remoteUserData.syncData ? JSON.parse(remoteUserData.syncData.content) : null;
413+
if (!remoteGlobalState) {
414+
this.logService.info('Skipping initializing global state because remote global state does not exist.');
415+
return;
416+
}
417+
418+
const argv: IStringDictionary<any> = {};
419+
const storage: IStringDictionary<any> = {};
420+
for (const key of Object.keys(remoteGlobalState.storage)) {
421+
if (key.startsWith(argvStoragePrefx)) {
422+
argv[key.substring(argvStoragePrefx.length)] = remoteGlobalState.storage[key].value;
423+
} else {
424+
if (this.storageService.get(key, StorageScope.PROFILE) === undefined) {
425+
storage[key] = remoteGlobalState.storage[key].value;
426+
}
427+
}
428+
}
429+
430+
if (Object.keys(argv).length) {
431+
let content = '{}';
432+
try {
433+
const fileContent = await this.fileService.readFile(this.environmentService.argvResource);
434+
content = fileContent.value.toString();
435+
} catch (error) { }
436+
for (const argvProperty of Object.keys(argv)) {
437+
content = edit(content, [argvProperty], argv[argvProperty], {});
438+
}
439+
await this.fileService.writeFile(this.environmentService.argvResource, VSBuffer.fromString(content));
440+
}
441+
442+
if (Object.keys(storage).length) {
443+
for (const key of Object.keys(storage)) {
444+
this.storageService.store(key, storage[key], StorageScope.PROFILE, StorageTarget.USER);
445+
}
446+
}
447+
}
448+
449+
}
450+
398451
export class UserDataSyncStoreTypeSynchronizer {
399452

400453
constructor(

src/vs/platform/userDataSync/common/keybindingsSync.ts

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
*--------------------------------------------------------------------------------------------*/
55

66
import { isNonEmptyArray } from 'vs/base/common/arrays';
7+
import { VSBuffer } from 'vs/base/common/buffer';
78
import { CancellationToken } from 'vs/base/common/cancellation';
89
import { Event } from 'vs/base/common/event';
910
import { parse } from 'vs/base/common/json';
@@ -18,8 +19,8 @@ import { ILogService } from 'vs/platform/log/common/log';
1819
import { IStorageService } from 'vs/platform/storage/common/storage';
1920
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
2021
import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity';
21-
import { IUserDataProfile } from 'vs/platform/userDataProfile/common/userDataProfile';
22-
import { AbstractJsonFileSynchroniser, IAcceptResult, IFileResourcePreview, IMergeResult } from 'vs/platform/userDataSync/common/abstractSynchronizer';
22+
import { IUserDataProfile, IUserDataProfilesService } from 'vs/platform/userDataProfile/common/userDataProfile';
23+
import { AbstractInitializer, AbstractJsonFileSynchroniser, IAcceptResult, IFileResourcePreview, IMergeResult } from 'vs/platform/userDataSync/common/abstractSynchronizer';
2324
import { merge } from 'vs/platform/userDataSync/common/keybindingsMerge';
2425
import { Change, IRemoteUserData, IUserDataSyncBackupStoreService, IUserDataSyncConfiguration, IUserDataSynchroniser, IUserDataSyncLogService, IUserDataSyncEnablementService, IUserDataSyncStoreService, IUserDataSyncUtilService, SyncResource, UserDataSyncError, UserDataSyncErrorCode, USER_DATA_SYNC_SCHEME, CONFIG_SYNC_KEYBINDINGS_PER_PLATFORM } from 'vs/platform/userDataSync/common/userDataSync';
2526

@@ -336,3 +337,55 @@ export class KeybindingsSynchroniser extends AbstractJsonFileSynchroniser implem
336337
}
337338

338339
}
340+
341+
export class KeybindingsInitializer extends AbstractInitializer {
342+
343+
constructor(
344+
@IFileService fileService: IFileService,
345+
@IUserDataProfilesService userDataProfilesService: IUserDataProfilesService,
346+
@IEnvironmentService environmentService: IEnvironmentService,
347+
@IUserDataSyncLogService logService: IUserDataSyncLogService,
348+
@IStorageService storageService: IStorageService,
349+
@IUriIdentityService uriIdentityService: IUriIdentityService,
350+
) {
351+
super(SyncResource.Keybindings, userDataProfilesService, environmentService, logService, fileService, storageService, uriIdentityService);
352+
}
353+
354+
protected async doInitialize(remoteUserData: IRemoteUserData): Promise<void> {
355+
const keybindingsContent = remoteUserData.syncData ? this.getKeybindingsContentFromSyncContent(remoteUserData.syncData.content) : null;
356+
if (!keybindingsContent) {
357+
this.logService.info('Skipping initializing keybindings because remote keybindings does not exist.');
358+
return;
359+
}
360+
361+
const isEmpty = await this.isEmpty();
362+
if (!isEmpty) {
363+
this.logService.info('Skipping initializing keybindings because local keybindings exist.');
364+
return;
365+
}
366+
367+
await this.fileService.writeFile(this.userDataProfilesService.defaultProfile.keybindingsResource, VSBuffer.fromString(keybindingsContent));
368+
369+
await this.updateLastSyncUserData(remoteUserData);
370+
}
371+
372+
private async isEmpty(): Promise<boolean> {
373+
try {
374+
const fileContent = await this.fileService.readFile(this.userDataProfilesService.defaultProfile.settingsResource);
375+
const keybindings = parse(fileContent.value.toString());
376+
return !isNonEmptyArray(keybindings);
377+
} catch (error) {
378+
return (<FileOperationError>error).fileOperationResult === FileOperationResult.FILE_NOT_FOUND;
379+
}
380+
}
381+
382+
private getKeybindingsContentFromSyncContent(syncContent: string): string | null {
383+
try {
384+
return getKeybindingsContentFromSyncContent(syncContent, true, this.logService);
385+
} catch (e) {
386+
this.logService.error(e);
387+
return null;
388+
}
389+
}
390+
391+
}

0 commit comments

Comments
 (0)