1use std::path::{Path, PathBuf};
4
5pub fn find_binary_in_node_modules(binary: &str, from_dir: &Path) -> Option<PathBuf> {
7 let bin_dir = from_dir.join("node_modules").join(".bin");
8 if !bin_dir.is_dir() {
9 return None;
10 }
11 let exact = bin_dir.join(binary);
12 if exact.exists() {
13 return Some(exact);
14 }
15 #[cfg(windows)]
16 {
17 let cmd = bin_dir.join(format!("{}.cmd", binary));
18 if cmd.exists() {
19 return Some(cmd);
20 }
21 }
22 None
23}
24
25pub fn exec_binary(
27 binary_path: &Path,
28 args: &[String],
29 cwd: &Path,
30) -> Result<std::process::ExitStatus, String> {
31 #[cfg(unix)]
32 {
33 let status = std::process::Command::new(binary_path)
34 .args(args)
35 .current_dir(cwd)
36 .status()
37 .map_err(|e| format!("Failed to execute: {}", e))?;
38 return Ok(status);
39 }
40
41 #[cfg(windows)]
42 {
43 let ext = binary_path.extension().and_then(|e| e.to_str());
44 if ext == Some("cmd") || ext == Some("bat") {
45 let mut cmd_args = vec!["/c".to_string(), binary_path.to_string_lossy().into_owned()];
46 cmd_args.extend(args.iter().cloned());
47 let status = std::process::Command::new("cmd")
48 .args(&cmd_args)
49 .current_dir(cwd)
50 .status()
51 .map_err(|e| format!("Failed to execute: {}", e))?;
52 return Ok(status);
53 }
54 let status = std::process::Command::new(binary_path)
55 .args(args)
56 .current_dir(cwd)
57 .status()
58 .map_err(|e| format!("Failed to execute: {}", e))?;
59 Ok(status)
60 }
61}