1use std::path::Path;
2use std::process::Stdio;
3
4use callisto_model::{CommandError, CommandOutput, CommandRunner};
5
6pub struct CliCommandRunner;
7
8impl CommandRunner for CliCommandRunner {
9 fn run(&self, program: &str, args: &[&str], cwd: &Path) -> Result<CommandOutput, CommandError> {
10 let output = std::process::Command::new(program)
11 .args(args)
12 .current_dir(cwd)
13 .stdin(Stdio::null())
14 .stdout(Stdio::piped())
15 .stderr(Stdio::piped())
16 .output();
17
18 match output {
19 Ok(o) => {
20 let out = CommandOutput {
21 exit_code: o.status.code(),
22 stdout: String::from_utf8_lossy(&o.stdout).into_owned(),
23 stderr: String::from_utf8_lossy(&o.stderr).into_owned(),
24 };
25 if !out.stderr.is_empty() {
26 eprint!("{}", out.stderr);
27 }
28 Ok(out)
29 }
30 Err(e) if e.kind() == std::io::ErrorKind::NotFound => Err(CommandError::NotFound {
31 program: program.to_string(),
32 }),
33 Err(e) => Err(CommandError::Io {
34 program: program.to_string(),
35 message: e.to_string(),
36 }),
37 }
38 }
39}