@@ -129,3 +129,127 @@ pub fn set_host_rpath(cmd: &mut Command) {
129
129
env:: join_paths ( paths. iter ( ) ) . unwrap ( )
130
130
} ) ;
131
131
}
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