@@ -8,17 +8,15 @@ use cargo::core::{Package, PackageId, Source, SourceId, Workspace};
88use cargo:: sources:: RegistrySource ;
99use curl:: easy:: Easy ;
1010use log:: debug;
11- use rand:: Rng ;
1211use rustc_session:: getopts;
1312use serde:: Deserialize ;
1413use std:: collections:: HashSet ;
1514use std:: {
16- env,
17- fs:: File ,
18- io:: BufReader ,
15+ env, io,
1916 io:: Write ,
2017 path:: { Path , PathBuf } ,
2118 process:: { Command , Stdio } ,
19+ sync:: { Arc , RwLock } ,
2220} ;
2321
2422pub type Result < T > = cargo:: util:: CargoResult < T > ;
@@ -503,33 +501,27 @@ impl<'a> WorkInfo<'a> {
503501 format ! ( "-C metadata={}" , if current { "new" } else { "old" } ) ,
504502 ) ;
505503
506- let mut outdir = env:: temp_dir ( ) ;
507- // The filename is randomized to avoid clashes when multiple cargo-semver instances are running.
508- outdir. push ( & format ! (
509- "cargo_semver_{}_{}_{}" ,
510- name,
511- current,
512- rand:: thread_rng( ) . gen :: <u32 >( )
513- ) ) ;
514-
515- // redirection gang
516- let outfile = File :: create ( & outdir) ?;
504+ // Capture build plan from a separate Cargo invocation
505+ let output = VecWrite ( Arc :: new ( RwLock :: new ( Vec :: new ( ) ) ) ) ;
517506
518- let mut file_write = cargo:: core:: Shell :: from_write ( Box :: new ( outfile ) ) ;
507+ let mut file_write = cargo:: core:: Shell :: from_write ( Box :: new ( output . clone ( ) ) ) ;
519508 file_write. set_verbosity ( cargo:: core:: Verbosity :: Quiet ) ;
509+
520510 let old_shell = std:: mem:: replace ( & mut * config. shell ( ) , file_write) ;
521511
522512 cargo:: ops:: compile ( & self . workspace , & opts) ?;
523513
524514 let _ = std:: mem:: replace ( & mut * config. shell ( ) , old_shell) ;
515+ let plan_output = output. read ( ) ?;
525516
526517 // actually compile things now
527518 opts. build_config . build_plan = false ;
528519
529520 let compilation = cargo:: ops:: compile ( & self . workspace , & opts) ?;
530521 env:: remove_var ( "RUSTFLAGS" ) ;
531522
532- let build_plan: BuildPlan = serde_json:: from_reader ( BufReader :: new ( File :: open ( & outdir) ?) ) ?;
523+ let build_plan: BuildPlan = serde_json:: from_slice ( & plan_output)
524+ . map_err ( |_| anyhow:: anyhow!( "Can't read build plan" ) ) ?;
533525
534526 // TODO: handle multiple outputs gracefully
535527 for i in & build_plan. invocations {
@@ -572,3 +564,30 @@ pub fn find_on_crates_io(crate_name: &str) -> Result<crates_io::Crate> {
572564 } )
573565 } )
574566}
567+
568+ /// Thread-safe byte buffer that implements `io::Write`.
569+ #[ derive( Clone ) ]
570+ struct VecWrite ( Arc < RwLock < Vec < u8 > > > ) ;
571+
572+ impl VecWrite {
573+ pub fn read ( & self ) -> io:: Result < std:: sync:: RwLockReadGuard < ' _ , Vec < u8 > > > {
574+ self . 0
575+ . read ( )
576+ . map_err ( |_| io:: Error :: new ( io:: ErrorKind :: Other , "lock poison" ) )
577+ }
578+ pub fn write ( & self ) -> io:: Result < std:: sync:: RwLockWriteGuard < ' _ , Vec < u8 > > > {
579+ self . 0
580+ . write ( )
581+ . map_err ( |_| io:: Error :: new ( io:: ErrorKind :: Other , "lock poison" ) )
582+ }
583+ }
584+
585+ impl io:: Write for VecWrite {
586+ fn write ( & mut self , data : & [ u8 ] ) -> io:: Result < usize > {
587+ let mut lock = Self :: write ( self ) ?;
588+ io:: Write :: write ( & mut * lock, data)
589+ }
590+ fn flush ( & mut self ) -> io:: Result < ( ) > {
591+ Ok ( ( ) )
592+ }
593+ }
0 commit comments