@@ -134,6 +134,33 @@ impl CommandChild {
134134 }
135135}
136136
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+
137164#[ cfg( not( windows) ) ]
138165fn relative_command_path ( command : String ) -> crate :: Result < String > {
139166 match std:: env:: current_exe ( ) ?. parent ( ) {
@@ -281,6 +308,57 @@ impl Command {
281308 } ,
282309 ) )
283310 }
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+ }
284362}
285363
286364// tests for the commands functions.
0 commit comments