aboutsummaryrefslogtreecommitdiff
path: root/src/worktree.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/worktree.rs')
-rw-r--r--src/worktree.rs80
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");