From 87060b36021361c1d99c29a91b8a22b5b1f34d09 Mon Sep 17 00:00:00 2001 From: MrLalelu Date: Mon, 8 Nov 2021 13:20:01 +0100 Subject: [PATCH] feat: Added Merge command (#1540) --- package.json | 13 ++++++++ src/commands.ts | 2 ++ src/commands/merge.ts | 54 ++++++++++++++++++++++++++++++++++ src/common/types.ts | 1 + src/helpers/branch.ts | 13 ++++++++ src/repository.ts | 11 +++++++ src/statusbar/syncStatusBar.ts | 3 +- src/svnRepository.ts | 18 ++++++++++++ 8 files changed, 114 insertions(+), 1 deletion(-) create mode 100644 src/commands/merge.ts diff --git a/package.json b/package.json index 1d0233f06..cbdb26037 100644 --- a/package.json +++ b/package.json @@ -456,6 +456,11 @@ "title": "Switch Branch", "category": "SVN" }, + { + "command": "svn.merge", + "title": "Merge", + "category": "SVN" + }, { "command": "svn.treeview.pullIncomingChange", "title": "Update selected", @@ -686,6 +691,10 @@ "command": "svn.switchBranch", "when": "config.svn.enabled && svnOpenRepositoryCount != 0" }, + { + "command": "svn.merge", + "when": "config.svn.enabled && svnOpenRepositoryCount != 0" + }, { "command": "svn.treeview.pullIncomingChange", "when": "false" @@ -814,6 +823,10 @@ "command": "svn.switchBranch", "when": "config.svn.enabled && scmProvider == svn" }, + { + "command": "svn.merge", + "when": "config.svn.enabled && scmProvider == svn" + }, { "command": "svn.update", "when": "config.svn.enabled && scmProvider == svn" diff --git a/src/commands.ts b/src/commands.ts index 9c1e9d470..63701f36b 100644 --- a/src/commands.ts +++ b/src/commands.ts @@ -45,6 +45,7 @@ import { Upgrade } from "./commands/upgrade"; import { SourceControlManager } from "./source_control_manager"; import { SearchLogByRevision } from "./commands/search_log_by_revision"; import { SearchLogByText } from "./commands/search_log_by_text"; +import { Merge } from "./commands/merge"; export function registerCommands( sourceControlManager: SourceControlManager, @@ -63,6 +64,7 @@ export function registerCommands( disposables.push(new OpenResourceHead()); disposables.push(new OpenChangeBase()); disposables.push(new SwitchBranch()); + disposables.push(new Merge()); disposables.push(new Revert()); disposables.push(new Update()); disposables.push(new PullIncommingChange()); diff --git a/src/commands/merge.ts b/src/commands/merge.ts new file mode 100644 index 000000000..fb6b9cbf9 --- /dev/null +++ b/src/commands/merge.ts @@ -0,0 +1,54 @@ +import { commands, window } from "vscode"; +import { IBranchItem } from "../common/types"; +import { isTrunk, selectBranch } from "../helpers/branch"; +import { Repository } from "../repository"; +import { Command } from "./command"; + +export class Merge extends Command { + constructor() { + super("svn.merge", { repository: true }); + } + + public async execute(repository: Repository) { + const branch = await selectBranch(repository); + + if (!branch) { + return; + } + + await this.merge(repository, branch); + } + + async merge(repository: Repository, branch: IBranchItem) { + let reintegrate = false; + if (isTrunk(repository.currentBranch)) { + reintegrate = true; + } + + try { + await repository.merge(branch.path, reintegrate); + } catch (error) { + if (typeof error === "object" && error.hasOwnProperty("stderrFormated")) { + if (error.stderrFormated.includes("try updating first")) { + const answer = await window.showErrorMessage( + "Seems like you need to update first prior to merging. " + + "Would you like to update now and try merging again?", + "Yes", + "No" + ); + if (answer === "Yes") { + await commands.executeCommand("svn.update"); + await this.merge(repository, branch); + } + } else { + window.showErrorMessage( + "Unable to merge branch: " + error.stderrFormated + ); + } + } else { + console.log(error); + window.showErrorMessage("Unable to merge branch"); + } + } + } +} diff --git a/src/common/types.ts b/src/common/types.ts index 69f6cf8fb..eeeeca634 100644 --- a/src/common/types.ts +++ b/src/common/types.ts @@ -110,6 +110,7 @@ export enum Operation { Info = "Info", Ignore = "Ignore", Log = "Log", + Merge = "Merge", NewBranch = "NewBranch", Patch = "Patch", Remove = "Remove", diff --git a/src/helpers/branch.ts b/src/helpers/branch.ts index 2089d0b0e..314ed7c7e 100644 --- a/src/helpers/branch.ts +++ b/src/helpers/branch.ts @@ -107,3 +107,16 @@ export async function selectBranch( return; } + +export function isTrunk(folder: string): boolean { + const conf = "layout.trunkRegex"; + const layout = configuration.get(conf); + const regex = new RegExp(`(^|/)(${layout})$`); + const matches = folder.match(regex); + const group = configuration.get(`${conf}Name`, 1) + 2; + + if (matches && matches[2] && matches[group]) { + return true; + } + return false; +} diff --git a/src/repository.ts b/src/repository.ts index f2d592107..39c4ef212 100644 --- a/src/repository.ts +++ b/src/repository.ts @@ -817,6 +817,17 @@ export class Repository implements IRemoteRepository { }); } + public async merge( + name: string, + reintegrate: boolean = false, + accept_action: string = "postpone" + ) { + await this.run(Operation.Merge, async () => { + await this.repository.merge(name, reintegrate, accept_action); + this.updateRemoteChangedFiles(); + }); + } + public async updateRevision( ignoreExternals: boolean = false ): Promise { diff --git a/src/statusbar/syncStatusBar.ts b/src/statusbar/syncStatusBar.ts index 4c43d5ac6..22ca3eff7 100644 --- a/src/statusbar/syncStatusBar.ts +++ b/src/statusbar/syncStatusBar.ts @@ -50,7 +50,8 @@ export class SyncStatusBar { const isSyncRunning = this.repository.operations.isRunning(Operation.SwitchBranch) || this.repository.operations.isRunning(Operation.NewBranch) || - this.repository.operations.isRunning(Operation.Update); + this.repository.operations.isRunning(Operation.Update) || + this.repository.operations.isRunning(Operation.Merge); const isStatusRemoteRunning = this.repository.operations.isRunning( Operation.StatusRemote diff --git a/src/svnRepository.ts b/src/svnRepository.ts index dd2048d06..a7fd8cf8d 100644 --- a/src/svnRepository.ts +++ b/src/svnRepository.ts @@ -662,6 +662,24 @@ export class Repository { return true; } + public async merge( + ref: string, + reintegrate: boolean = false, + accept_action: string = "postpone" + ) { + const repoUrl = await this.getRepoUrl(); + const branchUrl = repoUrl + "/" + ref; + + let args = ["merge", "--accept", accept_action]; + args = args.concat(reintegrate ? ["--reintegrate"] : []); + args = args.concat([branchUrl]); + + await this.exec(args); + + this.resetInfoCache(); + return true; + } + public async revert(files: string[], depth: keyof typeof SvnDepth) { files = files.map(file => this.removeAbsolutePath(file)); const result = await this.exec(["revert", "--depth", depth, ...files]);