greentic_dev/
passthrough.rs

1use anyhow::{Context, Result, anyhow, bail};
2use std::env;
3use std::ffi::OsString;
4use std::path::{Path, PathBuf};
5use std::process::{Command, ExitStatus, Stdio};
6
7/// Resolve a binary by name using env override, optional workspace target, then PATH.
8pub fn resolve_binary(name: &str) -> Result<PathBuf> {
9    let env_key = format!("GREENTIC_DEV_BIN_{}", name.replace('-', "_").to_uppercase());
10    if let Ok(path) = env::var(&env_key) {
11        let pb = PathBuf::from(path);
12        if pb.exists() {
13            return Ok(pb);
14        }
15        bail!("{env_key} points to non-existent binary: {}", pb.display());
16    }
17
18    // Optional workspace target resolution (debug and release).
19    if let Ok(cwd) = env::current_dir() {
20        for dir in ["target/debug", "target/release"] {
21            let candidate = cwd.join(dir).join(name);
22            if candidate.exists() {
23                return Ok(candidate);
24            }
25        }
26    }
27
28    which::which(name).with_context(|| {
29        format!("failed to find `{name}` in PATH; set {env_key} or install {name}")
30    })
31}
32
33pub fn run_passthrough(bin: &Path, args: &[OsString], verbose: bool) -> Result<ExitStatus> {
34    if verbose {
35        eprintln!("greentic-dev passthrough -> {} {:?}", bin.display(), args);
36        let _ = Command::new(bin)
37            .arg("--version")
38            .stdout(Stdio::inherit())
39            .stderr(Stdio::inherit())
40            .status();
41    }
42
43    Command::new(bin)
44        .args(args)
45        .stdin(Stdio::inherit())
46        .stdout(Stdio::inherit())
47        .stderr(Stdio::inherit())
48        .status()
49        .map_err(|e| anyhow!("failed to execute {}: {e}", bin.display()))
50}