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