mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-09 09:42:34 -05:00
Merge from vscode 073a24de05773f2261f89172987002dc0ae2f1cd (#9711)
This commit is contained in:
@@ -7,9 +7,9 @@ import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { IFileService, IFileContent, FileChangesEvent, FileOperationResult, FileOperationError } from 'vs/platform/files/common/files';
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { SyncResource, SyncStatus, IUserData, IUserDataSyncStoreService, UserDataSyncErrorCode, UserDataSyncError, IUserDataSyncLogService, IUserDataSyncUtilService, IUserDataSyncEnablementService, IUserDataSyncBackupStoreService, Conflict } from 'vs/platform/userDataSync/common/userDataSync';
|
||||
import { SyncResource, SyncStatus, IUserData, IUserDataSyncStoreService, UserDataSyncErrorCode, UserDataSyncError, IUserDataSyncLogService, IUserDataSyncUtilService, IUserDataSyncEnablementService, IUserDataSyncBackupStoreService, Conflict, ISyncResourceHandle, USER_DATA_SYNC_SCHEME } from 'vs/platform/userDataSync/common/userDataSync';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { joinPath, dirname, isEqual } from 'vs/base/common/resources';
|
||||
import { joinPath, dirname, isEqual, basename } from 'vs/base/common/resources';
|
||||
import { CancelablePromise } from 'vs/base/common/async';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
@@ -173,20 +173,36 @@ export abstract class AbstractSynchroniser extends Disposable {
|
||||
return !!lastSyncData;
|
||||
}
|
||||
|
||||
async getConflictContent(conflictResource: URI): Promise<string | null> {
|
||||
async getRemoteSyncResourceHandles(): Promise<ISyncResourceHandle[]> {
|
||||
const handles = await this.userDataSyncStoreService.getAllRefs(this.resource);
|
||||
return handles.map(({ created, ref }) => ({ created, uri: this.toRemoteBackupResource(ref) }));
|
||||
}
|
||||
|
||||
async getLocalSyncResourceHandles(): Promise<ISyncResourceHandle[]> {
|
||||
const handles = await this.userDataSyncBackupStoreService.getAllRefs(this.resource);
|
||||
return handles.map(({ created, ref }) => ({ created, uri: this.toLocalBackupResource(ref) }));
|
||||
}
|
||||
|
||||
private toRemoteBackupResource(ref: string): URI {
|
||||
return URI.from({ scheme: USER_DATA_SYNC_SCHEME, authority: 'remote-backup', path: `/${this.resource}/${ref}` });
|
||||
}
|
||||
|
||||
private toLocalBackupResource(ref: string): URI {
|
||||
return URI.from({ scheme: USER_DATA_SYNC_SCHEME, authority: 'local-backup', path: `/${this.resource}/${ref}` });
|
||||
}
|
||||
|
||||
async resolveContent(uri: URI): Promise<string | null> {
|
||||
const ref = basename(uri);
|
||||
if (isEqual(uri, this.toRemoteBackupResource(ref))) {
|
||||
const { content } = await this.getUserData(ref);
|
||||
return content;
|
||||
}
|
||||
if (isEqual(uri, this.toLocalBackupResource(ref))) {
|
||||
return this.userDataSyncBackupStoreService.resolveContent(this.resource, ref);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
async getRemoteContent(ref?: string): Promise<string | null> {
|
||||
const refOrLastSyncUserData: string | IRemoteUserData | null = ref || await this.getLastSyncUserData();
|
||||
const { content } = await this.getUserData(refOrLastSyncUserData);
|
||||
return content;
|
||||
}
|
||||
|
||||
async getLocalBackupContent(ref?: string): Promise<string | null> {
|
||||
return this.userDataSyncBackupStoreService.resolveContent(this.resource, ref);
|
||||
}
|
||||
|
||||
async resetLocal(): Promise<void> {
|
||||
try {
|
||||
await this.fileService.del(this.lastSyncResource);
|
||||
@@ -265,9 +281,10 @@ export abstract class AbstractSynchroniser extends Disposable {
|
||||
return this.userDataSyncBackupStoreService.backup(this.resource, JSON.stringify(syncData));
|
||||
}
|
||||
|
||||
abstract stop(): Promise<void>;
|
||||
|
||||
protected abstract readonly version: number;
|
||||
protected abstract performSync(remoteUserData: IRemoteUserData, lastSyncUserData: IRemoteUserData | null): Promise<SyncStatus>;
|
||||
abstract stop(): Promise<void>;
|
||||
}
|
||||
|
||||
export interface IFileSyncPreviewResult {
|
||||
@@ -310,7 +327,7 @@ export abstract class AbstractFileSynchroniser extends AbstractSynchroniser {
|
||||
this.setStatus(SyncStatus.Idle);
|
||||
}
|
||||
|
||||
async getConflictContent(conflictResource: URI): Promise<string | null> {
|
||||
protected async getConflictContent(conflictResource: URI): Promise<string | null> {
|
||||
if (isEqual(this.remotePreviewResource, conflictResource) || isEqual(this.localPreviewResource, conflictResource)) {
|
||||
if (this.syncPreviewResultPromise) {
|
||||
const result = await this.syncPreviewResultPromise;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { SyncStatus, IUserDataSyncStoreService, ISyncExtension, IUserDataSyncLogService, IUserDataSynchroniser, SyncResource, IUserDataSyncEnablementService, IUserDataSyncBackupStoreService } from 'vs/platform/userDataSync/common/userDataSync';
|
||||
import { SyncStatus, IUserDataSyncStoreService, ISyncExtension, IUserDataSyncLogService, IUserDataSynchroniser, SyncResource, IUserDataSyncEnablementService, IUserDataSyncBackupStoreService, ISyncResourceHandle } from 'vs/platform/userDataSync/common/userDataSync';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { IExtensionManagementService, IExtensionGalleryService, IGlobalExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
@@ -16,6 +16,9 @@ import { isNonEmptyArray } from 'vs/base/common/arrays';
|
||||
import { AbstractSynchroniser, IRemoteUserData, ISyncData } from 'vs/platform/userDataSync/common/abstractSynchronizer';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { joinPath, dirname, basename } from 'vs/base/common/resources';
|
||||
import { format } from 'vs/base/common/jsonFormatter';
|
||||
import { applyEdits } from 'vs/base/common/jsonEdit';
|
||||
|
||||
interface ISyncPreviewResult {
|
||||
readonly localExtensions: ISyncExtension[];
|
||||
@@ -120,28 +123,24 @@ export class ExtensionsSynchroniser extends AbstractSynchroniser implements IUse
|
||||
|
||||
async stop(): Promise<void> { }
|
||||
|
||||
async getRemoteContent(ref?: string, fragment?: string): Promise<string | null> {
|
||||
const content = await super.getRemoteContent(ref);
|
||||
if (content !== null && fragment) {
|
||||
return this.getFragment(content, fragment);
|
||||
}
|
||||
return content;
|
||||
async getAssociatedResources({ uri }: ISyncResourceHandle): Promise<{ resource: URI, comparableResource?: URI }[]> {
|
||||
return [{ resource: joinPath(uri, 'extensions.json') }];
|
||||
}
|
||||
|
||||
async getLocalBackupContent(ref?: string, fragment?: string): Promise<string | null> {
|
||||
let content = await super.getLocalBackupContent(ref);
|
||||
if (content !== null && fragment) {
|
||||
return this.getFragment(content, fragment);
|
||||
async resolveContent(uri: URI): Promise<string | null> {
|
||||
let content = await super.resolveContent(uri);
|
||||
if (content) {
|
||||
return content;
|
||||
}
|
||||
return content;
|
||||
}
|
||||
|
||||
private getFragment(content: string, fragment: string): string | null {
|
||||
const syncData = this.parseSyncData(content);
|
||||
if (syncData) {
|
||||
switch (fragment) {
|
||||
case 'extensions':
|
||||
return syncData.content;
|
||||
content = await super.resolveContent(dirname(uri));
|
||||
if (content) {
|
||||
const syncData = this.parseSyncData(content);
|
||||
if (syncData) {
|
||||
switch (basename(uri)) {
|
||||
case 'extensions.json':
|
||||
const edits = format(syncData.content, undefined, {});
|
||||
return applyEdits(syncData.content, edits);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { SyncStatus, IUserDataSyncStoreService, IUserDataSyncLogService, IGlobalState, SyncResource, IUserDataSynchroniser, IUserDataSyncEnablementService, IUserDataSyncBackupStoreService } from 'vs/platform/userDataSync/common/userDataSync';
|
||||
import { SyncStatus, IUserDataSyncStoreService, IUserDataSyncLogService, IGlobalState, SyncResource, IUserDataSynchroniser, IUserDataSyncEnablementService, IUserDataSyncBackupStoreService, ISyncResourceHandle } from 'vs/platform/userDataSync/common/userDataSync';
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { dirname } from 'vs/base/common/resources';
|
||||
import { dirname, joinPath, basename } from 'vs/base/common/resources';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { IStringDictionary } from 'vs/base/common/collections';
|
||||
import { edit } from 'vs/platform/userDataSync/common/content';
|
||||
@@ -17,6 +17,8 @@ import { AbstractSynchroniser, IRemoteUserData } from 'vs/platform/userDataSync/
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { format } from 'vs/base/common/jsonFormatter';
|
||||
import { applyEdits } from 'vs/base/common/jsonEdit';
|
||||
|
||||
const argvProperties: string[] = ['locale'];
|
||||
|
||||
@@ -105,28 +107,24 @@ export class GlobalStateSynchroniser extends AbstractSynchroniser implements IUs
|
||||
|
||||
async stop(): Promise<void> { }
|
||||
|
||||
async getRemoteContent(ref?: string, fragment?: string): Promise<string | null> {
|
||||
let content = await super.getRemoteContent(ref);
|
||||
if (content !== null && fragment) {
|
||||
return this.getFragment(content, fragment);
|
||||
}
|
||||
return content;
|
||||
async getAssociatedResources({ uri }: ISyncResourceHandle): Promise<{ resource: URI, comparableResource?: URI }[]> {
|
||||
return [{ resource: joinPath(uri, 'globalState.json') }];
|
||||
}
|
||||
|
||||
async getLocalBackupContent(ref?: string, fragment?: string): Promise<string | null> {
|
||||
let content = await super.getLocalBackupContent(ref);
|
||||
if (content !== null && fragment) {
|
||||
return this.getFragment(content, fragment);
|
||||
async resolveContent(uri: URI): Promise<string | null> {
|
||||
let content = await super.resolveContent(uri);
|
||||
if (content) {
|
||||
return content;
|
||||
}
|
||||
return content;
|
||||
}
|
||||
|
||||
private getFragment(content: string, fragment: string): string | null {
|
||||
const syncData = this.parseSyncData(content);
|
||||
if (syncData) {
|
||||
switch (fragment) {
|
||||
case 'globalState':
|
||||
return syncData.content;
|
||||
content = await super.resolveContent(dirname(uri));
|
||||
if (content) {
|
||||
const syncData = this.parseSyncData(content);
|
||||
if (syncData) {
|
||||
switch (basename(uri)) {
|
||||
case 'globalState.json':
|
||||
const edits = format(syncData.content, undefined, {});
|
||||
return applyEdits(syncData.content, edits);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IFileService, FileOperationError, FileOperationResult } from 'vs/platform/files/common/files';
|
||||
import { UserDataSyncError, UserDataSyncErrorCode, SyncStatus, IUserDataSyncStoreService, IUserDataSyncLogService, IUserDataSyncUtilService, SyncResource, IUserDataSynchroniser, IUserDataSyncEnablementService, IUserDataSyncBackupStoreService, USER_DATA_SYNC_SCHEME, PREVIEW_DIR_NAME } from 'vs/platform/userDataSync/common/userDataSync';
|
||||
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';
|
||||
import { merge } from 'vs/platform/userDataSync/common/keybindingsMerge';
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
import { parse } from 'vs/base/common/json';
|
||||
@@ -19,7 +19,7 @@ import { isNonEmptyArray } from 'vs/base/common/arrays';
|
||||
import { IFileSyncPreviewResult, AbstractJsonFileSynchroniser, IRemoteUserData } from 'vs/platform/userDataSync/common/abstractSynchronizer';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { joinPath, isEqual } from 'vs/base/common/resources';
|
||||
import { joinPath, isEqual, dirname, basename } from 'vs/base/common/resources';
|
||||
|
||||
interface ISyncContent {
|
||||
mac?: string;
|
||||
@@ -160,38 +160,36 @@ export class KeybindingsSynchroniser extends AbstractJsonFileSynchroniser implem
|
||||
return false;
|
||||
}
|
||||
|
||||
async getConflictContent(conflictResource: URI): Promise<string | null> {
|
||||
const content = await super.getConflictContent(conflictResource);
|
||||
return content !== null ? this.getKeybindingsContentFromSyncContent(content) : null;
|
||||
async getAssociatedResources({ uri }: ISyncResourceHandle): Promise<{ resource: URI, comparableResource?: URI }[]> {
|
||||
return [{ resource: joinPath(uri, 'keybindings.json'), comparableResource: this.file }];
|
||||
}
|
||||
|
||||
async getRemoteContent(ref?: string, fragment?: string): Promise<string | null> {
|
||||
const content = await super.getRemoteContent(ref);
|
||||
if (content !== null && fragment) {
|
||||
return this.getFragment(content, fragment);
|
||||
async resolveContent(uri: URI): Promise<string | null> {
|
||||
if (isEqual(this.remotePreviewResource, uri)) {
|
||||
return this.getConflictContent(uri);
|
||||
}
|
||||
return content;
|
||||
}
|
||||
|
||||
async getLocalBackupContent(ref?: string, fragment?: string): Promise<string | null> {
|
||||
let content = await super.getLocalBackupContent(ref);
|
||||
if (content !== null && fragment) {
|
||||
return this.getFragment(content, fragment);
|
||||
let content = await super.resolveContent(uri);
|
||||
if (content) {
|
||||
return content;
|
||||
}
|
||||
return content;
|
||||
}
|
||||
|
||||
private getFragment(content: string, fragment: string): string | null {
|
||||
const syncData = this.parseSyncData(content);
|
||||
if (syncData) {
|
||||
switch (fragment) {
|
||||
case 'keybindings':
|
||||
return this.getKeybindingsContentFromSyncContent(syncData.content);
|
||||
content = await super.resolveContent(dirname(uri));
|
||||
if (content) {
|
||||
const syncData = this.parseSyncData(content);
|
||||
if (syncData) {
|
||||
switch (basename(uri)) {
|
||||
case 'keybindings.json':
|
||||
return this.getKeybindingsContentFromSyncContent(syncData.content);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected async getConflictContent(conflictResource: URI): Promise<string | null> {
|
||||
const content = await super.getConflictContent(conflictResource);
|
||||
return content !== null ? this.getKeybindingsContentFromSyncContent(content) : null;
|
||||
}
|
||||
|
||||
protected async performSync(remoteUserData: IRemoteUserData, lastSyncUserData: IRemoteUserData | null): Promise<SyncStatus> {
|
||||
try {
|
||||
const result = await this.getPreview(remoteUserData, lastSyncUserData);
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IFileService, FileOperationError, FileOperationResult } from 'vs/platform/files/common/files';
|
||||
import { UserDataSyncError, UserDataSyncErrorCode, SyncStatus, IUserDataSyncStoreService, IUserDataSyncLogService, IUserDataSyncUtilService, CONFIGURATION_SYNC_STORE_KEY, SyncResource, IUserDataSyncEnablementService, IUserDataSyncBackupStoreService, USER_DATA_SYNC_SCHEME, PREVIEW_DIR_NAME } from 'vs/platform/userDataSync/common/userDataSync';
|
||||
import { UserDataSyncError, UserDataSyncErrorCode, SyncStatus, IUserDataSyncStoreService, IUserDataSyncLogService, IUserDataSyncUtilService, CONFIGURATION_SYNC_STORE_KEY, SyncResource, IUserDataSyncEnablementService, IUserDataSyncBackupStoreService, USER_DATA_SYNC_SCHEME, PREVIEW_DIR_NAME, ISyncResourceHandle } from 'vs/platform/userDataSync/common/userDataSync';
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
import { parse } from 'vs/base/common/json';
|
||||
import { localize } from 'vs/nls';
|
||||
@@ -20,7 +20,7 @@ import { IFileSyncPreviewResult, AbstractJsonFileSynchroniser, IRemoteUserData }
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { IExtensionManagementService } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
import { joinPath, isEqual } from 'vs/base/common/resources';
|
||||
import { joinPath, isEqual, dirname, basename } from 'vs/base/common/resources';
|
||||
|
||||
export interface ISettingsSyncContent {
|
||||
settings: string;
|
||||
@@ -173,7 +173,35 @@ export class SettingsSynchroniser extends AbstractJsonFileSynchroniser {
|
||||
return false;
|
||||
}
|
||||
|
||||
async getConflictContent(conflictResource: URI): Promise<string | null> {
|
||||
async getAssociatedResources({ uri }: ISyncResourceHandle): Promise<{ resource: URI, comparableResource?: URI }[]> {
|
||||
return [{ resource: joinPath(uri, 'settings.json'), comparableResource: this.file }];
|
||||
}
|
||||
|
||||
async resolveContent(uri: URI): Promise<string | null> {
|
||||
if (isEqual(this.remotePreviewResource, uri)) {
|
||||
return this.getConflictContent(uri);
|
||||
}
|
||||
let content = await super.resolveContent(uri);
|
||||
if (content) {
|
||||
return content;
|
||||
}
|
||||
content = await super.resolveContent(dirname(uri));
|
||||
if (content) {
|
||||
const syncData = this.parseSyncData(content);
|
||||
if (syncData) {
|
||||
const settingsSyncContent = this.parseSettingsSyncContent(syncData.content);
|
||||
if (settingsSyncContent) {
|
||||
switch (basename(uri)) {
|
||||
case 'settings.json':
|
||||
return settingsSyncContent.settings;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected async getConflictContent(conflictResource: URI): Promise<string | null> {
|
||||
let content = await super.getConflictContent(conflictResource);
|
||||
if (content !== null) {
|
||||
const settingsSyncContent = this.parseSettingsSyncContent(content);
|
||||
@@ -188,36 +216,6 @@ export class SettingsSynchroniser extends AbstractJsonFileSynchroniser {
|
||||
return content;
|
||||
}
|
||||
|
||||
async getRemoteContent(ref?: string, fragment?: string): Promise<string | null> {
|
||||
let content = await super.getRemoteContent(ref);
|
||||
if (content !== null && fragment) {
|
||||
return this.getFragment(content, fragment);
|
||||
}
|
||||
return content;
|
||||
}
|
||||
|
||||
async getLocalBackupContent(ref?: string, fragment?: string): Promise<string | null> {
|
||||
let content = await super.getLocalBackupContent(ref);
|
||||
if (content !== null && fragment) {
|
||||
return this.getFragment(content, fragment);
|
||||
}
|
||||
return content;
|
||||
}
|
||||
|
||||
private getFragment(content: string, fragment: string): string | null {
|
||||
const syncData = this.parseSyncData(content);
|
||||
if (syncData) {
|
||||
const settingsSyncContent = this.parseSettingsSyncContent(syncData.content);
|
||||
if (settingsSyncContent) {
|
||||
switch (fragment) {
|
||||
case 'settings':
|
||||
return settingsSyncContent.settings;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
async acceptConflict(conflict: URI, content: string): Promise<void> {
|
||||
if (this.status === SyncStatus.HasConflicts
|
||||
&& (isEqual(this.localPreviewResource, conflict) || isEqual(this.remotePreviewResource, conflict))
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { SyncStatus, IUserDataSyncStoreService, IUserDataSyncLogService, IUserDataSynchroniser, SyncResource, IUserDataSyncEnablementService, IUserDataSyncBackupStoreService, Conflict, USER_DATA_SYNC_SCHEME, PREVIEW_DIR_NAME, UserDataSyncError, UserDataSyncErrorCode } from 'vs/platform/userDataSync/common/userDataSync';
|
||||
import { SyncStatus, IUserDataSyncStoreService, IUserDataSyncLogService, IUserDataSynchroniser, SyncResource, IUserDataSyncEnablementService, IUserDataSyncBackupStoreService, Conflict, USER_DATA_SYNC_SCHEME, PREVIEW_DIR_NAME, UserDataSyncError, UserDataSyncErrorCode, ISyncResourceHandle } from 'vs/platform/userDataSync/common/userDataSync';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { IFileService, FileChangesEvent, IFileStat, IFileContent, FileOperationError, FileOperationResult } from 'vs/platform/files/common/files';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
@@ -11,7 +11,7 @@ import { AbstractSynchroniser, IRemoteUserData, ISyncData } from 'vs/platform/us
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { IStringDictionary } from 'vs/base/common/collections';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { joinPath, extname, relativePath, isEqualOrParent, isEqual, basename } from 'vs/base/common/resources';
|
||||
import { joinPath, extname, relativePath, isEqualOrParent, isEqual, basename, dirname } from 'vs/base/common/resources';
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
import { merge } from 'vs/platform/userDataSync/common/snippetsMerge';
|
||||
import { CancelablePromise, createCancelablePromise } from 'vs/base/common/async';
|
||||
@@ -148,8 +148,46 @@ export class SnippetsSynchroniser extends AbstractSynchroniser implements IUserD
|
||||
this.setStatus(SyncStatus.Idle);
|
||||
}
|
||||
|
||||
async getConflictContent(conflictResource: URI): Promise<string | null> {
|
||||
if (isEqualOrParent(conflictResource.with({ scheme: this.syncFolder.scheme }), this.snippetsPreviewFolder) && this.syncPreviewResultPromise) {
|
||||
async getAssociatedResources({ uri }: ISyncResourceHandle): Promise<{ resource: URI, comparableResource?: URI }[]> {
|
||||
let content = await super.resolveContent(uri);
|
||||
if (content) {
|
||||
const syncData = this.parseSyncData(content);
|
||||
if (syncData) {
|
||||
const snippets = this.parseSnippets(syncData);
|
||||
const result = [];
|
||||
for (const snippet of Object.keys(snippets)) {
|
||||
const resource = joinPath(uri, snippet);
|
||||
const comparableResource = joinPath(this.snippetsFolder, snippet);
|
||||
const exists = await this.fileService.exists(comparableResource);
|
||||
result.push({ resource, comparableResource: exists ? comparableResource : undefined });
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
async resolveContent(uri: URI): Promise<string | null> {
|
||||
if (isEqualOrParent(uri.with({ scheme: this.syncFolder.scheme }), this.snippetsPreviewFolder)) {
|
||||
return this.getConflictContent(uri);
|
||||
}
|
||||
let content = await super.resolveContent(uri);
|
||||
if (content) {
|
||||
return content;
|
||||
}
|
||||
content = await super.resolveContent(dirname(uri));
|
||||
if (content) {
|
||||
const syncData = this.parseSyncData(content);
|
||||
if (syncData) {
|
||||
const snippets = this.parseSnippets(syncData);
|
||||
return snippets[basename(uri)] || null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected async getConflictContent(conflictResource: URI): Promise<string | null> {
|
||||
if (this.syncPreviewResultPromise) {
|
||||
const result = await this.syncPreviewResultPromise;
|
||||
const key = relativePath(this.snippetsPreviewFolder, conflictResource.with({ scheme: this.snippetsPreviewFolder.scheme }))!;
|
||||
if (conflictResource.scheme === this.snippetsPreviewFolder.scheme) {
|
||||
@@ -162,37 +200,6 @@ export class SnippetsSynchroniser extends AbstractSynchroniser implements IUserD
|
||||
return null;
|
||||
}
|
||||
|
||||
async getRemoteContent(ref?: string, fragment?: string): Promise<string | null> {
|
||||
const content = await super.getRemoteContent(ref);
|
||||
if (content !== null && fragment) {
|
||||
return this.getFragment(content, fragment);
|
||||
}
|
||||
return content;
|
||||
}
|
||||
|
||||
async getLocalBackupContent(ref?: string, fragment?: string): Promise<string | null> {
|
||||
let content = await super.getLocalBackupContent(ref);
|
||||
if (content !== null && fragment) {
|
||||
return this.getFragment(content, fragment);
|
||||
}
|
||||
return content;
|
||||
}
|
||||
|
||||
private getFragment(content: string, fragment: string): string | null {
|
||||
const syncData = this.parseSyncData(content);
|
||||
return syncData ? this.getFragmentFromSyncData(syncData, fragment) : null;
|
||||
}
|
||||
|
||||
private getFragmentFromSyncData(syncData: ISyncData, fragment: string): string | null {
|
||||
switch (fragment) {
|
||||
case 'snippets':
|
||||
return syncData.content;
|
||||
default:
|
||||
const remoteSnippets = this.parseSnippets(syncData);
|
||||
return remoteSnippets[fragment] || null;
|
||||
}
|
||||
}
|
||||
|
||||
async acceptConflict(conflictResource: URI, content: string): Promise<void> {
|
||||
const conflict = this.conflicts.filter(({ local, remote }) => isEqual(local, conflictResource) || isEqual(remote, conflictResource))[0];
|
||||
if (this.status === SyncStatus.HasConflicts && conflict) {
|
||||
|
||||
@@ -18,7 +18,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur
|
||||
import { IStringDictionary } from 'vs/base/common/collections';
|
||||
import { FormattingOptions } from 'vs/base/common/jsonFormatter';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { joinPath, dirname, basename, isEqualOrParent } from 'vs/base/common/resources';
|
||||
import { joinPath, isEqualOrParent } from 'vs/base/common/resources';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { IProductService } from 'vs/platform/product/common/productService';
|
||||
import { distinct } from 'vs/base/common/arrays';
|
||||
@@ -243,6 +243,11 @@ export const enum SyncStatus {
|
||||
HasConflicts = 'hasConflicts',
|
||||
}
|
||||
|
||||
export interface ISyncResourceHandle {
|
||||
created: number;
|
||||
uri: URI;
|
||||
}
|
||||
|
||||
export type Conflict = { remote: URI, local: URI };
|
||||
|
||||
export interface IUserDataSynchroniser {
|
||||
@@ -263,11 +268,12 @@ export interface IUserDataSynchroniser {
|
||||
hasLocalData(): Promise<boolean>;
|
||||
resetLocal(): Promise<void>;
|
||||
|
||||
getConflictContent(conflictResource: URI): Promise<string | null>;
|
||||
resolveContent(resource: URI): Promise<string | null>;
|
||||
acceptConflict(conflictResource: URI, content: string): Promise<void>;
|
||||
|
||||
getRemoteContent(ref?: string, fragment?: string): Promise<string | null>;
|
||||
getLocalBackupContent(ref?: string, fragment?: string): Promise<string | null>;
|
||||
getRemoteSyncResourceHandles(): Promise<ISyncResourceHandle[]>;
|
||||
getLocalSyncResourceHandles(): Promise<ISyncResourceHandle[]>;
|
||||
getAssociatedResources(syncResourceHandle: ISyncResourceHandle): Promise<{ resource: URI, comparableResource?: URI }[]>;
|
||||
}
|
||||
|
||||
//#endregion
|
||||
@@ -315,6 +321,10 @@ export interface IUserDataSyncService {
|
||||
isFirstTimeSyncWithMerge(): Promise<boolean>;
|
||||
resolveContent(resource: URI): Promise<string | null>;
|
||||
acceptConflict(conflictResource: URI, content: string): Promise<void>;
|
||||
|
||||
getLocalSyncResourceHandles(resource: SyncResource): Promise<ISyncResourceHandle[]>;
|
||||
getRemoteSyncResourceHandles(resource: SyncResource): Promise<ISyncResourceHandle[]>;
|
||||
getAssociatedResources(resource: SyncResource, syncResourceHandle: ISyncResourceHandle): Promise<{ resource: URI, comparableResource?: URI }[]>;
|
||||
}
|
||||
|
||||
export const IUserDataAutoSyncService = createDecorator<IUserDataAutoSyncService>('IUserDataAutoSyncService');
|
||||
@@ -347,25 +357,6 @@ export const USER_DATA_SYNC_SCHEME = 'vscode-userdata-sync';
|
||||
export const CONTEXT_SYNC_STATE = new RawContextKey<string>('syncStatus', SyncStatus.Uninitialized);
|
||||
export const CONTEXT_SYNC_ENABLEMENT = new RawContextKey<boolean>('syncEnabled', false);
|
||||
|
||||
export function toRemoteBackupSyncResource(resource: SyncResource, ref?: string): URI {
|
||||
return URI.from({ scheme: USER_DATA_SYNC_SCHEME, authority: 'remote-backup', path: `/${resource}/${ref ? ref : 'latest'}` });
|
||||
}
|
||||
export function toLocalBackupSyncResource(resource: SyncResource, ref?: string): URI {
|
||||
return URI.from({ scheme: USER_DATA_SYNC_SCHEME, authority: 'local-backup', path: `/${resource}/${ref ? ref : 'latest'}` });
|
||||
}
|
||||
export function resolveBackupSyncResource(resource: URI): { remote: boolean, resource: SyncResource, path: string } | null {
|
||||
if (resource.scheme === USER_DATA_SYNC_SCHEME
|
||||
&& resource.authority === 'remote-backup' || resource.authority === 'local-backup') {
|
||||
const resourceKey: SyncResource = basename(dirname(resource)) as SyncResource;
|
||||
const path = resource.path.substring(resourceKey.length + 1);
|
||||
if (resourceKey && path) {
|
||||
const remote = resource.authority === 'remote-backup';
|
||||
return { remote, resource: resourceKey, path };
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export const PREVIEW_DIR_NAME = 'preview';
|
||||
export function getSyncResourceFromLocalPreview(localPreview: URI, environmentService: IEnvironmentService): SyncResource | undefined {
|
||||
if (localPreview.scheme === USER_DATA_SYNC_SCHEME) {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import { IServerChannel, IChannel } from 'vs/base/parts/ipc/common/ipc';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { IUserDataSyncService, IUserDataSyncUtilService, IUserDataAutoSyncService, IUserDataSyncStoreService, IUserDataSyncBackupStoreService } from 'vs/platform/userDataSync/common/userDataSync';
|
||||
import { IUserDataSyncService, IUserDataSyncUtilService, IUserDataAutoSyncService } from 'vs/platform/userDataSync/common/userDataSync';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { IStringDictionary } from 'vs/base/common/collections';
|
||||
import { FormattingOptions } from 'vs/base/common/jsonFormatter';
|
||||
@@ -28,14 +28,17 @@ export class UserDataSyncChannel implements IServerChannel {
|
||||
call(context: any, command: string, args?: any): Promise<any> {
|
||||
switch (command) {
|
||||
case '_getInitialData': return Promise.resolve([this.service.status, this.service.conflicts, this.service.lastSyncTime]);
|
||||
case 'sync': return this.service.sync();
|
||||
case 'acceptConflict': return this.service.acceptConflict(URI.revive(args[0]), args[1]);
|
||||
case 'pull': return this.service.pull();
|
||||
case 'sync': return this.service.sync();
|
||||
case 'stop': this.service.stop(); return Promise.resolve();
|
||||
case 'reset': return this.service.reset();
|
||||
case 'resetLocal': return this.service.resetLocal();
|
||||
case 'resolveContent': return this.service.resolveContent(URI.revive(args[0]));
|
||||
case 'isFirstTimeSyncWithMerge': return this.service.isFirstTimeSyncWithMerge();
|
||||
case 'acceptConflict': return this.service.acceptConflict(URI.revive(args[0]), args[1]);
|
||||
case 'resolveContent': return this.service.resolveContent(URI.revive(args[0]));
|
||||
case 'getLocalSyncResourceHandles': return this.service.getLocalSyncResourceHandles(args[0]);
|
||||
case 'getRemoteSyncResourceHandles': return this.service.getRemoteSyncResourceHandles(args[0]);
|
||||
case 'getAssociatedResources': return this.service.getAssociatedResources(args[0], { created: args[1].created, uri: URI.revive(args[1].uri) });
|
||||
}
|
||||
throw new Error('Invalid call');
|
||||
}
|
||||
@@ -98,38 +101,3 @@ export class UserDataSyncUtilServiceClient implements IUserDataSyncUtilService {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export class UserDataSyncStoreServiceChannel implements IServerChannel {
|
||||
|
||||
constructor(private readonly service: IUserDataSyncStoreService) { }
|
||||
|
||||
listen(_: unknown, event: string): Event<any> {
|
||||
throw new Error(`Event not found: ${event}`);
|
||||
}
|
||||
|
||||
call(context: any, command: string, args?: any): Promise<any> {
|
||||
switch (command) {
|
||||
case 'getAllRefs': return this.service.getAllRefs(args[0]);
|
||||
case 'resolveContent': return this.service.resolveContent(args[0], args[1]);
|
||||
case 'delete': return this.service.delete(args[0]);
|
||||
}
|
||||
throw new Error('Invalid call');
|
||||
}
|
||||
}
|
||||
|
||||
export class UserDataSyncBackupStoreServiceChannel implements IServerChannel {
|
||||
|
||||
constructor(private readonly service: IUserDataSyncBackupStoreService) { }
|
||||
|
||||
listen(_: unknown, event: string): Event<any> {
|
||||
throw new Error(`Event not found: ${event}`);
|
||||
}
|
||||
|
||||
call(context: any, command: string, args?: any): Promise<any> {
|
||||
switch (command) {
|
||||
case 'getAllRefs': return this.service.getAllRefs(args[0]);
|
||||
case 'resolveContent': return this.service.resolveContent(args[0], args[1]);
|
||||
}
|
||||
throw new Error('Invalid call');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { IUserDataSyncService, SyncStatus, IUserDataSyncStoreService, SyncResource, IUserDataSyncLogService, IUserDataSynchroniser, UserDataSyncStoreError, UserDataSyncErrorCode, UserDataSyncError, resolveBackupSyncResource, SyncResourceConflicts } from 'vs/platform/userDataSync/common/userDataSync';
|
||||
import { IUserDataSyncService, SyncStatus, IUserDataSyncStoreService, SyncResource, IUserDataSyncLogService, IUserDataSynchroniser, UserDataSyncStoreError, UserDataSyncErrorCode, UserDataSyncError, SyncResourceConflicts, ISyncResourceHandle } from 'vs/platform/userDataSync/common/userDataSync';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
@@ -188,25 +188,27 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ
|
||||
}
|
||||
|
||||
async resolveContent(resource: URI): Promise<string | null> {
|
||||
const result = resolveBackupSyncResource(resource);
|
||||
if (result) {
|
||||
const synchronizer = this.synchronisers.filter(s => s.resource === result.resource)[0];
|
||||
if (synchronizer) {
|
||||
const ref = result.path !== 'latest' ? result.path : undefined;
|
||||
return result.remote ? synchronizer.getRemoteContent(ref, resource.fragment) : synchronizer.getLocalBackupContent(ref, resource.fragment);
|
||||
}
|
||||
}
|
||||
|
||||
for (const synchronizer of this.synchronisers) {
|
||||
const content = await synchronizer.getConflictContent(resource);
|
||||
if (content !== null) {
|
||||
for (const synchroniser of this.synchronisers) {
|
||||
const content = await synchroniser.resolveContent(resource);
|
||||
if (content) {
|
||||
return content;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
getRemoteSyncResourceHandles(resource: SyncResource): Promise<ISyncResourceHandle[]> {
|
||||
return this.getSynchroniser(resource).getRemoteSyncResourceHandles();
|
||||
}
|
||||
|
||||
getLocalSyncResourceHandles(resource: SyncResource): Promise<ISyncResourceHandle[]> {
|
||||
return this.getSynchroniser(resource).getLocalSyncResourceHandles();
|
||||
}
|
||||
|
||||
getAssociatedResources(resource: SyncResource, syncResourceHandle: ISyncResourceHandle): Promise<{ resource: URI, comparableResource?: URI }[]> {
|
||||
return this.getSynchroniser(resource).getAssociatedResources(syncResourceHandle);
|
||||
}
|
||||
|
||||
async isFirstTimeSyncWithMerge(): Promise<boolean> {
|
||||
await this.checkEnablement();
|
||||
if (!await this.userDataSyncStoreService.manifest()) {
|
||||
|
||||
Reference in New Issue
Block a user