use std::ffi::OsStr;
use std::path::PathBuf;
pub trait CommandErrorContext {
fn output_with_context(
&mut self,
) -> impl std::future::Future<Output = anyhow::Result<std::process::Output>>;
}
impl CommandErrorContext for tokio::process::Command {
async fn output_with_context(&mut self) -> anyhow::Result<std::process::Output> {
let prog = program_name(self.as_std());
self.output()
.await
.map_err(|e| anyhow::anyhow!("failed to execute `{prog}`: {e}"))
}
}
pub trait SyncCommandErrorContext {
fn output_with_context(&mut self) -> anyhow::Result<std::process::Output>;
fn status_with_context(&mut self) -> anyhow::Result<std::process::ExitStatus>;
}
impl SyncCommandErrorContext for std::process::Command {
fn output_with_context(&mut self) -> anyhow::Result<std::process::Output> {
let prog = program_name(self);
self.output()
.map_err(|e| anyhow::anyhow!("failed to execute `{prog}`: {e}"))
}
fn status_with_context(&mut self) -> anyhow::Result<std::process::ExitStatus> {
let prog = program_name(self);
self.status()
.map_err(|e| anyhow::anyhow!("failed to execute `{prog}`: {e}"))
}
}
fn program_name(cmd: &std::process::Command) -> String {
let prog: &OsStr = cmd.get_program();
let path = PathBuf::from(prog);
path.display().to_string()
}