@@ -13,7 +13,9 @@ use std::fmt::{Debug, Formatter};
1313use std:: hash:: Hash ;
1414use std:: panic:: Location ;
1515use std:: path:: Path ;
16- use std:: process:: { Child , Command , CommandArgs , CommandEnvs , ExitStatus , Output , Stdio } ;
16+ use std:: process:: {
17+ Child , ChildStderr , ChildStdout , Command , CommandArgs , CommandEnvs , ExitStatus , Output , Stdio ,
18+ } ;
1719use std:: sync:: { Arc , Mutex } ;
1820
1921use build_helper:: ci:: CiEnv ;
@@ -449,6 +451,12 @@ enum CommandState<'a> {
449451 } ,
450452}
451453
454+ pub struct CommandStreaming {
455+ child : Child ,
456+ pub stdout : Option < ChildStdout > ,
457+ pub stderr : Option < ChildStderr > ,
458+ }
459+
452460#[ must_use]
453461pub struct DeferredCommand < ' a > {
454462 state : CommandState < ' a > ,
@@ -625,7 +633,48 @@ impl AsRef<ExecutionContext> for ExecutionContext {
625633 }
626634}
627635
636+ impl CommandStreaming {
637+ pub fn wait ( mut self ) -> Result < ExitStatus , std:: io:: Error > {
638+ self . child . wait ( )
639+ }
640+
641+ pub fn wait_with_output ( self ) -> Result < Output , std:: io:: Error > {
642+ self . child . wait_with_output ( )
643+ }
644+ }
645+
628646impl < ' a > DeferredCommand < ' a > {
647+ pub fn stream ( self ) -> Option < CommandStreaming > {
648+ if let CommandState :: Deferred {
649+ process,
650+ command,
651+ stdout : _,
652+ stderr : _,
653+ executed_at : _,
654+ cache_key : _,
655+ } = self . state
656+ {
657+ command. mark_as_executed ( ) ;
658+
659+ let child = match process {
660+ Some ( child) => child,
661+ None => {
662+ return None ;
663+ }
664+ } ;
665+
666+ let mut child = match child {
667+ Ok ( child) => child,
668+ Err ( e) => panic ! ( "failed to execute command: {:?}\n ERROR: {e}" , command) ,
669+ } ;
670+
671+ let stdout = child. stdout . take ( ) ;
672+ let stderr = child. stderr . take ( ) ;
673+ return Some ( CommandStreaming { child, stdout, stderr } ) ;
674+ }
675+ None
676+ }
677+
629678 pub fn wait_for_output ( self , exec_ctx : impl AsRef < ExecutionContext > ) -> CommandOutput {
630679 match self . state {
631680 CommandState :: Cached ( output) => output,
0 commit comments