kani_verifier/
cmd.rs

1// Copyright Kani Contributors
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3
4//! This module contains small helper functions for running Commands.
5//! We could possibly eliminate this if we find a small-enough dependency.
6
7use std::ffi::OsString;
8use std::process::Command;
9
10use anyhow::{Context, Result, bail};
11
12/// Helper trait to fallibly run commands
13pub trait AutoRun {
14    fn run(&mut self) -> Result<()>;
15}
16impl AutoRun for Command {
17    fn run(&mut self) -> Result<()> {
18        // This can sometimes fail during the set-up of the forked process before exec,
19        // for example by setting `current_dir` to a directory that does not exist.
20        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
33/// Render a Command as a string, to log it
34fn 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}