Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

merge editor temp model #161315

Merged
merged 1 commit into from Sep 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
27 changes: 22 additions & 5 deletions extensions/git/src/commands.ts
Expand Up @@ -1148,21 +1148,38 @@ export class CommandCenter {
}

@command('git.acceptMerge')
async acceptMerge(uri: Uri | unknown): Promise<void> {
if (!(uri instanceof Uri)) {
async acceptMerge(_uri: Uri | unknown): Promise<void> {
const { activeTab } = window.tabGroups.activeTabGroup;
if (!activeTab) {
return;
}

if (!(activeTab.input instanceof TabInputTextMerge)) {
return;
}

const uri = activeTab.input.result;

const repository = this.model.getRepository(uri);
if (!repository) {
console.log(`FAILED to accept merge because uri ${uri.toString()} doesn't belong to any repository`);
return;
}

const { activeTab } = window.tabGroups.activeTabGroup;
if (!activeTab) {
const result = await commands.executeCommand('mergeEditor.acceptMerge') as { successful: boolean };
if (result.successful) {
await repository.add([uri]);
await commands.executeCommand('workbench.view.scm');
}

/*
if (!(uri instanceof Uri)) {
return;
}




// make sure to save the merged document
const doc = workspace.textDocuments.find(doc => doc.uri.toString() === uri.toString());
if (!doc) {
Expand All @@ -1185,7 +1202,7 @@ export class CommandCenter {
if (didCloseTab) {
await repository.add([uri]);
await commands.executeCommand('workbench.view.scm');
}
}*/
}

@command('git.runGitMerge')
Expand Down
12 changes: 11 additions & 1 deletion src/vs/base/common/observableImpl/utils.ts
Expand Up @@ -51,13 +51,23 @@ export function waitForState<T, TState extends T>(observable: IObservable<T>, pr
export function waitForState<T>(observable: IObservable<T>, predicate: (state: T) => boolean): Promise<T>;
export function waitForState<T>(observable: IObservable<T>, predicate: (state: T) => boolean): Promise<T> {
return new Promise(resolve => {
let didRun = false;
let shouldDispose = false;
const d = autorun('waitForState', reader => {
const currentState = observable.read(reader);
if (predicate(currentState)) {
d.dispose();
if (!didRun) {
shouldDispose = true;
} else {
d.dispose();
}
resolve(currentState);
}
});
didRun = true;
if (shouldDispose) {
d.dispose();
}
});
}

Expand Down
16 changes: 15 additions & 1 deletion src/vs/editor/common/diff/standardLinesDiffComputer.ts
Expand Up @@ -3,6 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { assertFn, checkAdjacentItems } from 'vs/base/common/assert';
import { Position } from 'vs/editor/common/core/position';
import { Range } from 'vs/editor/common/core/range';
import { SequenceFromIntArray, OffsetRange, SequenceDiff, ISequence } from 'vs/editor/common/diff/algorithms/diffAlgorithm';
Expand Down Expand Up @@ -91,7 +92,9 @@ export function lineRangeMappingFromRangeMappings(alignments: RangeMapping[]): L
const changes: LineRangeMapping[] = [];
for (const g of group(
alignments,
(a1, a2) => a2.modifiedRange.startLineNumber - (a1.modifiedRange.endLineNumber - (a1.modifiedRange.endColumn > 1 ? 0 : 1)) <= 1
(a1, a2) =>
(a2.originalRange.startLineNumber - (a1.originalRange.endLineNumber - (a1.originalRange.endColumn > 1 ? 0 : 1)) <= 1)
|| (a2.modifiedRange.startLineNumber - (a1.modifiedRange.endLineNumber - (a1.modifiedRange.endColumn > 1 ? 0 : 1)) <= 1)
)) {
const first = g[0];
const last = g[g.length - 1];
Expand All @@ -108,6 +111,17 @@ export function lineRangeMappingFromRangeMappings(alignments: RangeMapping[]): L
g
));
}

assertFn(() => {
return checkAdjacentItems(changes,
(m1, m2) => m2.originalRange.startLineNumber - m1.originalRange.endLineNumberExclusive === m2.modifiedRange.startLineNumber - m1.modifiedRange.endLineNumberExclusive &&
// There has to be an unchanged line in between (otherwise both diffs should have been joined)
m1.originalRange.endLineNumberExclusive < m2.originalRange.startLineNumber &&
m1.modifiedRange.endLineNumberExclusive < m2.modifiedRange.startLineNumber,
);
});


return changes;
}

Expand Down
87 changes: 85 additions & 2 deletions src/vs/workbench/contrib/mergeEditor/browser/commands/commands.ts
Expand Up @@ -8,11 +8,13 @@ import { URI, UriComponents } from 'vs/base/common/uri';
import { localize } from 'vs/nls';
import { ILocalizedString } from 'vs/platform/action/common/action';
import { Action2, IAction2Options, MenuId } from 'vs/platform/actions/common/actions';
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
import { ITextEditorOptions } from 'vs/platform/editor/common/editor';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { IOpenerService } from 'vs/platform/opener/common/opener';
import { IResourceMergeEditorInput } from 'vs/workbench/common/editor';
import { MergeEditorInputData } from 'vs/workbench/contrib/mergeEditor/browser/mergeEditorInput';
import { IEditorIdentifier, IResourceMergeEditorInput } from 'vs/workbench/common/editor';
import { MergeEditorInput, MergeEditorInputData } from 'vs/workbench/contrib/mergeEditor/browser/mergeEditorInput';
import { IMergeEditorInputModel } from 'vs/workbench/contrib/mergeEditor/browser/mergeEditorInputModel';
import { MergeEditor } from 'vs/workbench/contrib/mergeEditor/browser/view/mergeEditor';
import { MergeEditorViewModel } from 'vs/workbench/contrib/mergeEditor/browser/view/viewModel';
import { ctxIsMergeEditor, ctxMergeEditorLayout, ctxMergeEditorShowBase } from 'vs/workbench/contrib/mergeEditor/common/mergeEditor';
Expand All @@ -37,6 +39,41 @@ abstract class MergeEditorAction extends Action2 {
abstract runWithViewModel(viewModel: MergeEditorViewModel, accessor: ServicesAccessor): void;
}

interface MergeEditorAction2Args {
inputModel: IMergeEditorInputModel;
viewModel: MergeEditorViewModel;
input: MergeEditorInput;
editorIdentifier: IEditorIdentifier;
}

abstract class MergeEditorAction2 extends Action2 {
constructor(desc: Readonly<IAction2Options>) {
super(desc);
}

run(accessor: ServicesAccessor): void {
const { activeEditorPane } = accessor.get(IEditorService);
if (activeEditorPane instanceof MergeEditor) {
const vm = activeEditorPane.viewModel.get();
if (!vm) {
return;
}

return this.runWithMergeEditor({
viewModel: vm,
inputModel: activeEditorPane.inputModel.get()!,
input: activeEditorPane.input as MergeEditorInput,
editorIdentifier: {
editor: activeEditorPane.input,
groupId: activeEditorPane.group.id,
}
}, accessor) as any;
}
}

abstract runWithMergeEditor(args: MergeEditorAction2Args, accessor: ServicesAccessor): unknown;
}

export class OpenMergeEditor extends Action2 {
constructor() {
super({
Expand Down Expand Up @@ -531,3 +568,49 @@ export class ResetDirtyConflictsToBaseCommand extends MergeEditorAction {
viewModel.model.resetDirtyConflictsToBase();
}
}

// this is an API command
export class AcceptMerge extends MergeEditorAction2 {
constructor() {
super({
id: 'mergeEditor.acceptMerge',
category: mergeEditorCategory,
title: {
value: localize(
'mergeEditor.acceptMerge',
'Accept Merge'
),
original: 'Accept Merge',
},
f1: false,
precondition: ctxIsMergeEditor
});
}

override async runWithMergeEditor({ inputModel, editorIdentifier, viewModel }: MergeEditorAction2Args, accessor: ServicesAccessor) {
const dialogService = accessor.get(IDialogService);
const editorService = accessor.get(IEditorService);

if (viewModel.model.unhandledConflictsCount.get() > 0) {
const confirmResult = await dialogService.confirm({
type: 'info',
message: localize('mergeEditor.acceptMerge.unhandledConflicts', "There are still unhandled conflicts. Are you sure you want to accept the merge?"),
primaryButton: localize('mergeEditor.acceptMerge.unhandledConflicts.accept', "Accept merge with unhandled conflicts"),
secondaryButton: localize('mergeEditor.acceptMerge.unhandledConflicts.cancel', "Cancel"),
});

if (!confirmResult.confirmed) {
return {
successful: false
};
}
}

await inputModel.accept();
await editorService.closeEditor(editorIdentifier);

return {
successful: true
};
}
}
Expand Up @@ -11,10 +11,10 @@ import { Registry } from 'vs/platform/registry/common/platform';
import { EditorPaneDescriptor, IEditorPaneRegistry } from 'vs/workbench/browser/editor';
import { Extensions as WorkbenchExtensions, IWorkbenchContributionsRegistry } from 'vs/workbench/common/contributions';
import { EditorExtensions, IEditorFactoryRegistry } from 'vs/workbench/common/editor';
import { AcceptAllInput1, AcceptAllInput2, CompareInput1WithBaseCommand, CompareInput2WithBaseCommand, GoToNextUnhandledConflict, GoToPreviousUnhandledConflict, OpenBaseFile, OpenMergeEditor, OpenResultResource, ResetDirtyConflictsToBaseCommand, ResetToBaseAndAutoMergeCommand, SetColumnLayout, SetMixedLayout, ShowHideBase, ToggleActiveConflictInput1, ToggleActiveConflictInput2 } from 'vs/workbench/contrib/mergeEditor/browser/commands/commands';
import { MergeEditorCopyContentsToJSON, MergeEditorSaveContentsToFolder, MergeEditorLoadContentsFromFolder } from 'vs/workbench/contrib/mergeEditor/browser/commands/devCommands';
import { AcceptAllInput1, AcceptAllInput2, AcceptMerge, CompareInput1WithBaseCommand, CompareInput2WithBaseCommand, GoToNextUnhandledConflict, GoToPreviousUnhandledConflict, OpenBaseFile, OpenMergeEditor, OpenResultResource, ResetDirtyConflictsToBaseCommand, ResetToBaseAndAutoMergeCommand, SetColumnLayout, SetMixedLayout, ShowHideBase, ToggleActiveConflictInput1, ToggleActiveConflictInput2 } from 'vs/workbench/contrib/mergeEditor/browser/commands/commands';
import { MergeEditorCopyContentsToJSON, MergeEditorLoadContentsFromFolder, MergeEditorSaveContentsToFolder } from 'vs/workbench/contrib/mergeEditor/browser/commands/devCommands';
import { MergeEditorInput } from 'vs/workbench/contrib/mergeEditor/browser/mergeEditorInput';
import { MergeEditor, MergeEditorResolverContribution, MergeEditorOpenHandlerContribution } from 'vs/workbench/contrib/mergeEditor/browser/view/mergeEditor';
import { MergeEditor, MergeEditorOpenHandlerContribution, MergeEditorResolverContribution } from 'vs/workbench/contrib/mergeEditor/browser/view/mergeEditor';
import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle';
import { MergeEditorSerializer } from './mergeEditorSerializer';

Expand Down Expand Up @@ -70,6 +70,8 @@ registerAction2(AcceptAllInput2);
registerAction2(ResetToBaseAndAutoMergeCommand);
registerAction2(ResetDirtyConflictsToBaseCommand);

registerAction2(AcceptMerge);

// Dev Commands
registerAction2(MergeEditorCopyContentsToJSON);
registerAction2(MergeEditorSaveContentsToFolder);
Expand All @@ -82,3 +84,23 @@ Registry
Registry
.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench)
.registerWorkbenchContribution(MergeEditorResolverContribution, 'MergeEditorResolverContribution', LifecyclePhase.Starting);
/*
class MergeEditorWorkbenchContribution extends Disposable implements IWorkbenchContribution {
constructor(@IWorkingCopyEditorService private readonly _workingCopyEditorService: IWorkingCopyEditorService) {
super();

this._register(
_workingCopyEditorService.registerHandler({
createEditor(workingCopy) {
throw new BugIndicatingError('not supported');
},
handles(workingCopy) {
return workingCopy.typeId === '';
},
isOpen(workingCopy, editor) {
return workingCopy.resource.toString() === that._model?.resultTextModel.uri.toString();
},
}));
}
}
*/