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
+
1
7
use toml;
2
8
use serde:: Serialize ;
3
9
4
10
use std:: collections:: BTreeMap ;
5
11
use std:: env;
6
12
use std:: fs;
7
- use std:: io:: { self , Read , Write } ;
13
+ use std:: io:: { self , Read , Write , BufRead , BufReader } ;
8
14
use std:: path:: { PathBuf , Path } ;
9
15
use std:: process:: { Command , Stdio } ;
16
+ use std:: collections:: HashMap ;
10
17
11
18
static HOSTS : & [ & str ] = & [
12
19
"aarch64-unknown-linux-gnu" ,
@@ -146,6 +153,9 @@ static MINGW: &[&str] = &[
146
153
"x86_64-pc-windows-gnu" ,
147
154
] ;
148
155
156
+ static TOOLSTATE : & str =
157
+ "https://raw.githubusercontent.com/rust-lang-nursery/rust-toolstate/master/history/linux.tsv" ;
158
+
149
159
#[ derive( Serialize ) ]
150
160
#[ serde( rename_all = "kebab-case" ) ]
151
161
struct Manifest {
@@ -270,6 +280,7 @@ fn main() {
270
280
// Do not ask for a passphrase while manually testing
271
281
let mut passphrase = String :: new ( ) ;
272
282
if should_sign {
283
+ // `x.py` passes the passphrase via stdin.
273
284
t ! ( io:: stdin( ) . read_to_string( & mut passphrase) ) ;
274
285
}
275
286
@@ -353,6 +364,7 @@ impl Builder {
353
364
self . lldb_git_commit_hash = self . git_commit_hash ( "lldb" , "x86_64-unknown-linux-gnu" ) ;
354
365
self . miri_git_commit_hash = self . git_commit_hash ( "miri" , "x86_64-unknown-linux-gnu" ) ;
355
366
367
+ self . check_toolstate ( ) ;
356
368
self . digest_and_sign ( ) ;
357
369
let manifest = self . build_manifest ( ) ;
358
370
self . write_channel_files ( & self . rust_release , & manifest) ;
@@ -362,6 +374,37 @@ impl Builder {
362
374
}
363
375
}
364
376
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`.
365
408
fn digest_and_sign ( & mut self ) {
366
409
for file in t ! ( self . input. read_dir( ) ) . map ( |e| t ! ( e) . path ( ) ) {
367
410
let filename = file. file_name ( ) . unwrap ( ) . to_str ( ) . unwrap ( ) ;
@@ -532,19 +575,20 @@ impl Builder {
532
575
. as_ref ( )
533
576
. cloned ( )
534
577
. map ( |version| ( version, true ) )
535
- . unwrap_or_default ( ) ;
578
+ . unwrap_or_default ( ) ; // `is_present` defaults to `false` here.
536
579
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.
539
581
if pkgname == "miri-preview" && self . rust_release != "nightly" {
540
- is_present = false ; // ignore it
582
+ is_present = false ; // Pretend the component is entirely missing.
541
583
}
542
584
543
585
let targets = targets. iter ( ) . map ( |name| {
544
586
if is_present {
587
+ // The component generally exists, but it might still be missing for this target.
545
588
let filename = self . filename ( pkgname, name) ;
546
589
let digest = match self . digests . remove ( & filename) {
547
590
Some ( digest) => digest,
591
+ // This component does not exist for this target -- skip it.
548
592
None => return ( name. to_string ( ) , Target :: unavailable ( ) ) ,
549
593
} ;
550
594
let xz_filename = filename. replace ( ".tar.gz" , ".tar.xz" ) ;
0 commit comments