rustible/src/utils/cmd.rs

119 lines
2.7 KiB
Rust
Raw Normal View History

2023-04-19 21:49:30 +02:00
use duct::cmd as duct_cmd;
use std::path::PathBuf;
#[derive(Clone, Debug, Serialize)]
pub struct Cmd {
program: String,
args: Vec<String>,
stdin: Option<String>,
chdir: Option<PathBuf>,
}
impl Cmd {
pub fn new<T: AsRef<str>>(program: T) -> Cmd {
Cmd {
program: program.as_ref().to_string(),
args: Vec::new(),
stdin: None,
chdir: None,
}
}
pub fn arg<T: AsRef<str>>(self, arg: T) -> Cmd {
let Self { program, mut args, stdin, chdir, .. } = self;
args.push(arg.as_ref().to_string());
Cmd {
program,
args,
stdin,
chdir,
}
}
pub fn args<T: AsRef<str>>(self, new_args: & [ T ]) -> Cmd {
let Self { program, mut args, stdin, chdir, .. } = self;
for arg in new_args {
args.push(arg.as_ref().to_string());
}
Cmd {
program,
args,
stdin,
chdir,
} }
pub fn stdin<T: AsRef<str>>(self, input: T) -> Cmd {
let Self { program, args, mut stdin, chdir, .. } = self;
stdin = if let Some(mut s) = stdin {
s.push_str(input.as_ref());
Some(s)
} else {
Some(input.as_ref().to_string())
};
Cmd {
program,
args,
stdin,
chdir,
}
}
pub fn chdir<T: AsRef<str>>(self, dir: T) -> Cmd {
let Self { program, args, stdin, .. } = self;
Cmd {
program,
args,
stdin,
chdir: Some(PathBuf::from(dir.as_ref())),
}
}
pub fn run(self) -> Result<CmdOutput, std::io::Error> {
let Self { program, args, stdin, chdir, .. } = self;
let mut cmd = duct_cmd(&program, &args);
if let Some(stdin) = &stdin {
cmd = cmd.stdin_bytes(stdin.as_bytes());
}
if let Some(chdir) = &chdir {
cmd = cmd.dir(chdir);
}
let res = cmd.unchecked()
.stdout_capture()
.stderr_capture()
.run()?;
Ok(CmdOutput {
program,
args,
success: res.status.success(),
stdin,
dir: chdir,
stdout: String::from_utf8(res.stdout).unwrap(),
stderr: String::from_utf8(res.stderr).unwrap(),
})
}
}
#[derive(Clone, Debug, Serialize)]
pub struct CmdOutput {
pub program: String,
pub args: Vec<String>,
pub success: bool,
pub stdin: Option<String>,
pub dir: Option<PathBuf>,
pub stdout: String,
pub stderr: String,
}