diff options
| author | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-06-22 00:51:00 +0300 |
|---|---|---|
| committer | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-06-22 00:51:00 +0300 |
| commit | 89ca3ba933eaf493234912972be8236c9c2493e5 (patch) | |
| tree | 508a0489cf3aa15f6d454a1c86697b0a7ba4ed72 /src/worktree.rs | |
| parent | a5182282a490cfb60b22776257edc5ac0fce6adc (diff) | |
fix: check out existing branches for worktree create
refs #729
Diffstat (limited to 'src/worktree.rs')
| -rw-r--r-- | src/worktree.rs | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/src/worktree.rs b/src/worktree.rs index f2f1dffe..33b03d56 100644 --- a/src/worktree.rs +++ b/src/worktree.rs @@ -246,6 +246,65 @@ pub(crate) fn build_worktree_add_new_branch_command( } } +pub(crate) fn build_worktree_add_existing_branch_command( + repo_root: &Path, + path: &Path, + branch: &str, +) -> WorktreeCommand { + WorktreeCommand { + program: "git".to_string(), + args: vec![ + "-C".to_string(), + repo_root.display().to_string(), + "worktree".to_string(), + "add".to_string(), + path.display().to_string(), + branch.to_string(), + ], + } +} + +pub(crate) fn local_branch_exists(repo_root: &Path, branch: &str) -> Result<bool, String> { + let output = std::process::Command::new("git") + .arg("-C") + .arg(repo_root) + .args(["show-ref", "--verify", "--quiet"]) + .arg(format!("refs/heads/{branch}")) + .output() + .map_err(|err| err.to_string())?; + + if output.status.success() { + return Ok(true); + } + if output.status.code() == Some(1) { + return Ok(false); + } + + let stderr = String::from_utf8_lossy(&output.stderr).trim().to_string(); + let stdout = String::from_utf8_lossy(&output.stdout).trim().to_string(); + if !stderr.is_empty() { + Err(stderr) + } else if !stdout.is_empty() { + Err(stdout) + } else { + Err(format!("git show-ref failed with status {}", output.status)) + } +} + +pub(crate) fn run_worktree_add_command( + repo_root: &Path, + path: &Path, + branch: &str, + base: &str, +) -> Result<(), String> { + let command = if local_branch_exists(repo_root, branch)? { + build_worktree_add_existing_branch_command(repo_root, path, branch) + } else { + build_worktree_add_new_branch_command(repo_root, path, branch, base) + }; + run_worktree_command(&command) +} + pub(crate) fn run_worktree_command(command: &WorktreeCommand) -> Result<(), String> { let output = std::process::Command::new(&command.program) .args(&command.args) @@ -756,6 +815,27 @@ prunable stale } #[test] + fn worktree_add_command_checks_out_existing_branch() { + let command = build_worktree_add_existing_branch_command( + Path::new("/repo/herdr"), + Path::new("/w/herdr/worktree-brave-river"), + "worktree/brave-river", + ); + assert_eq!(command.program, "git"); + assert_eq!( + command.args, + vec![ + "-C", + "/repo/herdr", + "worktree", + "add", + "/w/herdr/worktree-brave-river", + "worktree/brave-river" + ] + ); + } + + #[test] fn run_worktree_add_and_remove_create_and_delete_checkout() { let repo = create_committed_repo("worktree-run-repo"); let checkout = unique_temp_path("worktree-run-checkout"); |
