1use std::ffi::OsString;
8use std::process::Command;
9
10use anyhow::{Context, Result, bail};
11
12pub trait AutoRun {
14 fn run(&mut self) -> Result<()>;
15}
16impl AutoRun for Command {
17 fn run(&mut self) -> Result<()> {
18 let status = self.status().with_context(|| {
21 format!(
22 "Internal failure before invoking command: {}",
23 render_command(self).to_string_lossy()
24 )
25 })?;
26 if !status.success() {
27 bail!("Failed command: {}", render_command(self).to_string_lossy());
28 }
29 Ok(())
30 }
31}
32
33fn render_command(cmd: &Command) -> OsString {
35 let mut str = OsString::new();
36
37 for (k, v) in cmd.get_envs() {
38 if let Some(v) = v {
39 str.push(k);
40 str.push("=\"");
41 str.push(v);
42 str.push("\" ");
43 }
44 }
45
46 str.push(cmd.get_program());
47
48 for a in cmd.get_args() {
49 str.push(" ");
50 if a.to_string_lossy().contains(' ') {
51 str.push("\"");
52 str.push(a);
53 str.push("\"");
54 } else {
55 str.push(a);
56 }
57 }
58
59 str
60}