about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2019-09-14 12:57:39 +0200
committerRalf Jung <post@ralfj.de>2019-09-14 12:57:39 +0200
commit766c4a556e95b4c47f811932a710e326c263634c (patch)
tree029934c9b85beeadd3d196a110dafd8b1ff17f77
parentee83402918b25172665ba5cc09bcf8adc5f55380 (diff)
downloadrust-766c4a556e95b4c47f811932a710e326c263634c.tar.gz
rust-766c4a556e95b4c47f811932a710e326c263634c.zip
build-manifest: when Miri tests are not passing, do not add Miri component
-rw-r--r--Cargo.lock2
-rw-r--r--src/tools/build-manifest/Cargo.toml2
-rw-r--r--src/tools/build-manifest/src/main.rs54
3 files changed, 53 insertions, 5 deletions
diff --git a/Cargo.lock b/Cargo.lock
index f2eaf470658..9ec76d6c3cf 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -201,7 +201,9 @@ dependencies = [
 name = "build-manifest"
 version = "0.1.0"
 dependencies = [
+ "reqwest",
  "serde",
+ "serde_json",
  "toml",
 ]
 
diff --git a/src/tools/build-manifest/Cargo.toml b/src/tools/build-manifest/Cargo.toml
index c364479d8db..63ae445f99b 100644
--- a/src/tools/build-manifest/Cargo.toml
+++ b/src/tools/build-manifest/Cargo.toml
@@ -7,3 +7,5 @@ edition = "2018"
 [dependencies]
 toml = "0.5"
 serde = { version = "1.0", features = ["derive"] }
+serde_json = "1.0"
+reqwest = "0.9"
diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs
index 9ffa9391c82..c2d642bb136 100644
--- a/src/tools/build-manifest/src/main.rs
+++ b/src/tools/build-manifest/src/main.rs
@@ -1,12 +1,19 @@
+//! Build a dist manifest, hash and sign everything.
+//! This gets called by `promote-release`
+//! (https://github.com/rust-lang/rust-central-station/tree/master/promote-release)
+//! via `x.py dist hash-and-sign`; the cmdline arguments are set up
+//! by rustbuild (in `src/bootstrap/dist.rs`).
+
 use toml;
 use serde::Serialize;
 
 use std::collections::BTreeMap;
 use std::env;
 use std::fs;
-use std::io::{self, Read, Write};
+use std::io::{self, Read, Write, BufRead, BufReader};
 use std::path::{PathBuf, Path};
 use std::process::{Command, Stdio};
+use std::collections::HashMap;
 
 static HOSTS: &[&str] = &[
     "aarch64-unknown-linux-gnu",
@@ -146,6 +153,9 @@ static MINGW: &[&str] = &[
     "x86_64-pc-windows-gnu",
 ];
 
+static TOOLSTATE: &str =
+    "https://raw.githubusercontent.com/rust-lang-nursery/rust-toolstate/master/history/linux.tsv";
+
 #[derive(Serialize)]
 #[serde(rename_all = "kebab-case")]
 struct Manifest {
@@ -270,6 +280,7 @@ fn main() {
     // Do not ask for a passphrase while manually testing
     let mut passphrase = String::new();
     if should_sign {
+        // `x.py` passes the passphrase via stdin.
         t!(io::stdin().read_to_string(&mut passphrase));
     }
 
@@ -353,6 +364,7 @@ impl Builder {
         self.lldb_git_commit_hash = self.git_commit_hash("lldb", "x86_64-unknown-linux-gnu");
         self.miri_git_commit_hash = self.git_commit_hash("miri", "x86_64-unknown-linux-gnu");
 
+        self.check_toolstate();
         self.digest_and_sign();
         let manifest = self.build_manifest();
         self.write_channel_files(&self.rust_release, &manifest);
@@ -362,6 +374,37 @@ impl Builder {
         }
     }
 
+    /// If a tool does not pass its tests, don't ship it.
+    /// Right now, we do this only for Miri.
+    fn check_toolstate(&mut self) {
+        // Get the toolstate for this rust revision.
+        let rev = self.rust_git_commit_hash.as_ref().expect("failed to determine rust git hash");
+        let toolstates = reqwest::get(TOOLSTATE).expect("failed to get toolstates");
+        let toolstates = BufReader::new(toolstates);
+        let toolstate = toolstates.lines()
+            .find_map(|line| {
+                let line = line.expect("failed to read toolstate lines");
+                let mut pieces = line.splitn(2, '\t');
+                let commit = pieces.next().expect("malformed toolstate line");
+                if commit != rev {
+                    // Not the right commit.
+                    return None;
+                }
+                // Return the 2nd piece, the JSON.
+                Some(pieces.next().expect("malformed toolstate line").to_owned())
+            })
+            .expect("failed to find toolstate for rust commit");
+        let toolstate: HashMap<String, String> =
+            serde_json::from_str(&toolstate).expect("toolstate is malformed JSON");
+        // Mark some tools as missing based on toolstate.
+        if toolstate.get("miri").map(|s| &*s as &str) != Some("test-pass") {
+            println!("Miri tests are not passing, removing component");
+            self.miri_version = None;
+            self.miri_git_commit_hash = None;
+        }
+    }
+
+    /// Hash all files, compute their signatures, and collect the hashes in `self.digests`.
     fn digest_and_sign(&mut self) {
         for file in t!(self.input.read_dir()).map(|e| t!(e).path()) {
             let filename = file.file_name().unwrap().to_str().unwrap();
@@ -532,19 +575,20 @@ impl Builder {
             .as_ref()
             .cloned()
             .map(|version| (version, true))
-            .unwrap_or_default();
+            .unwrap_or_default(); // `is_present` defaults to `false` here.
 
-        // miri needs to build std with xargo, which doesn't allow stable/beta:
-        // <https://github.com/japaric/xargo/pull/204#issuecomment-374888868>
+        // Miri is nightly-only; never ship it for other trains.
         if pkgname == "miri-preview" && self.rust_release != "nightly" {
-            is_present = false; // ignore it
+            is_present = false; // Pretend the component is entirely missing.
         }
 
         let targets = targets.iter().map(|name| {
             if is_present {
+                // The component generally exists, but it might still be missing for this target.
                 let filename = self.filename(pkgname, name);
                 let digest = match self.digests.remove(&filename) {
                     Some(digest) => digest,
+                    // This component does not exist for this target -- skip it.
                     None => return (name.to_string(), Target::unavailable()),
                 };
                 let xz_filename = filename.replace(".tar.gz", ".tar.xz");