Skip to content

Commit

Permalink
Start adding a whitelist for rustc dependencies
Browse files Browse the repository at this point in the history
  • Loading branch information
mark-i-m committed Mar 5, 2018
1 parent 2cb8c5f commit 3ee4104
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 9 deletions.
5 changes: 5 additions & 0 deletions src/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/tools/tidy/Cargo.toml
Expand Up @@ -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"
76 changes: 67 additions & 9 deletions src/tools/tidy/src/deps.rs
Expand Up @@ -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",
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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
}
5 changes: 5 additions & 0 deletions src/tools/tidy/src/lib.rs
Expand Up @@ -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;
Expand Down

0 comments on commit 3ee4104

Please sign in to comment.