git_worktree_manager/operations/
shell.rs1use std::path::PathBuf;
5
6use console::style;
7
8use crate::error::{CwError, Result};
9use crate::git;
10
11pub fn shell_worktree(worktree: Option<&str>, command: Option<Vec<String>>) -> Result<()> {
13 let target_path: PathBuf;
14
15 if let Some(wt) = worktree {
16 let repo = git::get_repo_root(None)?;
17 let path = git::find_worktree_by_branch(&repo, wt)?
18 .or(git::find_worktree_by_branch(
19 &repo,
20 &format!("refs/heads/{}", git::normalize_branch_name(wt)),
21 )?)
22 .ok_or_else(|| {
23 CwError::WorktreeNotFound(format!("No worktree found for branch '{}'", wt))
24 })?;
25 target_path = path;
26 } else {
27 target_path = std::env::current_dir()?;
28 let _ = git::get_current_branch(Some(&target_path))?;
30 }
31
32 if !target_path.exists() {
33 return Err(CwError::WorktreeNotFound(format!(
34 "Worktree directory does not exist: {}",
35 target_path.display()
36 )));
37 }
38
39 if let Some(cmd) = command {
40 if cmd.is_empty() {
41 return open_shell(&target_path, worktree);
42 }
43 println!(
45 "{} {}\n",
46 style(format!("Executing in {}:", target_path.display())).cyan(),
47 cmd.join(" ")
48 );
49
50 let status = std::process::Command::new(&cmd[0])
51 .args(&cmd[1..])
52 .current_dir(&target_path)
53 .status()?;
54
55 std::process::exit(status.code().unwrap_or(1));
56 } else {
57 open_shell(&target_path, worktree)?;
58 }
59
60 Ok(())
61}
62
63fn open_shell(path: &std::path::Path, branch: Option<&str>) -> Result<()> {
64 let branch_name = branch
65 .map(|b| b.to_string())
66 .or_else(|| git::get_current_branch(Some(path)).ok())
67 .unwrap_or_else(|| "unknown".to_string());
68
69 println!(
70 "{} {}\n{}\n{}\n",
71 style("Opening shell in worktree:").cyan().bold(),
72 branch_name,
73 style(format!("Path: {}", path.display())).dim(),
74 style("Type 'exit' to return").dim(),
75 );
76
77 let shell = std::env::var("SHELL").unwrap_or_else(|_| "/bin/bash".to_string());
78
79 let _ = std::process::Command::new(&shell)
80 .current_dir(path)
81 .status();
82
83 Ok(())
84}