use std::process::Command; use anyhow::{Context, anyhow, bail}; /// Spawn a subprocess with arguments. /// /// Collects `stdout` and returns it on success. /// Returns `Err` if the exit code isn't 0, or if the process failed to spawn. pub fn cmd(cmd: &[&str]) -> anyhow::Result { let [cmd, args @ ..] = cmd else { bail!("missing command"); }; let mut command = Command::new(cmd); command.args(args); println!("$ {command:?}"); let output = command .output() .with_context(|| anyhow!("Failed to run {command:?}"))?; let stdout = String::from_utf8_lossy(&output.stdout); if !output.status.success() { let stderr = String::from_utf8_lossy(&output.stderr); eprintln!("{command:?} failed"); eprintln!("stdout:\n{stdout}\n"); eprintln!("stderr:\n{stderr}\n"); bail!("{command:?} failed with exit code {}", output.status); } Ok(stdout.to_string()) }