1+ //! Build a dist manifest, hash and sign everything.
2+ //! This gets called by `promote-release`
3+ //! (https://github.com/rust-lang/rust-central-station/tree/master/promote-release)
4+ //! via `x.py dist hash-and-sign`; the cmdline arguments are set up
5+ //! by rustbuild (in `src/bootstrap/dist.rs`).
6+
17use toml;
28use serde:: Serialize ;
39
410use std:: collections:: BTreeMap ;
511use std:: env;
612use std:: fs;
7- use std:: io:: { self , Read , Write } ;
13+ use std:: io:: { self , Read , Write , BufRead , BufReader } ;
814use std:: path:: { PathBuf , Path } ;
915use std:: process:: { Command , Stdio } ;
16+ use std:: collections:: HashMap ;
1017
1118static HOSTS : & [ & str ] = & [
1219 "aarch64-unknown-linux-gnu" ,
@@ -146,6 +153,9 @@ static MINGW: &[&str] = &[
146153 "x86_64-pc-windows-gnu" ,
147154] ;
148155
156+ static TOOLSTATE : & str =
157+ "https://raw.githubusercontent.com/rust-lang-nursery/rust-toolstate/master/history/linux.tsv" ;
158+
149159#[ derive( Serialize ) ]
150160#[ serde( rename_all = "kebab-case" ) ]
151161struct Manifest {
@@ -270,6 +280,7 @@ fn main() {
270280 // Do not ask for a passphrase while manually testing
271281 let mut passphrase = String :: new ( ) ;
272282 if should_sign {
283+ // `x.py` passes the passphrase via stdin.
273284 t ! ( io:: stdin( ) . read_to_string( & mut passphrase) ) ;
274285 }
275286
@@ -353,6 +364,7 @@ impl Builder {
353364 self . lldb_git_commit_hash = self . git_commit_hash ( "lldb" , "x86_64-unknown-linux-gnu" ) ;
354365 self . miri_git_commit_hash = self . git_commit_hash ( "miri" , "x86_64-unknown-linux-gnu" ) ;
355366
367+ self . check_toolstate ( ) ;
356368 self . digest_and_sign ( ) ;
357369 let manifest = self . build_manifest ( ) ;
358370 self . write_channel_files ( & self . rust_release , & manifest) ;
@@ -362,6 +374,37 @@ impl Builder {
362374 }
363375 }
364376
377+ /// If a tool does not pass its tests, don't ship it.
378+ /// Right now, we do this only for Miri.
379+ fn check_toolstate ( & mut self ) {
380+ // Get the toolstate for this rust revision.
381+ let rev = self . rust_git_commit_hash . as_ref ( ) . expect ( "failed to determine rust git hash" ) ;
382+ let toolstates = reqwest:: get ( TOOLSTATE ) . expect ( "failed to get toolstates" ) ;
383+ let toolstates = BufReader :: new ( toolstates) ;
384+ let toolstate = toolstates. lines ( )
385+ . find_map ( |line| {
386+ let line = line. expect ( "failed to read toolstate lines" ) ;
387+ let mut pieces = line. splitn ( 2 , '\t' ) ;
388+ let commit = pieces. next ( ) . expect ( "malformed toolstate line" ) ;
389+ if commit != rev {
390+ // Not the right commit.
391+ return None ;
392+ }
393+ // Return the 2nd piece, the JSON.
394+ Some ( pieces. next ( ) . expect ( "malformed toolstate line" ) . to_owned ( ) )
395+ } )
396+ . expect ( "failed to find toolstate for rust commit" ) ;
397+ let toolstate: HashMap < String , String > =
398+ serde_json:: from_str ( & toolstate) . expect ( "toolstate is malformed JSON" ) ;
399+ // Mark some tools as missing based on toolstate.
400+ if toolstate. get ( "miri" ) . map ( |s| & * s as & str ) != Some ( "test-pass" ) {
401+ println ! ( "Miri tests are not passing, removing component" ) ;
402+ self . miri_version = None ;
403+ self . miri_git_commit_hash = None ;
404+ }
405+ }
406+
407+ /// Hash all files, compute their signatures, and collect the hashes in `self.digests`.
365408 fn digest_and_sign ( & mut self ) {
366409 for file in t ! ( self . input. read_dir( ) ) . map ( |e| t ! ( e) . path ( ) ) {
367410 let filename = file. file_name ( ) . unwrap ( ) . to_str ( ) . unwrap ( ) ;
@@ -532,19 +575,20 @@ impl Builder {
532575 . as_ref ( )
533576 . cloned ( )
534577 . map ( |version| ( version, true ) )
535- . unwrap_or_default ( ) ;
578+ . unwrap_or_default ( ) ; // `is_present` defaults to `false` here.
536579
537- // miri needs to build std with xargo, which doesn't allow stable/beta:
538- // <https://github.com/japaric/xargo/pull/204#issuecomment-374888868>
580+ // Miri is nightly-only; never ship it for other trains.
539581 if pkgname == "miri-preview" && self . rust_release != "nightly" {
540- is_present = false ; // ignore it
582+ is_present = false ; // Pretend the component is entirely missing.
541583 }
542584
543585 let targets = targets. iter ( ) . map ( |name| {
544586 if is_present {
587+ // The component generally exists, but it might still be missing for this target.
545588 let filename = self . filename ( pkgname, name) ;
546589 let digest = match self . digests . remove ( & filename) {
547590 Some ( digest) => digest,
591+ // This component does not exist for this target -- skip it.
548592 None => return ( name. to_string ( ) , Target :: unavailable ( ) ) ,
549593 } ;
550594 let xz_filename = filename. replace ( ".tar.gz" , ".tar.xz" ) ;
0 commit comments