command_error/
exec_error.rs1use std::fmt::Debug;
2use std::fmt::Display;
3
4use crate::CommandDisplay;
5#[cfg(doc)]
6use crate::CommandExt;
7#[cfg(doc)]
8use crate::OutputError;
9#[cfg(feature = "miette")]
10use miette::Diagnostic;
11
12pub struct ExecError {
39 pub(crate) command: Box<dyn CommandDisplay + Send + Sync>,
40 pub(crate) inner: std::io::Error,
41}
42
43impl ExecError {
44 pub fn new(command: Box<dyn CommandDisplay + Send + Sync>, inner: std::io::Error) -> Self {
46 Self { command, inner }
47 }
48}
49
50impl Debug for ExecError {
51 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
52 f.debug_struct("ExecError")
53 .field("program", &self.command.program())
54 .field("inner", &self.inner)
55 .finish()
56 }
57}
58
59impl Display for ExecError {
60 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
61 write!(
62 f,
63 "Failed to execute `{}`: {}",
64 self.command.program_quoted(),
65 self.inner
66 )
67 }
68}
69
70impl std::error::Error for ExecError {}
71
72#[cfg(feature = "miette")]
73impl Diagnostic for ExecError {
74 fn help<'a>(&'a self) -> Option<Box<dyn Display + 'a>> {
75 Some(Box::new(format!(
76 "Is {} installed and present on your $PATH?",
77 self.command.program_quoted()
78 )))
79 }
80}
81
82#[cfg(test)]
83mod tests {
84 use super::*;
85 use static_assertions::assert_impl_all;
86
87 assert_impl_all!(ExecError: Send, Sync);
88}