git_worktree_manager/operations/
path_cmd.rs1use crate::error::{CwError, Result};
5use crate::git;
6use crate::messages;
7
8pub fn worktree_path(branch: Option<&str>, list_branches: bool, interactive: bool) -> Result<()> {
10 if interactive {
11 return interactive_path_selection();
12 }
13
14 if list_branches {
15 return list_branch_names();
16 }
17
18 let branch = branch.ok_or_else(|| {
19 CwError::Other(
20 "branch argument is required (unless --list-branches or --interactive is used)"
21 .to_string(),
22 )
23 })?;
24
25 let repo = git::get_repo_root(None)?;
27 let normalized = git::normalize_branch_name(branch);
28 let path = git::find_worktree_by_branch(&repo, branch)?
29 .or(git::find_worktree_by_branch(
30 &repo,
31 &format!("refs/heads/{}", normalized),
32 )?)
33 .ok_or_else(|| CwError::WorktreeNotFound(messages::worktree_not_found(branch)))?;
34
35 println!("{}", path.display());
36 Ok(())
37}
38
39fn list_branch_names() -> Result<()> {
40 if let Ok(repo) = git::get_repo_root(None) {
41 if let Ok(worktrees) = git::parse_worktrees(&repo) {
42 for (branch, _) in &worktrees {
43 let normalized = git::normalize_branch_name(branch);
44 if normalized != "(detached)" {
45 println!("{}", normalized);
46 }
47 }
48 }
49 }
50 Ok(())
51}
52
53fn interactive_path_selection() -> Result<()> {
54 let mut entries: Vec<(String, String)> = Vec::new(); let repo = git::get_main_repo_root(None)?;
57 let worktrees = git::parse_worktrees(&repo)?;
58 let repo_resolved = git::canonicalize_or(&repo);
59
60 for (branch, path) in &worktrees {
61 let normalized = git::normalize_branch_name(branch);
62 let path_resolved = git::canonicalize_or(path);
63 if path_resolved == repo_resolved {
64 let label = if normalized.is_empty() || normalized == "(detached)" {
65 "main (root)".to_string()
66 } else {
67 format!("{} (root)", normalized)
68 };
69 entries.insert(0, (label, path.to_string_lossy().to_string()));
70 } else if normalized != "(detached)" {
71 entries.push((normalized.to_string(), path.to_string_lossy().to_string()));
72 }
73 }
74
75 if entries.is_empty() {
76 eprintln!("No worktrees found.");
77 std::process::exit(1);
78 }
79
80 if entries.len() == 1 {
81 println!("{}", entries[0].1);
82 return Ok(());
83 }
84
85 match crate::tui::arrow_select(&entries, "Select worktree:", 0) {
87 Some(selected_path) => {
88 println!("{}", selected_path);
89 Ok(())
90 }
91 None => {
92 std::process::exit(1);
93 }
94 }
95}