cargo-deny 0.18.3

Cargo plugin to help you manage large dependency graphs
Documentation
const REPOS: &[&str] = &[
    "https://github.com/EmbarkStudios/cargo-about",
    "https://github.com/EmbarkStudios/physx-rs",
];

fn main() {
    use std::process::Command;

    let td = std::env::temp_dir().join("deny-repos");
    // This kind of doesn't work on windows!
    if td.exists() {
        std::fs::remove_dir_all(&td).unwrap();
    }
    std::fs::create_dir_all(&td).unwrap();

    // Fetch external sources once
    if !Command::new("cargo")
        .args(&["deny", "-L", "debug", "fetch", "all"])
        .status()
        .expect("failed to run cargo deny fetch")
        .success()
    {
        panic!("failed to run cargo deny fetch");
    }

    let (tx, rx) = std::sync::mpsc::channel();

    for repo in REPOS {
        let tx = tx.clone();
        let td = td.clone();
        std::thread::spawn(move || {
            let repo_name = &repo[repo.rfind('/').unwrap() + 1..];
            let repo_dir = td.join(repo_name);

            println!("cloning {}", repo);

            match Command::new("git")
                .arg("clone")
                .arg(repo)
                .arg(&repo_dir)
                .output()
            {
                Ok(out) => {
                    if !out.status.success() {
                        let err_str = String::from_utf8(out.stderr)
                            .unwrap_or_else(|e| format!("git err output has bad utf8: {}", e));
                        tx.send(Some((repo, err_str))).unwrap();
                        return;
                    }
                }
                Err(e) => {
                    tx.send(Some((repo, format!("failed to spawn git clone: {}", e))))
                        .unwrap();
                    return;
                }
            };

            println!("checking {}", repo);

            match Command::new("cargo")
                .args(&[
                    "deny",
                    "--all-features",
                    "-L",
                    "info",
                    "check",
                    "--disable-fetch",
                ])
                .current_dir(repo_dir)
                .output()
            {
                Ok(out) => {
                    if !out.status.success() {
                        let err_str = String::from_utf8(out.stderr)
                            .unwrap_or_else(|e| format!("deny err output has bad utf8: {}", e));
                        tx.send(Some((repo, err_str))).unwrap();
                    }
                }
                Err(e) => {
                    tx.send(Some((repo, format!("failed to spawn cargo deny: {}", e))))
                        .unwrap();
                }
            }
        });
    }

    drop(tx);

    let mut code = 0;
    while let Ok(bad) = rx.recv() {
        if let Some((repo, output)) = bad {
            code = 1;

            eprintln!("failed {}:\n{}", repo, output);
        }
    }

    std::process::exit(code);
}