use shlex;
use std::process;
#[allow(dead_code)]
#[derive(Debug)]
pub struct ProcStat {
pub exit_code: i32,
pub stdout: String,
pub stderr: String,
}
impl ProcStat {
pub fn output(&self) -> String {
self.stdout.clone()
}
pub fn trimmed_output(&self) -> String {
self.stdout.trim_end().to_string()
}
}
pub fn get_exitcode_stdout_stderr(cmd: &str) -> Option<ProcStat> {
let parts = shlex::split(cmd).unwrap_or_else(|| panic!("cannot parse command {:?}", cmd));
let head = &parts[0];
let tail = &parts[1..];
let mut p = process::Command::new(head);
p.args(tail);
let p = p
.output()
.unwrap_or_else(|_| panic!("failed to execute {:?}", cmd));
let result = ProcStat {
exit_code: p.status.code()?,
stdout: String::from_utf8_lossy(&p.stdout).to_string(),
stderr: String::from_utf8_lossy(&p.stderr).to_string(),
};
Some(result)
}
pub fn exec_cmd(cmd: &str) {
let parts = shlex::split(cmd).unwrap();
let head = &parts[0];
let tail = &parts[1..];
let mut p = process::Command::new(head);
p.args(tail);
let mut child = p
.spawn()
.unwrap_or_else(|_| panic!("command {:?} failed to start", cmd));
child.wait().expect("command wasn't running");
}
pub fn exec_cmd_in_bg(cmd: &str) {
let parts = shlex::split(cmd).unwrap();
let head = &parts[0];
let tail = &parts[1..];
process::Command::new(head)
.args(tail)
.spawn()
.unwrap_or_else(|_| panic!("command {:?} failed to start", cmd));
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn get_exitcode_stdout_stderr_exit_code_test() {
use which::which;
let cmd = "rustc";
let result = which(cmd);
if result.is_err() {
return;
}
let cmd = "rustc --version";
let stat = get_exitcode_stdout_stderr(cmd).unwrap();
assert_eq!(stat.exit_code, 0);
}
#[test]
fn get_exitcode_stdout_stderr_stdout_test() {
use which::which;
let cmd = "rustc";
let result = which(cmd);
if result.is_err() {
return;
}
let cmd = "rustc --version";
let stat = get_exitcode_stdout_stderr(cmd).unwrap();
assert!(stat.stdout.starts_with("rustc"));
}
#[test]
fn get_exitcode_stdout_stderr_stderr_test() {
use which::which;
let cmd = "rustc";
let result = which(cmd);
if result.is_err() {
return;
}
let cmd = "rustc --nothing20220731"; let stat = get_exitcode_stdout_stderr(cmd).unwrap();
assert!(stat.exit_code != 0);
assert!(stat.stderr.len() > 0);
}
#[test]
fn trimmed_output_test() {
use which::which;
let cmd = "rustc";
let result = which(cmd);
if result.is_err() {
return;
}
let cmd = "rustc --version";
let stat = get_exitcode_stdout_stderr(cmd).unwrap();
assert!(stat.output() == stat.stdout.clone());
assert!(stat.trimmed_output().len() < stat.output().len());
}
#[test]
fn exec_cmd_test() {
let cmd = "rustc --version";
exec_cmd(cmd);
}
#[test]
fn exec_cmd_in_bg_test() {
let cmd = "rustc --version";
exec_cmd_in_bg(cmd);
}
}