use std::collections::HashMap;
use std::ffi::{OsStr, OsString};
use std::io::Result;
use std::path::PathBuf;
use std::process::{Command, ExitStatus, Output};
#[derive(Clone, Debug)]
pub struct Cmd {
program: OsString,
args: Vec<OsString>,
envs: HashMap<OsString, OsString>,
work: Option<PathBuf>,
}
impl Cmd {
pub fn new<S: AsRef<OsStr>>(program: S) -> Self {
Self {
program: program.as_ref().to_owned(),
args: vec![],
envs: HashMap::new(),
work: None,
}
}
pub fn arg<S: AsRef<OsStr>>(mut self, arg: S) -> Self {
self.args.push(arg.as_ref().to_owned());
self
}
pub fn args<I, S>(mut self, args: I) -> Self
where
I: IntoIterator<Item = S>,
S: AsRef<OsStr>,
{
self.args.extend(args.into_iter().map(|e| e.as_ref().to_owned()));
self
}
pub fn env<K: AsRef<OsStr>, V: AsRef<OsStr>>(mut self, env: K, val: V) -> Self {
self.envs.insert(env.as_ref().to_owned(), val.as_ref().to_owned());
self
}
pub fn output(&self) -> Output {
println!("Executing: {:?} {:?} {:?}", self.program, self.args, self.envs);
self.command().output().expect(format!("Command executon '{:?} {:?} {:?}' failed",
self.program, self.args, self.envs).as_str()
)
}
pub fn run(&self) {
println!("Executing: {:?} {:?} {:?}", self.program, self.args, self.envs);
assert!(self.run_result().expect(format!("Command executon '{:?} {:?} {:?}' failed",
self.program, self.args, self.envs).as_str()
).success());
}
pub fn run_result(&self) -> Result<ExitStatus> {
self.command().status()
}
pub fn command(&self) -> Command {
let mut command = Command::new(&self.program);
command.args(&self.args);
command.envs(&self.envs);
if let Some(work_dir) = &self.work {
command.current_dir(work_dir);
}
command
}
}