diff --git a/extensions/git/package.json b/extensions/git/package.json index ecca4d76e17..34789ea5213 100644 --- a/extensions/git/package.json +++ b/extensions/git/package.json @@ -609,6 +609,18 @@ "command": "git.openMergeEditor", "title": "%command.git.openMergeEditor%", "category": "Git" + }, + { + "command": "git.runGitMerge", + "title": "%command.git.runGitMerge%", + "category": "Git", + "enablement": "isMergeEditor" + }, + { + "command": "git.runGitMergeDiff3", + "title": "%command.git.runGitMergeDiff3%", + "category": "Git", + "enablement": "isMergeEditor" } ], "keybindings": [ @@ -1568,6 +1580,16 @@ "when": "config.git.enabled && !git.missing && !isInDiffEditor && !isMergeEditor && resource in git.mergeChanges" } ], + "mergeEditor/result/context": [ + { + "command": "git.runGitMerge", + "when": "isMergeEditor" + }, + { + "command": "git.runGitMergeDiff3", + "when": "isMergeEditor" + } + ], "scm/change/title": [ { "command": "git.stageChange", diff --git a/extensions/git/package.nls.json b/extensions/git/package.nls.json index eaf627c3731..1aba43cb86a 100644 --- a/extensions/git/package.nls.json +++ b/extensions/git/package.nls.json @@ -104,6 +104,8 @@ "command.api.getRemoteSources": "Get Remote Sources", "command.git.acceptMerge": "Accept Merge", "command.git.openMergeEditor": "Open in Merge Editor", + "command.git.runGitMerge": "Compute Conflicts With Git", + "command.git.runGitMergeDiff3": "Compute Conflicts With Git (Diff3)", "config.enabled": "Whether git is enabled.", "config.path": "Path and filename of the git executable, e.g. `C:\\Program Files\\Git\\bin\\git.exe` (Windows). This can also be an array of string values containing multiple paths to look up.", "config.autoRepositoryDetection": "Configures when repositories should be automatically detected.", diff --git a/extensions/git/src/commands.ts b/extensions/git/src/commands.ts index 00827778a0e..65a9ba9ec98 100644 --- a/extensions/git/src/commands.ts +++ b/extensions/git/src/commands.ts @@ -1134,6 +1134,48 @@ export class CommandCenter { } } + @command('git.runGitMerge') + async runGitMergeNoDiff3(): Promise { + await this.runGitMerge(false); + } + + @command('git.runGitMergeDiff3') + async runGitMergeDiff3(): Promise { + await this.runGitMerge(true); + } + + private async runGitMerge(diff3: boolean): Promise { + const { activeTab } = window.tabGroups.activeTabGroup; + if (!activeTab) { + return; + } + + const input = activeTab.input as { base: Uri; input1: Uri; input2: Uri; result: Uri }; + + const result = await this.git.mergeFile({ + basePath: input.base.fsPath, + input1Path: input.input1.fsPath, + input2Path: input.input2.fsPath, + diff3, + }); + + const doc = workspace.textDocuments.find(doc => doc.uri.toString() === input.result.toString()); + if (!doc) { + return; + } + const e = new WorkspaceEdit(); + + e.replace( + input.result, + new Range( + new Position(0, 0), + new Position(doc.lineCount, 0), + ), + result + ); + await workspace.applyEdit(e); + } + private async _stageChanges(textEditor: TextEditor, changes: LineChange[]): Promise { const modifiedDocument = textEditor.document; const modifiedUri = modifiedDocument.uri; diff --git a/extensions/git/src/git.ts b/extensions/git/src/git.ts index 392ec661728..55c55bcdf7b 100644 --- a/extensions/git/src/git.ts +++ b/extensions/git/src/git.ts @@ -656,6 +656,27 @@ export class Git { private log(output: string): void { this._onOutput.emit('log', output); } + + async mergeFile(options: { input1Path: string; input2Path: string; basePath: string; diff3?: boolean }): Promise { + const args = ['merge-file', '-p', options.input1Path, options.basePath, options.input2Path]; + if (options.diff3) { + args.push('--diff3'); + } else { + args.push('--no-diff3'); + } + + try { + const result = await this.exec('', args); + return result.stdout; + } catch (err) { + if (typeof err.stdout === 'string') { + // The merge had conflicts, stdout still contains the merged result (with conflict markers) + return err.stdout; + } else { + throw err; + } + } + } } export interface Commit { diff --git a/src/vs/workbench/services/actions/common/menusExtensionPoint.ts b/src/vs/workbench/services/actions/common/menusExtensionPoint.ts index 40eea48969a..0cb561ff822 100644 --- a/src/vs/workbench/services/actions/common/menusExtensionPoint.ts +++ b/src/vs/workbench/services/actions/common/menusExtensionPoint.ts @@ -291,7 +291,11 @@ const apiMenus: IAPIMenu[] = [ description: localize('webview.context', "The webview context menu"), proposed: 'contribWebviewContext' }, - + { + key: 'mergeEditor/result/context', + id: MenuId.MergeInputResultToolbar, + description: localize('menus.mergeEditorResult', "The result toolbar of the merge editor"), + }, ]; namespace schema {