11use std:: io:: Read ;
2+ use std:: io:: Write ;
23use std:: ops:: DerefMut ;
34use std:: process:: Child ;
45use std:: process:: Command ;
@@ -315,6 +316,11 @@ impl State {
315316
316317 cmd. current_dir ( self . repo . workdir ( ) . ok_or ( Error :: NoRepoWorkdir ) ?) ;
317318
319+ self . current_cmd_log . push_cmd_with_output ( & cmd, "\n " . into ( ) ) ;
320+ self . update ( term, & [ GituEvent :: Refresh ] ) ?;
321+
322+ eprint ! ( "\r " ) ;
323+
318324 // Redirect stderr so we can capture it via `Child::wait_with_output()`
319325 cmd. stderr ( Stdio :: piped ( ) ) ;
320326
@@ -326,13 +332,27 @@ impl State {
326332 // state), the cursor may be missing in $EDITOR.
327333 term. show_cursor ( ) . map_err ( Error :: Term ) ?;
328334
329- let child = cmd. spawn ( ) . map_err ( Error :: SpawnCmd ) ?;
335+ let mut child = cmd. spawn ( ) . map_err ( Error :: SpawnCmd ) ?;
336+
337+ // Drop stdin as `Child::wait_with_output` would
338+ drop ( child. stdin . take ( ) ) ;
339+
340+ let ( mut stdout, mut stderr) = ( Vec :: new ( ) , Vec :: new ( ) ) ;
330341
331- let out = child. wait_with_output ( ) . map_err ( Error :: CouldntAwaitCmd ) ?;
332- let out_utf8 = String :: from_utf8 ( strip_ansi_escapes:: strip ( out. stderr . clone ( ) ) )
342+ tee ( child. stdout . as_mut ( ) , & mut [ & mut stdout] ) . map_err ( Error :: Term ) ?;
343+
344+ tee (
345+ child. stderr . as_mut ( ) ,
346+ & mut [ & mut std:: io:: stderr ( ) , & mut stderr] ,
347+ )
348+ . map_err ( Error :: Term ) ?;
349+
350+ let status = child. wait ( ) . map_err ( Error :: CouldntAwaitCmd ) ?;
351+ let out_utf8 = String :: from_utf8 ( strip_ansi_escapes:: strip ( stderr. clone ( ) ) )
333352 . expect ( "Error turning command output to String" )
334353 . into ( ) ;
335354
355+ self . current_cmd_log . clear ( ) ;
336356 self . current_cmd_log . push_cmd_with_output ( & cmd, out_utf8) ;
337357
338358 // restore the raw mode
@@ -347,7 +367,7 @@ impl State {
347367 term. clear ( ) . map_err ( Error :: Term ) ?;
348368 self . screen_mut ( ) . update ( ) ?;
349369
350- if !out . status . success ( ) {
370+ if !status. success ( ) {
351371 return Err ( Error :: CmdBadExit (
352372 format ! (
353373 "{} {}" ,
@@ -356,7 +376,7 @@ impl State {
356376 . map( |arg| arg. to_string_lossy( ) )
357377 . collect:: <String >( )
358378 ) ,
359- out . status . code ( ) ,
379+ status. code ( ) ,
360380 ) ) ;
361381 }
362382
@@ -376,6 +396,28 @@ impl State {
376396 }
377397}
378398
399+ fn tee ( maybe_input : Option < & mut impl Read > , outputs : & mut [ & mut dyn Write ] ) -> std:: io:: Result < ( ) > {
400+ let Some ( input) = maybe_input else {
401+ return Ok ( ( ) ) ;
402+ } ;
403+
404+ let mut buf = [ 0u8 ; 1024 ] ;
405+
406+ loop {
407+ let num_read = input. read ( & mut buf) ?;
408+ if num_read == 0 {
409+ break ;
410+ }
411+
412+ let buf = & buf[ ..num_read] ;
413+ for output in & mut * outputs {
414+ output. write_all ( buf) ?;
415+ }
416+ }
417+
418+ Ok ( ( ) )
419+ }
420+
379421pub ( crate ) fn root_menu ( config : & Config ) -> Option < Menu > {
380422 if config. general . always_show_help . enabled {
381423 Some ( Menu :: Help )
0 commit comments