about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMark Mansi <markm@cs.wisc.edu>2018-02-22 19:52:56 -0600
committerMark Mansi <markm@cs.wisc.edu>2018-03-05 14:43:44 -0600
commit3ee410498db9826c3ccb81ce8c0aa40f7f3b4082 (patch)
tree98a4943f8641a9e091331747b48c4f2c6412bc46
parent2cb8c5fff690cff5e98c84f9bd08411f79347bd9 (diff)
downloadrust-3ee410498db9826c3ccb81ce8c0aa40f7f3b4082.tar.gz
rust-3ee410498db9826c3ccb81ce8c0aa40f7f3b4082.zip
Start adding a whitelist for rustc dependencies
-rw-r--r--src/Cargo.lock5
-rw-r--r--src/tools/tidy/Cargo.toml5
-rw-r--r--src/tools/tidy/src/deps.rs76
-rw-r--r--src/tools/tidy/src/lib.rs5
4 files changed, 82 insertions, 9 deletions
diff --git a/src/Cargo.lock b/src/Cargo.lock
index 7620fe8ddb3..5e7909ff435 100644
--- a/src/Cargo.lock
+++ b/src/Cargo.lock
@@ -2585,6 +2585,11 @@ dependencies = [
 [[package]]
 name = "tidy"
 version = "0.1.0"
+dependencies = [
+ "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
+]
 
 [[package]]
 name = "time"
diff --git a/src/tools/tidy/Cargo.toml b/src/tools/tidy/Cargo.toml
index 664aecfcbdb..f7b491823f8 100644
--- a/src/tools/tidy/Cargo.toml
+++ b/src/tools/tidy/Cargo.toml
@@ -2,3 +2,8 @@
 name = "tidy"
 version = "0.1.0"
 authors = ["Alex Crichton <alex@alexcrichton.com>"]
+
+[dependencies]
+serde = "1.0.8"
+serde_derive = "1.0.8"
+serde_json = "1.0.2"
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index c3fb0d3913f..2cb8a70844e 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -14,6 +14,10 @@ use std::fs::File;
 use std::io::Read;
 use std::path::Path;
 
+use std::process::Command;
+
+use serde_json;
+
 static LICENSES: &'static [&'static str] = &[
     "MIT/Apache-2.0",
     "MIT / Apache-2.0",
@@ -44,31 +48,68 @@ static EXCEPTIONS: &'static [&'static str] = &[
     "clippy_lints",       // MPL-2.0 rls
 ];
 
+// Whitelist of crates rustc is allowed to depend on. Avoid adding to the list if possible.
+static WHITELIST: &'static [(&'static str, &'static str)] = &[];
+
+// Some type for Serde to deserialize the output of `cargo metadata` to...
+
+#[derive(Deserialize)]
+struct Output {
+    packages: Vec<Package>,
+    _resolve: String,
+}
+
+#[derive(Deserialize)]
+struct Package {
+    _id: String,
+    name: String,
+    version: String,
+    _source: Option<String>,
+    _manifest_path: String,
+}
+
+/// Checks the dependency at the given path. Changes `bad` to `true` if a check failed.
+///
+/// Specifically, this checks that the license is correct and that the dependencies are on the
+/// whitelist.
 pub fn check(path: &Path, bad: &mut bool) {
+    // Check licences
     let path = path.join("vendor");
     assert!(path.exists(), "vendor directory missing");
     let mut saw_dir = false;
-    'next_path: for dir in t!(path.read_dir()) {
+    for dir in t!(path.read_dir()) {
         saw_dir = true;
         let dir = t!(dir);
 
         // skip our exceptions
-        for exception in EXCEPTIONS {
-            if dir.path()
+        if EXCEPTIONS.iter().any(|exception| {
+            dir.path()
                 .to_str()
                 .unwrap()
                 .contains(&format!("src/vendor/{}", exception))
-            {
-                continue 'next_path;
-            }
+        }) {
+            continue;
         }
 
         let toml = dir.path().join("Cargo.toml");
-        if !check_license(&toml) {
-            *bad = true;
-        }
+        *bad = *bad || !check_license(&toml);
     }
     assert!(saw_dir, "no vendored source");
+
+    // Check dependencies
+    let deps = get_deps(&path);
+    *bad = *bad
+        || deps.iter().any(
+            |&Package {
+                 ref name,
+                 ref version,
+                 ..
+             }| {
+                WHITELIST
+                    .iter()
+                    .all(|&(wname, wversion)| name != wname || version != wversion)
+            },
+        );
 }
 
 fn check_license(path: &Path) -> bool {
@@ -109,3 +150,20 @@ fn extract_license(line: &str) -> String {
         "bad-license-parse".into()
     }
 }
+
+fn get_deps(path: &Path) -> Vec<Package> {
+    // Run `cargo metadata` to get the set of dependencies
+    let output = Command::new("cargo")
+        .arg("metadata")
+        .arg("--format-version")
+        .arg("1")
+        .arg("--manifest-path")
+        .arg(path.join("Cargo.toml"))
+        .output()
+        .expect("Unable to run `cargo metadata`")
+        .stdout;
+    let output = String::from_utf8_lossy(&output);
+    let output: Output = serde_json::from_str(&output).unwrap();
+
+    output.packages
+}
diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs
index 5134c869912..c927ff19b27 100644
--- a/src/tools/tidy/src/lib.rs
+++ b/src/tools/tidy/src/lib.rs
@@ -15,6 +15,11 @@
 
 #![deny(warnings)]
 
+extern crate serde;
+extern crate serde_json;
+#[macro_use]
+extern crate serde_derive;
+
 use std::fs;
 
 use std::path::Path;