提交 e9e726f6 编写于 作者: S Sandeep Somavarapu

handle conflicts outside synchroniser

上级 2d6ab9cb
......@@ -91,14 +91,13 @@ export const SETTINGS_PREVIEW_RESOURCE = URI.file('Settings-Preview').with({ sch
export interface ISynchroniser {
readonly conflicts: URI | null;
readonly status: SyncStatus;
readonly onDidChangeStatus: Event<SyncStatus>;
readonly onDidChangeLocal: Event<void>;
sync(): Promise<boolean>;
continueSync(): Promise<boolean>;
handleConflicts(): boolean;
}
export const IUserDataSyncService = createDecorator<IUserDataSyncService>('IUserDataSyncService');
......
......@@ -24,6 +24,7 @@ import { ResourceContextKey } from 'vs/workbench/common/resources';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
import { Event } from 'vs/base/common/event';
import { IHistoryService } from 'vs/workbench/services/history/common/history';
const CONTEXT_SYNC_STATE = new RawContextKey<string>('syncStatus', SyncStatus.Uninitialized);
......@@ -93,6 +94,7 @@ class SyncActionsContribution extends Disposable implements IWorkbenchContributi
@IConfigurationService private readonly configurationService: IConfigurationService,
@IEditorService private readonly editorService: IEditorService,
@ITextFileService private readonly textFileService: ITextFileService,
@IHistoryService private readonly historyService: IHistoryService,
) {
super();
this.syncEnablementContext = CONTEXT_SYNC_STATE.bindTo(contextKeyService);
......@@ -126,7 +128,7 @@ class SyncActionsContribution extends Disposable implements IWorkbenchContributi
[
{
label: localize('resolve', "Resolve Conflicts"),
run: () => this.userDataSyncService.handleConflicts()
run: () => this.handleConflicts()
}
]);
this.conflictsWarningDisposable.value = toDisposable(() => handle.close());
......@@ -160,6 +162,22 @@ class SyncActionsContribution extends Disposable implements IWorkbenchContributi
}
}
private async handleConflicts(): Promise<void> {
const resource = this.userDataSyncService.conflicts;
if (resource) {
const resourceInput = {
resource,
options: {
preserveFocus: false,
pinned: false,
revealIfVisible: true,
},
mode: 'jsonc'
};
this.editorService.openEditor(resourceInput).then(() => this.historyService.remove(resourceInput));
}
}
private registerActions(): void {
const startSyncMenuItem: IMenuItem = {
......@@ -194,7 +212,7 @@ class SyncActionsContribution extends Disposable implements IWorkbenchContributi
},
when: CONTEXT_SYNC_STATE.isEqualTo(SyncStatus.HasConflicts),
};
CommandsRegistry.registerCommand(resolveConflictsMenuItem.command.id, serviceAccessor => serviceAccessor.get(IUserDataSyncService).handleConflicts());
CommandsRegistry.registerCommand(resolveConflictsMenuItem.command.id, () => this.handleConflicts());
MenuRegistry.appendMenuItem(MenuId.GlobalActivity, resolveConflictsMenuItem);
MenuRegistry.appendMenuItem(MenuId.CommandPalette, resolveConflictsMenuItem);
......
......@@ -6,16 +6,15 @@
import { Disposable } from 'vs/base/common/lifecycle';
import { IFileService, FileSystemProviderErrorCode, FileSystemProviderError, IFileContent } from 'vs/platform/files/common/files';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { IUserData, UserDataSyncStoreError, UserDataSyncStoreErrorCode, ISynchroniser, SyncStatus, SETTINGS_PREVIEW_RESOURCE, ISettingsMergeService, IUserDataSyncStoreService } from 'vs/platform/userDataSync/common/userDataSync';
import { IUserData, UserDataSyncStoreError, UserDataSyncStoreErrorCode, ISynchroniser, SyncStatus, ISettingsMergeService, IUserDataSyncStoreService, SETTINGS_PREVIEW_RESOURCE } from 'vs/platform/userDataSync/common/userDataSync';
import { VSBuffer } from 'vs/base/common/buffer';
import { parse, ParseError } from 'vs/base/common/json';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { localize } from 'vs/nls';
import { Emitter, Event } from 'vs/base/common/event';
import { ILogService } from 'vs/platform/log/common/log';
import { IHistoryService } from 'vs/workbench/services/history/common/history';
import { CancelablePromise, createCancelablePromise, ThrottledDelayer } from 'vs/base/common/async';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { URI } from 'vs/base/common/uri';
interface ISyncPreviewResult {
readonly fileContent: IFileContent | null;
......@@ -41,15 +40,15 @@ export class SettingsSynchroniser extends Disposable implements ISynchroniser {
private _onDidChangeLocal: Emitter<void> = this._register(new Emitter<void>());
readonly onDidChangeLocal: Event<void> = this._onDidChangeLocal.event;
readonly conflicts: URI = SETTINGS_PREVIEW_RESOURCE;
constructor(
@IFileService private readonly fileService: IFileService,
@IEnvironmentService private readonly environmentService: IEnvironmentService,
@IStorageService private readonly storageService: IStorageService,
@IUserDataSyncStoreService private readonly userDataSyncStoreService: IUserDataSyncStoreService,
@IEditorService private readonly editorService: IEditorService,
@ISettingsMergeService private readonly settingsMergeService: ISettingsMergeService,
@ILogService private readonly logService: ILogService,
@IHistoryService private readonly historyService: IHistoryService,
) {
super();
this.throttledDelayer = this._register(new ThrottledDelayer<void>(500));
......@@ -111,24 +110,6 @@ export class SettingsSynchroniser extends Disposable implements ISynchroniser {
}
}
handleConflicts(): boolean {
if (this.status !== SyncStatus.HasConflicts) {
return false;
}
const resourceInput = {
resource: SETTINGS_PREVIEW_RESOURCE,
label: localize('Settings Conflicts', "Local ↔ Remote (Settings Conflicts)"),
options: {
preserveFocus: false,
pinned: false,
revealIfVisible: true,
},
mode: 'jsonc'
};
this.editorService.openEditor(resourceInput).then(() => this.historyService.remove(resourceInput));
return true;
}
async continueSync(): Promise<boolean> {
if (this.status !== SyncStatus.HasConflicts) {
return false;
......@@ -142,8 +123,8 @@ export class SettingsSynchroniser extends Disposable implements ISynchroniser {
return;
}
if (await this.fileService.exists(SETTINGS_PREVIEW_RESOURCE)) {
const settingsPreivew = await this.fileService.readFile(SETTINGS_PREVIEW_RESOURCE);
if (await this.fileService.exists(this.conflicts)) {
const settingsPreivew = await this.fileService.readFile(this.conflicts);
const content = settingsPreivew.value.toString();
if (this.hasErrors(content)) {
return Promise.reject(localize('errorInvalidSettings', "Unable to sync settings. Please resolve conflicts without any errors/warnings and try again."));
......@@ -162,7 +143,7 @@ export class SettingsSynchroniser extends Disposable implements ISynchroniser {
}
// Delete the preview
await this.fileService.del(SETTINGS_PREVIEW_RESOURCE);
await this.fileService.del(this.conflicts);
}
this.syncPreviewResultPromise = null;
......@@ -194,7 +175,7 @@ export class SettingsSynchroniser extends Disposable implements ISynchroniser {
if (fileContent && !remoteUserData) {
this.logService.trace('Settings Sync: Remote contents does not exist. So sync with settings file.');
hasRemoteChanged = true;
await this.fileService.writeFile(SETTINGS_PREVIEW_RESOURCE, VSBuffer.fromString(fileContent.value.toString()));
await this.fileService.writeFile(this.conflicts, VSBuffer.fromString(fileContent.value.toString()));
return { fileContent, remoteUserData, hasLocalChanged, hasRemoteChanged, hasConflicts };
}
......@@ -202,7 +183,7 @@ export class SettingsSynchroniser extends Disposable implements ISynchroniser {
if (remoteUserData && !fileContent) {
this.logService.trace('Settings Sync: Settings file does not exist. So sync with remote contents');
hasLocalChanged = true;
await this.fileService.writeFile(SETTINGS_PREVIEW_RESOURCE, VSBuffer.fromString(remoteUserData.content));
await this.fileService.writeFile(this.conflicts, VSBuffer.fromString(remoteUserData.content));
return { fileContent, remoteUserData, hasLocalChanged, hasRemoteChanged, hasConflicts };
}
......@@ -221,7 +202,7 @@ export class SettingsSynchroniser extends Disposable implements ISynchroniser {
if (hasLocalChanged || hasRemoteChanged) {
// Sync only if there are changes
hasConflicts = this.hasErrors(mergeContent);
await this.fileService.writeFile(SETTINGS_PREVIEW_RESOURCE, VSBuffer.fromString(mergeContent));
await this.fileService.writeFile(this.conflicts, VSBuffer.fromString(mergeContent));
return { fileContent, remoteUserData, hasLocalChanged, hasRemoteChanged, hasConflicts };
}
}
......
......@@ -11,6 +11,7 @@ import { SettingsSynchroniser } from 'vs/workbench/services/userData/common/sett
import { Emitter, Event } from 'vs/base/common/event';
import { IFileService } from 'vs/platform/files/common/files';
import { InMemoryFileSystemProvider } from 'vs/workbench/services/userData/common/inMemoryUserDataProvider';
import { URI } from 'vs/base/common/uri';
export class UserDataSyncService extends Disposable implements IUserDataSyncService {
......@@ -40,6 +41,11 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ
this.onDidChangeLocal = Event.any(...this.synchronisers.map(s => s.onDidChangeLocal));
}
get conflicts(): URI | null {
const synchroniser = this.synchronisers.filter(s => s.status === SyncStatus.HasConflicts)[0];
return synchroniser ? synchroniser.conflicts : null;
}
async sync(): Promise<boolean> {
if (!this.userDataSyncStoreService.enabled) {
throw new Error('Not enabled');
......@@ -64,18 +70,6 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ
return false;
}
handleConflicts(): boolean {
if (!this.userDataSyncStoreService.enabled) {
throw new Error('Not enabled');
}
for (const synchroniser of this.synchronisers) {
if (synchroniser.handleConflicts()) {
return true;
}
}
return false;
}
private updateStatus(): void {
this.setStatus(this.computeStatus());
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册