Skip to content

Commit b089ff1

Browse files
committed
microsoft#86678 Enhance back up views
- Show individual resources
1 parent 47a5274 commit b089ff1

16 files changed

Lines changed: 278 additions & 410 deletions

File tree

src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ import { IProductService } from 'vs/platform/product/common/productService';
5252
import { IUserDataSyncService, IUserDataSyncStoreService, registerConfiguration, IUserDataSyncLogService, IUserDataSyncUtilService, IUserDataSyncEnablementService, IUserDataSyncBackupStoreService } from 'vs/platform/userDataSync/common/userDataSync';
5353
import { UserDataSyncService } from 'vs/platform/userDataSync/common/userDataSyncService';
5454
import { UserDataSyncStoreService } from 'vs/platform/userDataSync/common/userDataSyncStoreService';
55-
import { UserDataSyncChannel, UserDataSyncUtilServiceClient, UserDataAutoSyncChannel, UserDataSyncStoreServiceChannel, UserDataSyncBackupStoreServiceChannel } from 'vs/platform/userDataSync/common/userDataSyncIpc';
55+
import { UserDataSyncChannel, UserDataSyncUtilServiceClient, UserDataAutoSyncChannel } from 'vs/platform/userDataSync/common/userDataSyncIpc';
5656
import { IElectronService } from 'vs/platform/electron/node/electron';
5757
import { LoggerService } from 'vs/platform/log/node/loggerService';
5858
import { UserDataSyncLogService } from 'vs/platform/userDataSync/common/userDataSyncLog';
@@ -219,14 +219,6 @@ async function main(server: Server, initData: ISharedProcessInitData, configurat
219219
const authTokenChannel = new AuthenticationTokenServiceChannel(authTokenService);
220220
server.registerChannel('authToken', authTokenChannel);
221221

222-
const userDataSyncStoreService = accessor.get(IUserDataSyncStoreService);
223-
const userDataSyncStoreServiceChannel = new UserDataSyncStoreServiceChannel(userDataSyncStoreService);
224-
server.registerChannel('userDataSyncStoreService', userDataSyncStoreServiceChannel);
225-
226-
const userDataSyncBackupStoreService = accessor.get(IUserDataSyncBackupStoreService);
227-
const userDataSyncBackupStoreServiceChannel = new UserDataSyncBackupStoreServiceChannel(userDataSyncBackupStoreService);
228-
server.registerChannel('userDataSyncBackupStoreService', userDataSyncBackupStoreServiceChannel);
229-
230222
const userDataSyncService = accessor.get(IUserDataSyncService);
231223
const userDataSyncChannel = new UserDataSyncChannel(userDataSyncService);
232224
server.registerChannel('userDataSync', userDataSyncChannel);

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

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ import { Disposable } from 'vs/base/common/lifecycle';
77
import { IFileService, IFileContent, FileChangesEvent, FileOperationResult, FileOperationError } from 'vs/platform/files/common/files';
88
import { VSBuffer } from 'vs/base/common/buffer';
99
import { URI } from 'vs/base/common/uri';
10-
import { SyncResource, SyncStatus, IUserData, IUserDataSyncStoreService, UserDataSyncErrorCode, UserDataSyncError, IUserDataSyncLogService, IUserDataSyncUtilService, IUserDataSyncEnablementService, IUserDataSyncBackupStoreService, Conflict } from 'vs/platform/userDataSync/common/userDataSync';
10+
import { SyncResource, SyncStatus, IUserData, IUserDataSyncStoreService, UserDataSyncErrorCode, UserDataSyncError, IUserDataSyncLogService, IUserDataSyncUtilService, IUserDataSyncEnablementService, IUserDataSyncBackupStoreService, Conflict, ISyncResourceHandle, USER_DATA_SYNC_SCHEME } from 'vs/platform/userDataSync/common/userDataSync';
1111
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
12-
import { joinPath, dirname, isEqual } from 'vs/base/common/resources';
12+
import { joinPath, dirname, isEqual, basename } from 'vs/base/common/resources';
1313
import { CancelablePromise } from 'vs/base/common/async';
1414
import { Emitter, Event } from 'vs/base/common/event';
1515
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
@@ -173,18 +173,34 @@ export abstract class AbstractSynchroniser extends Disposable {
173173
return !!lastSyncData;
174174
}
175175

176-
async getConflictContent(conflictResource: URI): Promise<string | null> {
177-
return null;
176+
async getRemoteSyncResourceHandles(): Promise<ISyncResourceHandle[]> {
177+
const handles = await this.userDataSyncStoreService.getAllRefs(this.resource);
178+
return handles.map(({ created, ref }) => ({ created, uri: this.toRemoteBackupResource(ref) }));
179+
}
180+
181+
async getLocalSyncResourceHandles(): Promise<ISyncResourceHandle[]> {
182+
const handles = await this.userDataSyncBackupStoreService.getAllRefs(this.resource);
183+
return handles.map(({ created, ref }) => ({ created, uri: this.toLocalBackupResource(ref) }));
178184
}
179185

180-
async getRemoteContent(ref?: string): Promise<string | null> {
181-
const refOrLastSyncUserData: string | IRemoteUserData | null = ref || await this.getLastSyncUserData();
182-
const { content } = await this.getUserData(refOrLastSyncUserData);
183-
return content;
186+
private toRemoteBackupResource(ref: string): URI {
187+
return URI.from({ scheme: USER_DATA_SYNC_SCHEME, authority: 'remote-backup', path: `/${this.resource}/${ref}` });
184188
}
185189

186-
async getLocalBackupContent(ref?: string): Promise<string | null> {
187-
return this.userDataSyncBackupStoreService.resolveContent(this.resource, ref);
190+
private toLocalBackupResource(ref: string): URI {
191+
return URI.from({ scheme: USER_DATA_SYNC_SCHEME, authority: 'local-backup', path: `/${this.resource}/${ref}` });
192+
}
193+
194+
async resolveContent(uri: URI): Promise<string | null> {
195+
const ref = basename(uri);
196+
if (isEqual(uri, this.toRemoteBackupResource(ref))) {
197+
const { content } = await this.getUserData(ref);
198+
return content;
199+
}
200+
if (isEqual(uri, this.toLocalBackupResource(ref))) {
201+
return this.userDataSyncBackupStoreService.resolveContent(this.resource, ref);
202+
}
203+
return null;
188204
}
189205

190206
async resetLocal(): Promise<void> {
@@ -265,9 +281,10 @@ export abstract class AbstractSynchroniser extends Disposable {
265281
return this.userDataSyncBackupStoreService.backup(this.resource, JSON.stringify(syncData));
266282
}
267283

284+
abstract stop(): Promise<void>;
285+
268286
protected abstract readonly version: number;
269287
protected abstract performSync(remoteUserData: IRemoteUserData, lastSyncUserData: IRemoteUserData | null): Promise<SyncStatus>;
270-
abstract stop(): Promise<void>;
271288
}
272289

273290
export interface IFileSyncPreviewResult {
@@ -310,7 +327,7 @@ export abstract class AbstractFileSynchroniser extends AbstractSynchroniser {
310327
this.setStatus(SyncStatus.Idle);
311328
}
312329

313-
async getConflictContent(conflictResource: URI): Promise<string | null> {
330+
protected async getConflictContent(conflictResource: URI): Promise<string | null> {
314331
if (isEqual(this.remotePreviewResource, conflictResource) || isEqual(this.localPreviewResource, conflictResource)) {
315332
if (this.syncPreviewResultPromise) {
316333
const result = await this.syncPreviewResultPromise;

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

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6-
import { SyncStatus, IUserDataSyncStoreService, ISyncExtension, IUserDataSyncLogService, IUserDataSynchroniser, SyncResource, IUserDataSyncEnablementService, IUserDataSyncBackupStoreService } from 'vs/platform/userDataSync/common/userDataSync';
6+
import { SyncStatus, IUserDataSyncStoreService, ISyncExtension, IUserDataSyncLogService, IUserDataSynchroniser, SyncResource, IUserDataSyncEnablementService, IUserDataSyncBackupStoreService, ISyncResourceHandle } from 'vs/platform/userDataSync/common/userDataSync';
77
import { Event } from 'vs/base/common/event';
88
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
99
import { IExtensionManagementService, IExtensionGalleryService, IGlobalExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionManagement';
@@ -16,6 +16,9 @@ import { isNonEmptyArray } from 'vs/base/common/arrays';
1616
import { AbstractSynchroniser, IRemoteUserData, ISyncData } from 'vs/platform/userDataSync/common/abstractSynchronizer';
1717
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
1818
import { URI } from 'vs/base/common/uri';
19+
import { joinPath, dirname, basename } from 'vs/base/common/resources';
20+
import { format } from 'vs/base/common/jsonFormatter';
21+
import { applyEdits } from 'vs/base/common/jsonEdit';
1922

2023
interface ISyncPreviewResult {
2124
readonly localExtensions: ISyncExtension[];
@@ -120,28 +123,24 @@ export class ExtensionsSynchroniser extends AbstractSynchroniser implements IUse
120123

121124
async stop(): Promise<void> { }
122125

123-
async getRemoteContent(ref?: string, fragment?: string): Promise<string | null> {
124-
const content = await super.getRemoteContent(ref);
125-
if (content !== null && fragment) {
126-
return this.getFragment(content, fragment);
127-
}
128-
return content;
126+
async getAssociatedResources({ uri }: ISyncResourceHandle): Promise<{ resource: URI, comparableResource?: URI }[]> {
127+
return [{ resource: joinPath(uri, 'extensions.json') }];
129128
}
130129

131-
async getLocalBackupContent(ref?: string, fragment?: string): Promise<string | null> {
132-
let content = await super.getLocalBackupContent(ref);
133-
if (content !== null && fragment) {
134-
return this.getFragment(content, fragment);
130+
async resolveContent(uri: URI): Promise<string | null> {
131+
let content = await super.resolveContent(uri);
132+
if (content) {
133+
return content;
135134
}
136-
return content;
137-
}
138-
139-
private getFragment(content: string, fragment: string): string | null {
140-
const syncData = this.parseSyncData(content);
141-
if (syncData) {
142-
switch (fragment) {
143-
case 'extensions':
144-
return syncData.content;
135+
content = await super.resolveContent(dirname(uri));
136+
if (content) {
137+
const syncData = this.parseSyncData(content);
138+
if (syncData) {
139+
switch (basename(uri)) {
140+
case 'extensions.json':
141+
const edits = format(syncData.content, undefined, {});
142+
return applyEdits(syncData.content, edits);
143+
}
145144
}
146145
}
147146
return null;

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

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6-
import { SyncStatus, IUserDataSyncStoreService, IUserDataSyncLogService, IGlobalState, SyncResource, IUserDataSynchroniser, IUserDataSyncEnablementService, IUserDataSyncBackupStoreService } from 'vs/platform/userDataSync/common/userDataSync';
6+
import { SyncStatus, IUserDataSyncStoreService, IUserDataSyncLogService, IGlobalState, SyncResource, IUserDataSynchroniser, IUserDataSyncEnablementService, IUserDataSyncBackupStoreService, ISyncResourceHandle } from 'vs/platform/userDataSync/common/userDataSync';
77
import { VSBuffer } from 'vs/base/common/buffer';
88
import { Event } from 'vs/base/common/event';
99
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
10-
import { dirname } from 'vs/base/common/resources';
10+
import { dirname, joinPath, basename } from 'vs/base/common/resources';
1111
import { IFileService } from 'vs/platform/files/common/files';
1212
import { IStringDictionary } from 'vs/base/common/collections';
1313
import { edit } from 'vs/platform/userDataSync/common/content';
@@ -17,6 +17,8 @@ import { AbstractSynchroniser, IRemoteUserData } from 'vs/platform/userDataSync/
1717
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
1818
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
1919
import { URI } from 'vs/base/common/uri';
20+
import { format } from 'vs/base/common/jsonFormatter';
21+
import { applyEdits } from 'vs/base/common/jsonEdit';
2022

2123
const argvProperties: string[] = ['locale'];
2224

@@ -105,28 +107,24 @@ export class GlobalStateSynchroniser extends AbstractSynchroniser implements IUs
105107

106108
async stop(): Promise<void> { }
107109

108-
async getRemoteContent(ref?: string, fragment?: string): Promise<string | null> {
109-
let content = await super.getRemoteContent(ref);
110-
if (content !== null && fragment) {
111-
return this.getFragment(content, fragment);
112-
}
113-
return content;
114-
}
115-
116-
async getLocalBackupContent(ref?: string, fragment?: string): Promise<string | null> {
117-
let content = await super.getLocalBackupContent(ref);
118-
if (content !== null && fragment) {
119-
return this.getFragment(content, fragment);
120-
}
121-
return content;
110+
async getAssociatedResources({ uri }: ISyncResourceHandle): Promise<{ resource: URI, comparableResource?: URI }[]> {
111+
return [{ resource: joinPath(uri, 'globalState.json') }];
122112
}
123113

124-
private getFragment(content: string, fragment: string): string | null {
125-
const syncData = this.parseSyncData(content);
126-
if (syncData) {
127-
switch (fragment) {
128-
case 'globalState':
129-
return syncData.content;
114+
async resolveContent(uri: URI): Promise<string | null> {
115+
let content = await super.resolveContent(uri);
116+
if (content) {
117+
return content;
118+
}
119+
content = await super.resolveContent(dirname(uri));
120+
if (content) {
121+
const syncData = this.parseSyncData(content);
122+
if (syncData) {
123+
switch (basename(uri)) {
124+
case 'globalState.json':
125+
const edits = format(syncData.content, undefined, {});
126+
return applyEdits(syncData.content, edits);
127+
}
130128
}
131129
}
132130
return null;

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

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

66
import { IFileService, FileOperationError, FileOperationResult } from 'vs/platform/files/common/files';
7-
import { UserDataSyncError, UserDataSyncErrorCode, SyncStatus, IUserDataSyncStoreService, IUserDataSyncLogService, IUserDataSyncUtilService, SyncResource, IUserDataSynchroniser, IUserDataSyncEnablementService, IUserDataSyncBackupStoreService, USER_DATA_SYNC_SCHEME, PREVIEW_DIR_NAME } from 'vs/platform/userDataSync/common/userDataSync';
7+
import { UserDataSyncError, UserDataSyncErrorCode, SyncStatus, IUserDataSyncStoreService, IUserDataSyncLogService, IUserDataSyncUtilService, SyncResource, IUserDataSynchroniser, IUserDataSyncEnablementService, IUserDataSyncBackupStoreService, USER_DATA_SYNC_SCHEME, PREVIEW_DIR_NAME, ISyncResourceHandle } from 'vs/platform/userDataSync/common/userDataSync';
88
import { merge } from 'vs/platform/userDataSync/common/keybindingsMerge';
99
import { VSBuffer } from 'vs/base/common/buffer';
1010
import { parse } from 'vs/base/common/json';
@@ -19,7 +19,7 @@ import { isNonEmptyArray } from 'vs/base/common/arrays';
1919
import { IFileSyncPreviewResult, AbstractJsonFileSynchroniser, IRemoteUserData } from 'vs/platform/userDataSync/common/abstractSynchronizer';
2020
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
2121
import { URI } from 'vs/base/common/uri';
22-
import { joinPath, isEqual } from 'vs/base/common/resources';
22+
import { joinPath, isEqual, dirname, basename } from 'vs/base/common/resources';
2323

2424
interface ISyncContent {
2525
mac?: string;
@@ -160,38 +160,36 @@ export class KeybindingsSynchroniser extends AbstractJsonFileSynchroniser implem
160160
return false;
161161
}
162162

163-
async getConflictContent(conflictResource: URI): Promise<string | null> {
164-
const content = await super.getConflictContent(conflictResource);
165-
return content !== null ? this.getKeybindingsContentFromSyncContent(content) : null;
163+
async getAssociatedResources({ uri }: ISyncResourceHandle): Promise<{ resource: URI, comparableResource?: URI }[]> {
164+
return [{ resource: joinPath(uri, 'keybindings.json'), comparableResource: this.file }];
166165
}
167166

168-
async getRemoteContent(ref?: string, fragment?: string): Promise<string | null> {
169-
const content = await super.getRemoteContent(ref);
170-
if (content !== null && fragment) {
171-
return this.getFragment(content, fragment);
167+
async resolveContent(uri: URI): Promise<string | null> {
168+
if (isEqual(this.remotePreviewResource, uri)) {
169+
return this.getConflictContent(uri);
172170
}
173-
return content;
174-
}
175-
176-
async getLocalBackupContent(ref?: string, fragment?: string): Promise<string | null> {
177-
let content = await super.getLocalBackupContent(ref);
178-
if (content !== null && fragment) {
179-
return this.getFragment(content, fragment);
171+
let content = await super.resolveContent(uri);
172+
if (content) {
173+
return content;
180174
}
181-
return content;
182-
}
183-
184-
private getFragment(content: string, fragment: string): string | null {
185-
const syncData = this.parseSyncData(content);
186-
if (syncData) {
187-
switch (fragment) {
188-
case 'keybindings':
189-
return this.getKeybindingsContentFromSyncContent(syncData.content);
175+
content = await super.resolveContent(dirname(uri));
176+
if (content) {
177+
const syncData = this.parseSyncData(content);
178+
if (syncData) {
179+
switch (basename(uri)) {
180+
case 'keybindings.json':
181+
return this.getKeybindingsContentFromSyncContent(syncData.content);
182+
}
190183
}
191184
}
192185
return null;
193186
}
194187

188+
protected async getConflictContent(conflictResource: URI): Promise<string | null> {
189+
const content = await super.getConflictContent(conflictResource);
190+
return content !== null ? this.getKeybindingsContentFromSyncContent(content) : null;
191+
}
192+
195193
protected async performSync(remoteUserData: IRemoteUserData, lastSyncUserData: IRemoteUserData | null): Promise<SyncStatus> {
196194
try {
197195
const result = await this.getPreview(remoteUserData, lastSyncUserData);

0 commit comments

Comments
 (0)