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 {
51 output,
52 command: Box::new(displayed),
53 }),
54 Err(error) => Err(Error::from(OutputConversionError {
55 command: Box::new(displayed),
56 inner: Box::new(error),
57 })
58 .into()),
59 },
60 Err(inner) => Err(Error::from(ExecError {
61 command: Box::new(displayed),
62 inner,
63 })
64 .into()),
65 }
66 }
67
68 fn status_checked_as<R, E>(
69 &mut self,
70 succeeded: impl Fn(OutputContext<std::process::ExitStatus>) -> Result<R, E>,
71 ) -> Result<R, E>
72 where
73 E: From<Self::Error>,
74 {
75 self.log()?;
76 let displayed: Utf8ProgramAndArgs = self.command().into();
77 let mut child = match self.spawn() {
78 Ok(child) => child,
79 Err(inner) => {
80 return Err(Error::from(ExecError::new(Box::new(displayed), inner)).into());
81 }
82 };
83
84 match child.wait() {
85 Ok(status) => succeeded(OutputContext {
86 output: status,
87 command: Box::new(displayed),
88 }),
89 Err(inner) => Err(Error::from(ExecError {
90 command: Box::new(displayed),
91 inner,
92 })
93 .into()),
94 }
95 }
96
97 fn spawn_checked(&mut self) -> Result<Self::Child, Self::Error> {
98 let displayed: Utf8ProgramAndArgs = self.command().into();
99 match self.spawn() {
100 Ok(child) => Ok(ChildContext {
101 child,
102 command: Box::new(displayed),
103 }),
104 Err(inner) => Err(Error::from(ExecError {
105 command: Box::new(displayed),
106 inner,
107 })),
108 }
109 }
110}