1use crate::cli::output::print_warning;
4use crate::infra::error::HookError;
5use std::collections::BTreeMap;
6use std::path::Path;
7use std::process::Command;
8
9pub fn execute_hook_command(
11 command_str: &str,
12 working_dir: &Path,
13 env_vars: &BTreeMap<String, String>,
14) -> Result<bool, HookError> {
15 #[cfg(unix)]
16 let mut cmd = Command::new("sh");
17 #[cfg(unix)]
18 cmd.args(["-c", command_str]);
19
20 #[cfg(windows)]
21 let mut cmd = Command::new("cmd");
22 #[cfg(windows)]
23 cmd.args(["/C", command_str]);
24
25 cmd.current_dir(working_dir);
26 for (k, v) in env_vars {
27 cmd.env(k, v);
28 }
29
30 let status = cmd
31 .status()
32 .map_err(|e| HookError::ExecutionFailed(format!("Failed to spawn hook command: {}", e)))?;
33
34 Ok(status.success())
35}
36
37pub fn run_post_start_hook(
39 hook: Option<&str>,
40 worktree_path: &Path,
41 env_vars: &BTreeMap<String, String>,
42) -> Result<bool, HookError> {
43 if let Some(cmd) = hook {
44 let success = execute_hook_command(cmd, worktree_path, env_vars)?;
45 if !success {
46 print_warning(format!(
47 "post_start hook '{}' exited with non-zero status; retaining worktree",
48 cmd
49 ));
50 }
51 return Ok(success);
52 }
53 Ok(true)
54}
55
56pub fn run_pre_finish_hook(
58 hook: Option<&str>,
59 worktree_path: &Path,
60 env_vars: &BTreeMap<String, String>,
61 force: bool,
62) -> Result<bool, HookError> {
63 if let Some(cmd) = hook {
64 let success = execute_hook_command(cmd, worktree_path, env_vars)?;
65 if !success {
66 if force {
67 print_warning(format!(
68 "pre_finish hook '{}' failed, but continuing due to --force",
69 cmd
70 ));
71 return Ok(false);
72 } else {
73 return Err(HookError::PreFinishFailed {
74 hook: cmd.to_string(),
75 code: 1,
76 });
77 }
78 }
79 return Ok(true);
80 }
81 Ok(true)
82}
83
84pub fn run_post_finish_hook(
86 hook: Option<&str>,
87 repo_root: &Path,
88 env_vars: &BTreeMap<String, String>,
89) -> Result<bool, HookError> {
90 if let Some(cmd) = hook {
91 let success = execute_hook_command(cmd, repo_root, env_vars)?;
92 if !success {
93 print_warning(format!(
94 "post_finish hook '{}' exited with non-zero status",
95 cmd
96 ));
97 }
98 return Ok(success);
99 }
100 Ok(true)
101}