diff --git a/crates/maestro-daemon/tests/worktree.rs b/crates/maestro-daemon/tests/worktree.rs index c7c8dbf..e5d2339 100644 --- a/crates/maestro-daemon/tests/worktree.rs +++ b/crates/maestro-daemon/tests/worktree.rs @@ -405,13 +405,17 @@ fn run_git(dir: &std::path::Path, args: &[&str]) { ); } +/// `git worktree add -b` alone fails outright when the branch already exists, +/// even with the target directory free — a random handle commonly collides +/// with one an earlier, already-removed worktree left behind. `add_new` +/// sidesteps it on the branch name itself instead of erroring (#77). #[test] -fn add_fails_when_branch_already_exists() { +fn add_new_suffixes_branch_name_on_branch_collision() { let repo_dir = TempDir::new().unwrap(); let repo = repo_dir.path().to_path_buf(); init_repo(&repo); - // pre-create the branch + // pre-create the branch, unused by any worktree. let status = Command::new("git") .arg("-C") .arg(&repo) @@ -423,9 +427,17 @@ fn add_fails_when_branch_already_exists() { let wt_root = TempDir::new().unwrap(); let mgr = WorktreeManager::new(Some(wt_root.path().to_path_buf())); - let err = mgr.add_new(&repo, "feat/dup").unwrap_err(); - let msg = format!("{err}"); - assert!(msg.contains("git exited"), "{msg}"); + let path = mgr + .add_new(&repo, "feat/dup") + .expect("sidesteps the branch collision"); + assert!(path.ends_with("feat/dup-2"), "{}", path.display()); + assert!(path.exists()); + + // The pre-existing branch is untouched; the new worktree checked out the + // suffixed one instead of erroring or adopting `feat/dup`. + let branches = worktree_branches(&repo); + assert!(branches.contains(&"feat/dup-2".to_string()), "{branches:?}"); + assert!(!branches.contains(&"feat/dup".to_string()), "{branches:?}"); } /// The project picker lists linked worktrees as pickable rows, so `base_repo`