Skip to main content

urma_node/install/
runner.rs

1use crate::install::Error;
2use std::process::{Command, Stdio};
3
4#[derive(Clone, Debug, PartialEq, Eq)]
5pub struct Outcome {
6    pub success: bool,
7    pub stdout: String,
8    pub stderr: String,
9}
10
11pub trait Runner {
12    fn run(&mut self, program: &str, args: &[&str]) -> Result<Outcome, Error>;
13
14    fn require(&mut self, program: &str, args: &[&str]) -> Result<Outcome, Error> {
15        let outcome = self.run(program, args)?;
16        match outcome.success {
17            true => Ok(outcome),
18            false => Err(failure(program, args, outcome.stderr.trim().to_owned())),
19        }
20    }
21}
22
23pub struct Commands;
24
25fn failure(program: &str, args: &[&str], detail: String) -> Error {
26    Error::Command {
27        program: program.to_owned(),
28        args: args.iter().map(|arg| (*arg).to_owned()).collect(),
29        detail,
30    }
31}
32
33fn text(program: &str, args: &[&str], bytes: Vec<u8>) -> Result<String, Error> {
34    String::from_utf8(bytes).map_err(|error| failure(program, args, error.to_string()))
35}
36
37impl Runner for Commands {
38    fn run(&mut self, program: &str, args: &[&str]) -> Result<Outcome, Error> {
39        let output = Command::new(program)
40            .args(args)
41            .stdin(Stdio::null())
42            .output()
43            .map_err(|error| failure(program, args, error.to_string()))?;
44        Ok(Outcome {
45            success: output.status.success(),
46            stdout: text(program, args, output.stdout)?,
47            stderr: text(program, args, output.stderr)?,
48        })
49    }
50}