use std::process::{Command, ExitStatus};
use anyhow::{anyhow, Context, Result};
pub trait CommandExt {
fn run(&mut self, verbose: bool) -> Result<()>;
fn run_and_get_status(&mut self, verbose: bool) -> Result<ExitStatus>;
fn run_and_get_stdout(&mut self, verbose: bool) -> Result<String>;
}
impl CommandExt for Command {
fn run(&mut self, verbose: bool) -> Result<()> {
let status = self.run_and_get_status(verbose)?;
if status.success() {
Ok(())
} else {
Err(anyhow!(
"`{:?}` failed with exit code: {:?}",
self,
status.code()
))
}
}
fn run_and_get_status(&mut self, verbose: bool) -> Result<ExitStatus> {
if verbose {
eprintln!("+ {:?}", self);
}
self.status()
.with_context(|| format!("couldn't execute `{:?}`", self))
}
fn run_and_get_stdout(&mut self, verbose: bool) -> Result<String> {
if verbose {
eprintln!("+ {:?}", self);
}
let out = self
.output()
.with_context(|| format!("couldn't execute `{:?}`", self))?;
if out.status.success() {
Ok(String::from_utf8(out.stdout)
.with_context(|| format!("`{:?}` output was not UTF-8", self))?)
} else {
Err(anyhow!(
"`{:?}` failed with exit code: {:?}",
self,
out.status.code()
))?
}
}
}