33
44use std:: {
55 ffi:: OsString ,
6- fmt, io,
6+ fmt,
7+ io:: { self , BufWriter , Write } ,
78 marker:: PhantomData ,
89 path:: PathBuf ,
910 process:: { ChildStderr , ChildStdout , Command , Stdio } ,
1011} ;
1112
1213use crossbeam_channel:: Sender ;
14+ use paths:: Utf8PathBuf ;
1315use process_wrap:: std:: { StdChildWrapper , StdCommandWrap } ;
1416use stdx:: process:: streaming_output;
1517
@@ -40,7 +42,7 @@ impl<T: Sized + Send + 'static> CargoActor<T> {
4042}
4143
4244impl < T : Sized + Send + ' static > CargoActor < T > {
43- fn run ( self ) -> io:: Result < ( bool , String ) > {
45+ fn run ( self , outfile : Option < Utf8PathBuf > ) -> io:: Result < ( bool , String ) > {
4446 // We manually read a line at a time, instead of using serde's
4547 // stream deserializers, because the deserializer cannot recover
4648 // from an error, resulting in it getting stuck, because we try to
@@ -50,6 +52,15 @@ impl<T: Sized + Send + 'static> CargoActor<T> {
5052 // simply skip a line if it doesn't parse, which just ignores any
5153 // erroneous output.
5254
55+ let mut stdout = outfile. as_ref ( ) . and_then ( |path| {
56+ _ = std:: fs:: create_dir_all ( path) ;
57+ Some ( BufWriter :: new ( std:: fs:: File :: create ( path. join ( "stdout" ) ) . ok ( ) ?) )
58+ } ) ;
59+ let mut stderr = outfile. as_ref ( ) . and_then ( |path| {
60+ _ = std:: fs:: create_dir_all ( path) ;
61+ Some ( BufWriter :: new ( std:: fs:: File :: create ( path. join ( "stderr" ) ) . ok ( ) ?) )
62+ } ) ;
63+
5364 let mut stdout_errors = String :: new ( ) ;
5465 let mut stderr_errors = String :: new ( ) ;
5566 let mut read_at_least_one_stdout_message = false ;
@@ -67,11 +78,19 @@ impl<T: Sized + Send + 'static> CargoActor<T> {
6778 self . stdout ,
6879 self . stderr ,
6980 & mut |line| {
81+ if let Some ( stdout) = & mut stdout {
82+ _ = stdout. write_all ( line. as_bytes ( ) ) ;
83+ _ = stdout. write_all ( b"\n " ) ;
84+ }
7085 if process_line ( line, & mut stdout_errors) {
7186 read_at_least_one_stdout_message = true ;
7287 }
7388 } ,
7489 & mut |line| {
90+ if let Some ( stderr) = & mut stderr {
91+ _ = stderr. write_all ( line. as_bytes ( ) ) ;
92+ _ = stderr. write_all ( b"\n " ) ;
93+ }
7594 if process_line ( line, & mut stderr_errors) {
7695 read_at_least_one_stderr_message = true ;
7796 }
@@ -130,6 +149,7 @@ impl<T: Sized + Send + 'static> CommandHandle<T> {
130149 mut command : Command ,
131150 parser : impl CargoParser < T > ,
132151 sender : Sender < T > ,
152+ out_file : Option < Utf8PathBuf > ,
133153 ) -> std:: io:: Result < Self > {
134154 command. stdout ( Stdio :: piped ( ) ) . stderr ( Stdio :: piped ( ) ) . stdin ( Stdio :: null ( ) ) ;
135155
@@ -150,7 +170,7 @@ impl<T: Sized + Send + 'static> CommandHandle<T> {
150170 let actor = CargoActor :: < T > :: new ( parser, sender, stdout, stderr) ;
151171 let thread =
152172 stdx:: thread:: Builder :: new ( stdx:: thread:: ThreadIntent :: Worker , "CommandHandle" )
153- . spawn ( move || actor. run ( ) )
173+ . spawn ( move || actor. run ( out_file ) )
154174 . expect ( "failed to spawn thread" ) ;
155175 Ok ( CommandHandle { program, arguments, current_dir, child, thread, _phantom : PhantomData } )
156176 }
0 commit comments