Files
rust/src/tools/tidy/src/main.rs
2022-12-31 01:55:24 +00:00

128 lines
4.2 KiB
Rust

//! Tidy checks source code in this repository.
//!
//! This program runs all of the various tidy checks for style, cleanliness,
//! etc. This is run by default on `./x.py test` and as part of the auto
//! builders. The tidy checks can be executed with `./x.py test tidy`.
use tidy::*;
use std::collections::VecDeque;
use std::env;
use std::num::NonZeroUsize;
use std::path::PathBuf;
use std::process;
use std::str::FromStr;
use std::sync::atomic::{AtomicBool, Ordering};
use std::thread::{scope, ScopedJoinHandle};
fn main() {
let root_path: PathBuf = env::args_os().nth(1).expect("need path to root of repo").into();
let cargo: PathBuf = env::args_os().nth(2).expect("need path to cargo").into();
let output_directory: PathBuf =
env::args_os().nth(3).expect("need path to output directory").into();
let concurrency: NonZeroUsize =
FromStr::from_str(&env::args().nth(4).expect("need concurrency"))
.expect("concurrency must be a number");
let src_path = root_path.join("src");
let library_path = root_path.join("library");
let compiler_path = root_path.join("compiler");
let args: Vec<String> = env::args().skip(1).collect();
let verbose = args.iter().any(|s| *s == "--verbose");
let bless = args.iter().any(|s| *s == "--bless");
let bad = std::sync::Arc::new(AtomicBool::new(false));
let drain_handles = |handles: &mut VecDeque<ScopedJoinHandle<'_, ()>>| {
// poll all threads for completion before awaiting the oldest one
for i in (0..handles.len()).rev() {
if handles[i].is_finished() {
handles.swap_remove_back(i).unwrap().join().unwrap();
}
}
while handles.len() >= concurrency.get() {
handles.pop_front().unwrap().join().unwrap();
}
};
scope(|s| {
let mut handles: VecDeque<ScopedJoinHandle<'_, ()>> =
VecDeque::with_capacity(concurrency.get());
macro_rules! check {
($p:ident $(, $args:expr)* ) => {
drain_handles(&mut handles);
let handle = s.spawn(|| {
let mut flag = false;
$p::check($($args),* , &mut flag);
if (flag) {
bad.store(true, Ordering::Relaxed);
}
});
handles.push_back(handle);
}
}
check!(target_specific_tests, &src_path);
// 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);
check!(mir_opt_tests, &src_path, bless);
// Checks that only make sense for the compiler.
check!(errors, &compiler_path);
check!(error_codes_check, &[&src_path, &compiler_path]);
// Checks that only make sense for the std libs.
check!(pal, &library_path);
check!(primitive_docs, &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);
if bins::check_filesystem_support(&[&root_path], &output_directory) {
check!(bins, &root_path);
}
check!(style, &src_path);
check!(style, &compiler_path);
check!(style, &library_path);
check!(edition, &src_path);
check!(edition, &compiler_path);
check!(edition, &library_path);
check!(alphabetical, &src_path);
check!(alphabetical, &compiler_path);
check!(alphabetical, &library_path);
let collected = {
drain_handles(&mut handles);
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);
});
if bad.load(Ordering::Relaxed) {
eprintln!("some tidy checks failed");
process::exit(1);
}
}