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