@@ -13,7 +13,9 @@ use std::fmt::{Debug, Formatter};
13
13
use std:: hash:: Hash ;
14
14
use std:: panic:: Location ;
15
15
use 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
+ } ;
17
19
use std:: sync:: { Arc , Mutex } ;
18
20
19
21
use build_helper:: ci:: CiEnv ;
@@ -209,15 +211,22 @@ impl<'a> BootstrapCommand {
209
211
exec_ctx. as_ref ( ) . start ( self , OutputMode :: Capture , OutputMode :: Print )
210
212
}
211
213
212
- /// Provides access to the stdlib Command inside.
213
- /// FIXME: This function should be eventually removed from bootstrap.
214
- pub fn as_command_mut ( & mut self ) -> & mut Command {
215
- // We proactively mark this command as executed since we can't be certain how the returned
216
- // command will be handled. Caching must also be avoided here, as the inner command could be
217
- // modified externally without us being aware.
218
- self . mark_as_executed ( ) ;
219
- self . do_not_cache ( ) ;
220
- & mut self . command
214
+ /// Spawn the command in background, while capturing and returns a handle to stream the output.
215
+ #[ track_caller]
216
+ pub fn stream_capture (
217
+ & ' a mut self ,
218
+ exec_ctx : impl AsRef < ExecutionContext > ,
219
+ ) -> Option < StreamingCommand > {
220
+ exec_ctx. as_ref ( ) . stream ( self , OutputMode :: Capture , OutputMode :: Capture )
221
+ }
222
+
223
+ /// Spawn the command in background, while capturing and returning stdout, and printing stderr.
224
+ #[ track_caller]
225
+ pub fn stream_capture_stdout (
226
+ & ' a mut self ,
227
+ exec_ctx : impl AsRef < ExecutionContext > ,
228
+ ) -> Option < StreamingCommand > {
229
+ exec_ctx. as_ref ( ) . stream ( self , OutputMode :: Capture , OutputMode :: Print )
221
230
}
222
231
223
232
/// Mark the command as being executed, disarming the drop bomb.
@@ -449,6 +458,12 @@ enum CommandState<'a> {
449
458
} ,
450
459
}
451
460
461
+ pub struct StreamingCommand {
462
+ child : Child ,
463
+ pub stdout : Option < ChildStdout > ,
464
+ pub stderr : Option < ChildStderr > ,
465
+ }
466
+
452
467
#[ must_use]
453
468
pub struct DeferredCommand < ' a > {
454
469
state : CommandState < ' a > ,
@@ -617,6 +632,39 @@ impl ExecutionContext {
617
632
}
618
633
exit ! ( 1 ) ;
619
634
}
635
+
636
+ <<<<<<< HEAD
637
+ pub fn stream< ' a > (
638
+ =======
639
+ /// Spawns the command with configured stdout and stderr handling.
640
+ ///
641
+ /// Returns `None` if in dry-run mode and the command is not allowed to run.
642
+ ///
643
+ /// Panics if the command fails to spawn.
644
+ pub fn stream (
645
+ >>>>>>> c2e83361cec ( add comment to exec)
646
+ & self ,
647
+ command : & ' a mut BootstrapCommand ,
648
+ stdout : OutputMode ,
649
+ stderr : OutputMode ,
650
+ ) -> Option < StreamingCommand > {
651
+ command. mark_as_executed ( ) ;
652
+ if !command. run_in_dry_run && self . dry_run ( ) {
653
+ return None ;
654
+ }
655
+ let cmd = & mut command. command ;
656
+ cmd. stdout ( stdout. stdio ( ) ) ;
657
+ cmd. stderr ( stderr. stdio ( ) ) ;
658
+ let child = cmd. spawn ( ) ;
659
+ let mut child = match child {
660
+ Ok ( child) => child,
661
+ Err ( e) => panic ! ( "failed to execute command: {cmd:?}\n ERROR: {e}" ) ,
662
+ } ;
663
+
664
+ let stdout = child. stdout . take ( ) ;
665
+ let stderr = child. stderr . take ( ) ;
666
+ return Some ( StreamingCommand { child, stdout, stderr } ) ;
667
+ }
620
668
}
621
669
622
670
impl AsRef < ExecutionContext > for ExecutionContext {
@@ -625,6 +673,12 @@ impl AsRef<ExecutionContext> for ExecutionContext {
625
673
}
626
674
}
627
675
676
+ impl StreamingCommand {
677
+ pub fn wait ( mut self ) -> Result < ExitStatus , std:: io:: Error > {
678
+ self . child . wait ( )
679
+ }
680
+ }
681
+
628
682
impl < ' a > DeferredCommand < ' a > {
629
683
pub fn wait_for_output ( self , exec_ctx : impl AsRef < ExecutionContext > ) -> CommandOutput {
630
684
match self . state {
0 commit comments