@@ -134,6 +134,33 @@ impl CommandChild {
134
134
}
135
135
}
136
136
137
+ /// Describes the result of a process after it has terminated.
138
+ pub struct ExitStatus {
139
+ code : Option < i32 > ,
140
+ }
141
+
142
+ impl ExitStatus {
143
+ /// Returns the exit code of the process, if any.
144
+ pub fn code ( & self ) -> Option < i32 > {
145
+ self . code
146
+ }
147
+
148
+ /// Was termination successful? Signal termination is not considered a success, and success is defined as a zero exit status.
149
+ pub fn success ( & self ) -> bool {
150
+ self . code == Some ( 0 )
151
+ }
152
+ }
153
+
154
+ /// The output of a finished process.
155
+ pub struct Output {
156
+ /// The status (exit code) of the process.
157
+ pub status : ExitStatus ,
158
+ /// The data that the process wrote to stdout.
159
+ pub stdout : String ,
160
+ /// The data that the process wrote to stderr.
161
+ pub stderr : String ,
162
+ }
163
+
137
164
#[ cfg( not( windows) ) ]
138
165
fn relative_command_path ( command : String ) -> crate :: Result < String > {
139
166
match std:: env:: current_exe ( ) ?. parent ( ) {
@@ -281,6 +308,57 @@ impl Command {
281
308
} ,
282
309
) )
283
310
}
311
+
312
+ /// Executes a command as a child process, waiting for it to finish and collecting its exit status.
313
+ /// Stdin, stdout and stderr are ignored.
314
+ pub fn status ( self ) -> crate :: api:: Result < ExitStatus > {
315
+ let ( mut rx, _child) = self . spawn ( ) ?;
316
+ let code = crate :: async_runtime:: block_on ( async move {
317
+ let mut code = None ;
318
+ while let Some ( event) = rx. recv ( ) . await {
319
+ if let CommandEvent :: Terminated ( payload) = event {
320
+ code = payload. code ;
321
+ }
322
+ }
323
+ code
324
+ } ) ;
325
+ Ok ( ExitStatus { code } )
326
+ }
327
+
328
+ /// Executes the command as a child process, waiting for it to finish and collecting all of its output.
329
+ /// Stdin is ignored.
330
+ pub fn output ( self ) -> crate :: api:: Result < Output > {
331
+ let ( mut rx, _child) = self . spawn ( ) ?;
332
+
333
+ let output = crate :: async_runtime:: block_on ( async move {
334
+ let mut code = None ;
335
+ let mut stdout = String :: new ( ) ;
336
+ let mut stderr = String :: new ( ) ;
337
+ while let Some ( event) = rx. recv ( ) . await {
338
+ match event {
339
+ CommandEvent :: Terminated ( payload) => {
340
+ code = payload. code ;
341
+ }
342
+ CommandEvent :: Stdout ( line) => {
343
+ stdout. push_str ( line. as_str ( ) ) ;
344
+ stdout. push ( '\n' ) ;
345
+ }
346
+ CommandEvent :: Stderr ( line) => {
347
+ stderr. push_str ( line. as_str ( ) ) ;
348
+ stderr. push ( '\n' ) ;
349
+ }
350
+ CommandEvent :: Error ( _) => { }
351
+ }
352
+ }
353
+ Output {
354
+ status : ExitStatus { code } ,
355
+ stdout,
356
+ stderr,
357
+ }
358
+ } ) ;
359
+
360
+ Ok ( output)
361
+ }
284
362
}
285
363
286
364
// tests for the commands functions.
0 commit comments