Skip to main content

jhol_core/
exec.rs

1//! Native exec: run a binary from node_modules/.bin without npx/npm exec.
2
3use std::path::{Path, PathBuf};
4
5/// Find binary in node_modules/.bin. On Windows also looks for <binary>.cmd.
6pub 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
25/// Execute binary at path with args. On Windows, .cmd scripts are run via cmd /c.
26pub 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}