checked_command/
wrapper.rs

1use std::ffi::OsStr;
2use std::io::Error as IoError;
3use std::path::Path;
4use std::process;
5use std::process::Stdio;
6use std::process::{Child, Command};
7
8use ext::{ChildExt, CommandExt, Error, Output};
9
10/// A wrapper around `std::process::Child`
11/// which hides the original `wait`/`wait_with_output` methods
12/// and replaces it with the versions from `checked_command::ChildExt`
13#[derive(Debug)]
14pub struct CheckedChild {
15    child: Child,
16}
17
18impl From<Child> for CheckedChild {
19    fn from(child: Child) -> CheckedChild {
20        CheckedChild { child }
21    }
22}
23
24impl CheckedChild {
25    /// returns a mutable reference to the wrapped child
26    pub fn as_std_command(&mut self) -> &mut Child {
27        &mut self.child
28    }
29
30    /// converts the checked child into a `std::process::Child`
31    /// note that a `Into<Child>` implementation is not provided.
32    pub fn into_std_command(self) -> Child {
33        self.child
34    }
35
36    /// return a optional &mut to the childs Stding
37    pub fn stdin(&mut self) -> &mut Option<process::ChildStdin> {
38        &mut self.child.stdin
39    }
40
41    /// return a optional &mut to the childs Stding
42    pub fn stdout(&mut self) -> &mut Option<process::ChildStdout> {
43        &mut self.child.stdout
44    }
45
46    /// return a optional &mut to the childs Stding
47    pub fn stderr(&mut self) -> &mut Option<process::ChildStderr> {
48        &mut self.child.stderr
49    }
50
51    /// calls `std::process::Child::kill`
52    pub fn kill(&mut self) -> Result<(), IoError> {
53        self.child.kill()
54    }
55
56    /// calls `std::process::Child::id`
57    pub fn id(&self) -> u32 {
58        self.child.id()
59    }
60
61    /// calls `ChildExt::checked_wait` on the wrapped `Child`
62    pub fn wait(&mut self) -> Result<(), Error> {
63        self.child.checked_wait()
64    }
65
66    /// calls `ChildExt::checked_try_wait` on the wrapped `Child`
67    #[cfg(feature = "process_try_wait")]
68    pub fn try_wait(&mut self) -> Result<bool, Error> {
69        self.child.checked_try_wait()
70    }
71
72    /// calls `ChildExt::checked_wait_with_output` on the wrapped `Child`
73    pub fn wait_with_output(self) -> Result<Output, Error> {
74        self.child.checked_wait_with_output()
75    }
76}
77
78/// A wrapper around `std::process::Command`
79/// which hides the original `status`/`output` methods
80/// and replaces them with the versions from `checked_command::CommandExt`
81#[derive(Debug)]
82pub struct CheckedCommand {
83    command: Command,
84}
85
86impl From<Command> for CheckedCommand {
87    fn from(command: Command) -> CheckedCommand {
88        CheckedCommand { command }
89    }
90}
91
92impl CheckedCommand {
93    /// return a mutable reference to the wrapped `std::process::Command`
94    /// this can be useful if the cammand has to be passed to a function
95    /// or to access a extension trait for `std::process::Command`
96    pub fn as_std_command(&mut self) -> &mut Command {
97        &mut self.command
98    }
99
100    /// converts this Command into a `std::process::Command`
101    /// (basically unwrapping it).
102    ///
103    /// Note that this function was intentionally provided instead
104    /// of `Into<Command>` as the main reason for this wrapper is
105    /// to prevent forgetting to check the exit status. As such it
106    /// will forward all calls except `spawn`,`status` and `output`
107    /// which normally tend to be the last function ever called on
108    /// a command instances. Therefore converting a `CheckedCommand`
109    /// to a `Command` is quite likely a bug. (Through there are some
110    /// cases where it makes sense).
111    pub fn into_std_command(self) -> Command {
112        self.command
113    }
114
115    /// creates a new `CheckedCommand`
116    /// see `std::process:Command::new` for more details
117    pub fn new<S: AsRef<OsStr>>(program: S) -> CheckedCommand {
118        CheckedCommand {
119            command: Command::new(program),
120        }
121    }
122
123    /// calls `std::process::Command::arg`
124    pub fn arg<S: AsRef<OsStr>>(&mut self, arg: S) -> &mut CheckedCommand {
125        self.command.arg(arg);
126        self
127    }
128
129    /// calls `std::process::Command::args`
130    pub fn args<I, S>(&mut self, args: I) -> &mut CheckedCommand
131    where
132        I: IntoIterator<Item = S>,
133        S: AsRef<OsStr>,
134    {
135        self.command.args(args);
136        self
137    }
138
139    /// calls `std::process::Command::env`
140    pub fn env<K, V>(&mut self, key: K, val: V) -> &mut CheckedCommand
141    where
142        K: AsRef<OsStr>,
143        V: AsRef<OsStr>,
144    {
145        self.command.env(key, val);
146        self
147    }
148
149    /// calls `std::process::Command::envs`
150    #[cfg(feature = "command_envs")]
151    pub fn envs<I, K, V>(&mut self, vars: I) -> &mut CheckedCommand
152    where
153        I: IntoIterator<Item = (K, V)>,
154        K: AsRef<OsStr>,
155        V: AsRef<OsStr>,
156    {
157        self.command.envs(vars);
158        self
159    }
160
161    /// calls `std::process::Command::env_remove`
162    pub fn env_remove<K: AsRef<OsStr>>(&mut self, key: K) -> &mut CheckedCommand {
163        self.command.env_remove(key);
164        self
165    }
166
167    /// calls `std::process::Command::env_clear`
168    pub fn env_clear(&mut self) -> &mut CheckedCommand {
169        self.command.env_clear();
170        self
171    }
172
173    /// calls `std::process::Command::current_dir`
174    pub fn current_dir<P: AsRef<Path>>(&mut self, dir: P) -> &mut CheckedCommand {
175        self.command.current_dir(dir);
176        self
177    }
178
179    /// calls `std::process::Command::stdin`
180    pub fn stdin(&mut self, cfg: Stdio) -> &mut CheckedCommand {
181        self.command.stdin(cfg);
182        self
183    }
184
185    /// calls `std::process::Command::stdout`
186    pub fn stdout(&mut self, cfg: Stdio) -> &mut CheckedCommand {
187        self.command.stdout(cfg);
188        self
189    }
190
191    /// calls `std::process::Command::stderr`
192    pub fn stderr(&mut self, cfg: Stdio) -> &mut CheckedCommand {
193        self.command.stderr(cfg);
194        self
195    }
196
197    /// calls `std::process::Command::spawn` and converts the
198    /// `Child` into a `CheckedChild`
199    pub fn spawn(&mut self) -> Result<CheckedChild, IoError> {
200        self.command.spawn().map(Into::into)
201    }
202
203    /// calls `CommandExt::checked_output` on the wrapped `Command`
204    pub fn output(&mut self) -> Result<Output, Error> {
205        self.command.checked_output()
206    }
207
208    /// calls `CommandExt::checked_status` on the wrapped `Command`
209    pub fn status(&mut self) -> Result<(), Error> {
210        self.command.checked_status()
211    }
212}