@@ -129,3 +129,127 @@ pub fn set_host_rpath(cmd: &mut Command) {
129129 env:: join_paths ( paths. iter ( ) ) . unwrap ( )
130130 } ) ;
131131}
132+
133+ /// Implement common helpers for command wrappers. This assumes that the command wrapper is a struct
134+ /// containing a `cmd: Command` field. The provided helpers are:
135+ ///
136+ /// 1. Generic argument acceptors: `arg` and `args` (delegated to [`Command`]). These are intended
137+ /// to be *fallback* argument acceptors, when specific helpers don't make sense. Prefer to add
138+ /// new specific helper methods over relying on these generic argument providers.
139+ /// 2. Environment manipulation methods: `env`, `env_remove` and `env_clear`: these delegate to
140+ /// methods of the same name on [`Command`].
141+ /// 3. Output and execution: `output`, `run` and `run_fail` are provided. `output` waits for the
142+ /// command to finish running and returns the process's [`Output`]. `run` and `run_fail` are
143+ /// higher-level convenience methods which waits for the command to finish running and assert
144+ /// that the command successfully ran or failed as expected. Prefer `run` and `run_fail` when
145+ /// possible.
146+ ///
147+ /// Example usage:
148+ ///
149+ /// ```ignore (illustrative)
150+ /// struct CommandWrapper { cmd: Command }
151+ ///
152+ /// crate::impl_common_helpers!(CommandWrapper);
153+ ///
154+ /// impl CommandWrapper {
155+ /// // ... additional specific helper methods
156+ /// }
157+ /// ```
158+ ///
159+ /// [`Command`]: ::std::process::Command
160+ /// [`Output`]: ::std::process::Output
161+ macro_rules! impl_common_helpers {
162+ ( $wrapper: ident) => {
163+ impl $wrapper {
164+ /// Specify an environment variable.
165+ pub fn env<K , V >( & mut self , key: K , value: V ) -> & mut Self
166+ where
167+ K : AsRef <:: std:: ffi:: OsStr >,
168+ V : AsRef <:: std:: ffi:: OsStr >,
169+ {
170+ self . cmd. env( key, value) ;
171+ self
172+ }
173+
174+ /// Remove an environmental variable.
175+ pub fn env_remove<K >( & mut self , key: K ) -> & mut Self
176+ where
177+ K : AsRef <:: std:: ffi:: OsStr >,
178+ {
179+ self . cmd. env_remove( key) ;
180+ self
181+ }
182+
183+ /// Clear all environmental variables.
184+ pub fn env_var( & mut self ) -> & mut Self {
185+ self . cmd. env_clear( ) ;
186+ self
187+ }
188+
189+ /// Generic command argument provider. Prefer specific helper methods if possible.
190+ /// Note that for some executables, arguments might be platform specific. For C/C++
191+ /// compilers, arguments might be platform *and* compiler specific.
192+ pub fn arg<S >( & mut self , arg: S ) -> & mut Self
193+ where
194+ S : AsRef <:: std:: ffi:: OsStr >,
195+ {
196+ self . cmd. arg( arg) ;
197+ self
198+ }
199+
200+ /// Generic command arguments provider. Prefer specific helper methods if possible.
201+ /// Note that for some executables, arguments might be platform specific. For C/C++
202+ /// compilers, arguments might be platform *and* compiler specific.
203+ pub fn args<S >( & mut self , args: & [ S ] ) -> & mut Self
204+ where
205+ S : AsRef <:: std:: ffi:: OsStr >,
206+ {
207+ self . cmd. args( args) ;
208+ self
209+ }
210+
211+ /// Inspect what the underlying [`Command`][::std::process::Command] is up to the
212+ /// current construction.
213+ pub fn inspect<I >( & mut self , inspector: I ) -> & mut Self
214+ where
215+ I : FnOnce ( & :: std:: process:: Command ) ,
216+ {
217+ inspector( & self . cmd) ;
218+ self
219+ }
220+
221+ /// Get the [`Output`][::std::process::Output] of the finished process.
222+ pub fn output( & mut self ) -> :: std:: process:: Output {
223+ self . cmd. output( ) . expect( "failed to get output of finished process" )
224+ }
225+
226+ /// Run the constructed command and assert that it is successfully run.
227+ #[ track_caller]
228+ pub fn run( & mut self ) -> :: std:: process:: Output {
229+ let caller_location = :: std:: panic:: Location :: caller( ) ;
230+ let caller_line_number = caller_location. line( ) ;
231+
232+ let output = self . cmd. output( ) . unwrap( ) ;
233+ if !output. status. success( ) {
234+ handle_failed_output( & self . cmd, output, caller_line_number) ;
235+ }
236+ output
237+ }
238+
239+ /// Run the constructed command and assert that it does not successfully run.
240+ #[ track_caller]
241+ pub fn run_fail( & mut self ) -> :: std:: process:: Output {
242+ let caller_location = :: std:: panic:: Location :: caller( ) ;
243+ let caller_line_number = caller_location. line( ) ;
244+
245+ let output = self . cmd. output( ) . unwrap( ) ;
246+ if output. status. success( ) {
247+ handle_failed_output( & self . cmd, output, caller_line_number) ;
248+ }
249+ output
250+ }
251+ }
252+ } ;
253+ }
254+
255+ pub ( crate ) use impl_common_helpers;
0 commit comments