command_error/
process_wrap.rs

1use std::fmt::Debug;
2use std::fmt::Display;
3use std::process::Output;
4
5use process_wrap::std::StdChildWrapper;
6use process_wrap::std::StdCommandWrap;
7
8use crate::ChildContext;
9use crate::CommandExt;
10use crate::Error;
11use crate::ExecError;
12use crate::OutputContext;
13use crate::OutputConversionError;
14use crate::OutputLike;
15use crate::Utf8ProgramAndArgs;
16
17impl CommandExt for StdCommandWrap {
18    type Error = Error;
19    type Child = ChildContext<Box<dyn StdChildWrapper>>;
20
21    fn log(&self) -> Result<(), Self::Error> {
22        #[cfg(feature = "tracing")]
23        {
24            let command: Utf8ProgramAndArgs = self.command().into();
25            tracing::debug!(%command, "Executing command");
26        }
27        Ok(())
28    }
29
30    fn output_checked_as<O, R, E>(
31        &mut self,
32        succeeded: impl Fn(OutputContext<O>) -> Result<R, E>,
33    ) -> Result<R, E>
34    where
35        O: Debug + OutputLike + TryFrom<Output> + Send + Sync + 'static,
36        <O as TryFrom<Output>>::Error: Display + Send + Sync,
37        E: From<Self::Error> + Send + Sync,
38    {
39        self.log()?;
40        let displayed: Utf8ProgramAndArgs = self.command().into();
41        let child = match self.spawn() {
42            Ok(child) => child,
43            Err(inner) => {
44                return Err(Error::from(ExecError::new(Box::new(displayed), inner)).into());
45            }
46        };
47
48        match child.wait_with_output() {
49            Ok(output) => match output.try_into() {
50                Ok(output) => succeeded(OutputContext::new(output, Box::new(displayed))),
51                Err(error) => Err(Error::from(OutputConversionError::new(
52                    Box::new(displayed),
53                    Box::new(error),
54                ))
55                .into()),
56            },
57            Err(inner) => Err(Error::from(ExecError::new(Box::new(displayed), inner)).into()),
58        }
59    }
60
61    fn status_checked_as<R, E>(
62        &mut self,
63        succeeded: impl Fn(OutputContext<std::process::ExitStatus>) -> Result<R, E>,
64    ) -> Result<R, E>
65    where
66        E: From<Self::Error>,
67    {
68        self.log()?;
69        let displayed: Utf8ProgramAndArgs = self.command().into();
70        let mut child = match self.spawn() {
71            Ok(child) => child,
72            Err(inner) => {
73                return Err(Error::from(ExecError::new(Box::new(displayed), inner)).into());
74            }
75        };
76
77        match child.wait() {
78            Ok(status) => succeeded(OutputContext::new(status, Box::new(displayed))),
79            Err(inner) => Err(Error::from(ExecError::new(Box::new(displayed), inner)).into()),
80        }
81    }
82
83    fn spawn_checked(&mut self) -> Result<Self::Child, Self::Error> {
84        let displayed: Utf8ProgramAndArgs = self.command().into();
85        match self.spawn() {
86            Ok(child) => Ok(ChildContext::new(child, Box::new(displayed))),
87            Err(inner) => Err(Error::from(ExecError::new(Box::new(displayed), inner))),
88        }
89    }
90}