command_error/
process_wrap.rs1use 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}