@@ -439,6 +439,19 @@ pub fn cargo_exe() -> PathBuf {
439439 *
440440 */
441441
442+ /// This is the raw output from the process.
443+ ///
444+ /// This is similar to `std::process::Output`, however the `status` is
445+ /// translated to the raw `code`. This is necessary because `ProcessError`
446+ /// does not have access to the raw `ExitStatus` because `ProcessError` needs
447+ /// to be serializable (for the Rustc cache), and `ExitStatus` does not
448+ /// provide a constructor.
449+ pub struct RawOutput {
450+ pub code : Option < i32 > ,
451+ pub stdout : Vec < u8 > ,
452+ pub stderr : Vec < u8 > ,
453+ }
454+
442455#[ must_use]
443456#[ derive( Clone ) ]
444457pub struct Execs {
@@ -728,6 +741,25 @@ impl Execs {
728741 }
729742 }
730743
744+ /// Runs the process, checks the expected output, and returns the first
745+ /// JSON object on stdout.
746+ #[ track_caller]
747+ pub fn run_json ( & mut self ) -> serde_json:: Value {
748+ self . ran = true ;
749+ let p = ( & self . process_builder ) . clone ( ) . unwrap ( ) ;
750+ match self . match_process ( & p) {
751+ Err ( e) => panic ! ( "\n {}" , e) ,
752+ Ok ( output) => serde_json:: from_slice ( & output. stdout ) . unwrap_or_else ( |e| {
753+ panic ! (
754+ "\n failed to parse JSON: {}\n \
755+ output was:\n {}\n ",
756+ e,
757+ String :: from_utf8_lossy( & output. stdout)
758+ ) ;
759+ } ) ,
760+ }
761+ }
762+
731763 #[ track_caller]
732764 pub fn run_output ( & mut self , output : & Output ) {
733765 self . ran = true ;
@@ -763,7 +795,7 @@ impl Execs {
763795 }
764796 }
765797
766- fn match_process ( & self , process : & ProcessBuilder ) -> Result < ( ) > {
798+ fn match_process ( & self , process : & ProcessBuilder ) -> Result < RawOutput > {
767799 println ! ( "running {}" , process) ;
768800 let res = if self . stream_output {
769801 if is_ci ( ) {
@@ -785,7 +817,14 @@ impl Execs {
785817 } ;
786818
787819 match res {
788- Ok ( out) => self . match_output ( & out) ,
820+ Ok ( out) => {
821+ self . match_output ( & out) ?;
822+ return Ok ( RawOutput {
823+ stdout : out. stdout ,
824+ stderr : out. stderr ,
825+ code : out. status . code ( ) ,
826+ } ) ;
827+ }
789828 Err ( e) => {
790829 if let Some ( ProcessError {
791830 stdout : Some ( stdout) ,
@@ -794,10 +833,14 @@ impl Execs {
794833 ..
795834 } ) = e. downcast_ref :: < ProcessError > ( )
796835 {
797- return self
798- . match_status ( * code, stdout, stderr)
836+ self . match_status ( * code, stdout, stderr)
799837 . and ( self . match_stdout ( stdout, stderr) )
800- . and ( self . match_stderr ( stdout, stderr) ) ;
838+ . and ( self . match_stderr ( stdout, stderr) ) ?;
839+ return Ok ( RawOutput {
840+ stdout : stdout. to_vec ( ) ,
841+ stderr : stderr. to_vec ( ) ,
842+ code : * code,
843+ } ) ;
801844 }
802845 bail ! ( "could not exec process {}: {:?}" , process, e)
803846 }
0 commit comments