//! Worktree-manager integration tests against a real `git` binary and a //! tmpdir-backed source repo. mod common; use std::path::PathBuf; use std::process::Command; use common::init_repo; use maestro_daemon::worktree::WorktreeManager; use tempfile::TempDir; fn worktree_branches(repo: &PathBuf) -> Vec { let out = Command::new("git") .arg("-C") .arg(repo) .args(["worktree", "list", "--porcelain"]) .output() .expect("git worktree list"); assert!(out.status.success()); let s = String::from_utf8_lossy(&out.stdout); s.lines() .filter_map(|l| l.strip_prefix("branch refs/heads/").map(String::from)) .collect() } #[test] fn add_creates_worktree_on_new_branch() { let repo_dir = TempDir::new().unwrap(); let repo = repo_dir.path().to_path_buf(); init_repo(&repo); let wt_root = TempDir::new().unwrap(); let mgr = WorktreeManager::new(wt_root.path()); let path = mgr.add(&repo, "feat/example").expect("add worktree"); assert!(path.exists()); assert!(path.join("README").exists()); assert!(path.starts_with(wt_root.path())); let branches = worktree_branches(&repo); assert!(branches.iter().any(|b| b == "feat/example"), "{branches:?}"); } #[test] fn add_twice_generates_distinct_paths() { let repo_dir = TempDir::new().unwrap(); let repo = repo_dir.path().to_path_buf(); init_repo(&repo); let wt_root = TempDir::new().unwrap(); let mgr = WorktreeManager::new(wt_root.path()); let p1 = mgr.add(&repo, "feat/a").expect("add a"); let p2 = mgr.add(&repo, "feat/b").expect("add b"); assert_ne!(p1, p2); assert!(p1.exists()); assert!(p2.exists()); } #[test] fn remove_prunes_worktree() { let repo_dir = TempDir::new().unwrap(); let repo = repo_dir.path().to_path_buf(); init_repo(&repo); let wt_root = TempDir::new().unwrap(); let mgr = WorktreeManager::new(wt_root.path()); let path = mgr.add(&repo, "feat/gone").expect("add"); assert!(path.exists()); mgr.remove(&repo, &path).expect("remove"); assert!(!path.exists()); let branches = worktree_branches(&repo); // The branch itself still exists, but the worktree should be gone — only // the base repo's main branch should show in `worktree list`. assert_eq!(branches, vec!["main".to_string()]); } #[test] fn add_fails_when_branch_already_exists() { let repo_dir = TempDir::new().unwrap(); let repo = repo_dir.path().to_path_buf(); init_repo(&repo); // pre-create the branch let status = Command::new("git") .arg("-C") .arg(&repo) .args(["branch", "feat/dup"]) .status() .unwrap(); assert!(status.success()); let wt_root = TempDir::new().unwrap(); let mgr = WorktreeManager::new(wt_root.path()); let err = mgr.add(&repo, "feat/dup").unwrap_err(); let msg = format!("{err}"); assert!(msg.contains("git exited"), "{msg}"); }