diff --git a/Cargo.lock b/Cargo.lock index 6e95fd6af273fb4a0637b9e28b82c0bd391b18a1..2f2d90655115a8af1e5f543e5434324232eb7dab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5239,6 +5239,7 @@ name = "tidy" version = "0.1.0" dependencies = [ "cargo_metadata 0.11.1", + "crossbeam-utils 0.8.0", "lazy_static", "regex", "walkdir", diff --git a/src/tools/tidy/Cargo.toml b/src/tools/tidy/Cargo.toml index 777d7be8fdc43c22db553171000981b9fc1f60a1..58c32993cb6ef24b1a08ac25c9a28acb32d925ba 100644 --- a/src/tools/tidy/Cargo.toml +++ b/src/tools/tidy/Cargo.toml @@ -10,6 +10,7 @@ cargo_metadata = "0.11" regex = "1" lazy_static = "1" walkdir = "2" +crossbeam-utils = "0.8.0" [[bin]] name = "rust-tidy" diff --git a/src/tools/tidy/src/bins.rs b/src/tools/tidy/src/bins.rs index 62cfa85577f983e2155ffc93b21272ea09f9912f..f4e203cac408de76aa818bc9826abf69b8019b1a 100644 --- a/src/tools/tidy/src/bins.rs +++ b/src/tools/tidy/src/bins.rs @@ -32,9 +32,12 @@ fn is_executable(path: &Path) -> std::io::Result { // readily create a file there to test. // // See #36706 and #74753 for context. - let mut temp_path = path.join("tidy-test-file"); + // + // We also add the thread ID to avoid threads trampling on each others files. + let file_name = format!("t{}.tidy-test-file", std::thread::current().id().as_u64()); + let mut temp_path = path.join(&file_name); match fs::File::create(&temp_path).or_else(|_| { - temp_path = output.join("tidy-test-file"); + temp_path = output.join(&file_name); fs::File::create(&temp_path) }) { Ok(file) => { diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs index 11d36751f67bb0b6a2b725d877a2e152164a3f0d..45cc169470b96166760f3f8bdff36007e14812af 100644 --- a/src/tools/tidy/src/lib.rs +++ b/src/tools/tidy/src/lib.rs @@ -4,6 +4,7 @@ //! to be used by tools. #![cfg_attr(bootstrap, feature(str_split_once))] +#![feature(thread_id_value)] use std::fs::File; use std::io::Read; @@ -54,6 +55,12 @@ pub mod unstable_book; fn filter_dirs(path: &Path) -> bool { + // Filter out temporary files used by the bins module to probe the filesystem + match path.extension() { + Some(ext) if ext == "tidy-test-file" => return true, + _ => {} + } + let skip = [ "compiler/rustc_codegen_cranelift", "src/llvm-project", diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs index 2ac96e404acb9e61940c5e7061a3724101ea41ec..9151d2bb4062a6bb810cbc088f4f63371f77e85a 100644 --- a/src/tools/tidy/src/main.rs +++ b/src/tools/tidy/src/main.rs @@ -6,9 +6,11 @@ use tidy::*; +use crossbeam_utils::thread::scope; use std::env; use std::path::PathBuf; use std::process; +use std::sync::atomic::{AtomicBool, Ordering}; fn main() { let root_path: PathBuf = env::args_os().nth(1).expect("need path to root of repo").into(); @@ -22,45 +24,68 @@ fn main() { let args: Vec = env::args().skip(1).collect(); - let mut bad = false; let verbose = args.iter().any(|s| *s == "--verbose"); - // Checks over tests. - debug_artifacts::check(&src_path, &mut bad); - ui_tests::check(&src_path, &mut bad); - - // Checks that only make sense for the compiler. - errors::check(&compiler_path, &mut bad); - error_codes_check::check(&src_path, &mut bad); - - // Checks that only make sense for the std libs. - pal::check(&library_path, &mut bad); - - // Checks that need to be done for both the compiler and std libraries. - unit_tests::check(&src_path, &mut bad); - unit_tests::check(&compiler_path, &mut bad); - unit_tests::check(&library_path, &mut bad); - - bins::check(&src_path, &output_directory, &mut bad); - bins::check(&compiler_path, &output_directory, &mut bad); - bins::check(&library_path, &output_directory, &mut bad); - - style::check(&src_path, &mut bad); - style::check(&compiler_path, &mut bad); - style::check(&library_path, &mut bad); - - edition::check(&src_path, &mut bad); - edition::check(&compiler_path, &mut bad); - edition::check(&library_path, &mut bad); - - let collected = features::check(&src_path, &compiler_path, &library_path, &mut bad, verbose); - unstable_book::check(&src_path, collected, &mut bad); - - // Checks that are done on the cargo workspace. - deps::check(&root_path, &cargo, &mut bad); - extdeps::check(&root_path, &mut bad); - - if bad { + let bad = std::sync::Arc::new(AtomicBool::new(false)); + + scope(|s| { + macro_rules! check { + ($p:ident $(, $args:expr)* ) => { + s.spawn(|_| { + let mut flag = false; + $p::check($($args),* , &mut flag); + if (flag) { + bad.store(true, Ordering::Relaxed); + } + }); + } + } + + // Checks that are done on the cargo workspace. + check!(deps, &root_path, &cargo); + check!(extdeps, &root_path); + + // Checks over tests. + check!(debug_artifacts, &src_path); + check!(ui_tests, &src_path); + + // Checks that only make sense for the compiler. + check!(errors, &compiler_path); + check!(error_codes_check, &src_path); + + // Checks that only make sense for the std libs. + check!(pal, &library_path); + + // Checks that need to be done for both the compiler and std libraries. + check!(unit_tests, &src_path); + check!(unit_tests, &compiler_path); + check!(unit_tests, &library_path); + + check!(bins, &src_path, &output_directory); + check!(bins, &compiler_path, &output_directory); + check!(bins, &library_path, &output_directory); + + check!(style, &src_path); + check!(style, &compiler_path); + check!(style, &library_path); + + check!(edition, &src_path); + check!(edition, &compiler_path); + check!(edition, &library_path); + + let collected = { + let mut flag = false; + let r = features::check(&src_path, &compiler_path, &library_path, &mut flag, verbose); + if flag { + bad.store(true, Ordering::Relaxed); + } + r + }; + check!(unstable_book, &src_path, collected); + }) + .unwrap(); + + if bad.load(Ordering::Relaxed) { eprintln!("some tidy checks failed"); process::exit(1); }