Skip to content

Commit 0679691

Browse files
authored
Merge pull request #9 from ozankasikci/merge-cmd
merge cmd
2 parents d57573e + 23df9f8 commit 0679691

File tree

1 file changed

+111
-3
lines changed
  • src/commands/merge_pr_github

1 file changed

+111
-3
lines changed

src/commands/merge_pr_github/mod.rs

Lines changed: 111 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -148,16 +148,29 @@ where
148148
.run("gh", repo_path, &args)
149149
.wrap_err("failed to run `gh pr merge`")?;
150150

151-
if !output.success {
151+
let branch_delete_failed = gh_branch_delete_failure(&output);
152+
153+
if !output.success && !branch_delete_failed {
152154
return Err(command_failure("gh", &args, &output));
153155
}
154156

155-
self.restore_worktree_branch(worktree_path, branch)?;
156-
157157
let pr_label = format_with_color(&format!("#{}", pr_number), |text| {
158158
format!("{}", text.green().bold())
159159
});
160160
let branch_label = format_with_color(branch, |text| format!("{}", text.magenta().bold()));
161+
162+
if branch_delete_failed {
163+
let warning = format!(
164+
"PR {} merged but `gh` could not delete branch `{}`. Leaving the branch intact.",
165+
pr_label, branch_label
166+
);
167+
println!(
168+
"{}",
169+
warning.if_supports_color(Stream::Stdout, |text| format!("{}", text.yellow()))
170+
);
171+
}
172+
173+
self.restore_worktree_branch(worktree_path, branch)?;
161174
println!("Merged PR {} for branch `{}`.", pr_label, branch_label);
162175
Ok(())
163176
}
@@ -181,6 +194,15 @@ where
181194
}
182195
}
183196

197+
fn gh_branch_delete_failure(output: &CommandOutput) -> bool {
198+
if output.success {
199+
return false;
200+
}
201+
202+
let stderr = output.stderr.to_lowercase();
203+
stderr.contains("failed to delete local branch") || stderr.contains("cannot delete branch")
204+
}
205+
184206
fn command_failure(program: &str, args: &[String], output: &CommandOutput) -> color_eyre::Report {
185207
let command_line = format_command(program, args);
186208
let status = match output.status_code {
@@ -392,6 +414,92 @@ mod tests {
392414
Ok(())
393415
}
394416

417+
#[test]
418+
fn treats_branch_delete_failure_as_success() -> color_eyre::Result<()> {
419+
let repo_dir = TempDir::new()?;
420+
init_git_repo(&repo_dir)?;
421+
let repo = Repo::discover_from(repo_dir.path())?;
422+
let repo_root = repo.root().to_path_buf();
423+
let worktree_path = repo.worktrees_dir().join("feature/test");
424+
fs::create_dir_all(&worktree_path)?;
425+
426+
let mut runner = MockCommandRunner::default();
427+
runner.responses.extend([
428+
Ok(CommandOutput {
429+
stdout: "feature/test\n".into(),
430+
stderr: String::new(),
431+
success: true,
432+
status_code: Some(0),
433+
}),
434+
Ok(CommandOutput {
435+
stdout: "[{\"number\":42}]".into(),
436+
stderr: String::new(),
437+
success: true,
438+
status_code: Some(0),
439+
}),
440+
Ok(CommandOutput {
441+
stdout: "Pull request successfully merged".into(),
442+
stderr: "failed to delete local branch merge-cmd".into(),
443+
success: false,
444+
status_code: Some(1),
445+
}),
446+
Ok(CommandOutput {
447+
stdout: String::new(),
448+
stderr: String::new(),
449+
success: true,
450+
status_code: Some(0),
451+
}),
452+
]);
453+
454+
let mut command = MergePrGithubCommand::with_runner("feature/test".into(), runner);
455+
command.execute(&repo)?;
456+
457+
assert_eq!(
458+
command.runner.calls,
459+
vec![
460+
RecordedCall {
461+
program: "git".into(),
462+
dir: worktree_path.clone(),
463+
args: vec!["rev-parse".into(), "--abbrev-ref".into(), "HEAD".into()],
464+
},
465+
RecordedCall {
466+
program: "gh".into(),
467+
dir: repo_root.clone(),
468+
args: vec![
469+
"pr".into(),
470+
"list".into(),
471+
"--head".into(),
472+
"feature/test".into(),
473+
"--state".into(),
474+
"open".into(),
475+
"--json".into(),
476+
"number".into(),
477+
"--limit".into(),
478+
"1".into(),
479+
],
480+
},
481+
RecordedCall {
482+
program: "gh".into(),
483+
dir: repo_root.clone(),
484+
args: vec![
485+
"pr".into(),
486+
"merge".into(),
487+
"42".into(),
488+
"--merge".into(),
489+
"--delete-branch".into(),
490+
],
491+
},
492+
RecordedCall {
493+
program: "git".into(),
494+
dir: worktree_path,
495+
args: vec!["switch".into(), "feature/test".into()],
496+
},
497+
]
498+
);
499+
500+
Ok(())
501+
}
502+
395503
#[test]
396504
fn skips_merge_when_no_pull_request_found() -> color_eyre::Result<()> {
397505
let repo_dir = TempDir::new()?;

0 commit comments

Comments
 (0)