// Copyright Kani Contributors // SPDX-License-Identifier: Apache-2.0 OR MIT //! This module contains small helper functions for running Commands. //! We could possibly eliminate this if we find a small-enough dependency. use std::ffi::OsString; use std::process::Command; use anyhow::{bail, Context, Result}; /// Helper trait to fallibly run commands pub trait AutoRun { fn run(&mut self) -> Result<()>; } impl AutoRun for Command { fn run(&mut self) -> Result<()> { // This can sometimes fail during the set-up of the forked process before exec, // for example by setting `current_dir` to a directory that does not exist. let status = self.status().with_context(|| { format!( "Internal failure before invoking command: {}", render_command(self).to_string_lossy() ) })?; if !status.success() { bail!("Failed command: {}", render_command(self).to_string_lossy()); } Ok(()) } } /// Render a Command as a string, to log it fn render_command(cmd: &Command) -> OsString { let mut str = OsString::new(); for (k, v) in cmd.get_envs() { if let Some(v) = v { str.push(k); str.push("=\""); str.push(v); str.push("\" "); } } str.push(cmd.get_program()); for a in cmd.get_args() { str.push(" "); if a.to_string_lossy().contains(' ') { str.push("\""); str.push(a); str.push("\""); } else { str.push(a); } } str }