]> git.lizzy.rs Git - rust.git/blob - src/tools/tidy/src/main.rs
review comment
[rust.git] / src / tools / tidy / src / main.rs
1 //! Tidy checks source code in this repository.
2 //!
3 //! This program runs all of the various tidy checks for style, cleanliness,
4 //! etc. This is run by default on `./x.py test` and as part of the auto
5 //! builders. The tidy checks can be executed with `./x.py test tidy`.
6
7 use tidy::*;
8
9 use std::collections::VecDeque;
10 use std::env;
11 use std::num::NonZeroUsize;
12 use std::path::PathBuf;
13 use std::process;
14 use std::str::FromStr;
15 use std::sync::atomic::{AtomicBool, Ordering};
16 use std::thread::{scope, ScopedJoinHandle};
17
18 fn main() {
19     let root_path: PathBuf = env::args_os().nth(1).expect("need path to root of repo").into();
20     let cargo: PathBuf = env::args_os().nth(2).expect("need path to cargo").into();
21     let output_directory: PathBuf =
22         env::args_os().nth(3).expect("need path to output directory").into();
23     let concurrency: NonZeroUsize =
24         FromStr::from_str(&env::args().nth(4).expect("need concurrency"))
25             .expect("concurrency must be a number");
26
27     let src_path = root_path.join("src");
28     let library_path = root_path.join("library");
29     let compiler_path = root_path.join("compiler");
30
31     let args: Vec<String> = env::args().skip(1).collect();
32
33     let verbose = args.iter().any(|s| *s == "--verbose");
34     let bless = args.iter().any(|s| *s == "--bless");
35
36     let bad = std::sync::Arc::new(AtomicBool::new(false));
37
38     let drain_handles = |handles: &mut VecDeque<ScopedJoinHandle<'_, ()>>| {
39         // poll all threads for completion before awaiting the oldest one
40         for i in (0..handles.len()).rev() {
41             if handles[i].is_finished() {
42                 handles.swap_remove_back(i).unwrap().join().unwrap();
43             }
44         }
45
46         while handles.len() >= concurrency.get() {
47             handles.pop_front().unwrap().join().unwrap();
48         }
49     };
50
51     scope(|s| {
52         let mut handles: VecDeque<ScopedJoinHandle<'_, ()>> =
53             VecDeque::with_capacity(concurrency.get());
54
55         macro_rules! check {
56             ($p:ident $(, $args:expr)* ) => {
57                 drain_handles(&mut handles);
58
59                 let handle = s.spawn(|| {
60                     let mut flag = false;
61                     $p::check($($args),* , &mut flag);
62                     if (flag) {
63                         bad.store(true, Ordering::Relaxed);
64                     }
65                 });
66                 handles.push_back(handle);
67             }
68         }
69
70         check!(target_specific_tests, &src_path);
71
72         // Checks that are done on the cargo workspace.
73         check!(deps, &root_path, &cargo);
74         check!(extdeps, &root_path);
75
76         // Checks over tests.
77         check!(debug_artifacts, &src_path);
78         check!(ui_tests, &src_path);
79         check!(mir_opt_tests, &src_path, bless);
80
81         // Checks that only make sense for the compiler.
82         check!(errors, &compiler_path);
83         check!(error_codes_check, &[&src_path, &compiler_path]);
84
85         // Checks that only make sense for the std libs.
86         check!(pal, &library_path);
87         check!(primitive_docs, &library_path);
88
89         // Checks that need to be done for both the compiler and std libraries.
90         check!(unit_tests, &src_path);
91         check!(unit_tests, &compiler_path);
92         check!(unit_tests, &library_path);
93
94         if bins::check_filesystem_support(&[&root_path], &output_directory) {
95             check!(bins, &root_path);
96         }
97
98         check!(style, &src_path);
99         check!(style, &compiler_path);
100         check!(style, &library_path);
101
102         check!(edition, &src_path);
103         check!(edition, &compiler_path);
104         check!(edition, &library_path);
105
106         check!(alphabetical, &src_path);
107         check!(alphabetical, &compiler_path);
108         check!(alphabetical, &library_path);
109
110         let collected = {
111             drain_handles(&mut handles);
112
113             let mut flag = false;
114             let r = features::check(&src_path, &compiler_path, &library_path, &mut flag, verbose);
115             if flag {
116                 bad.store(true, Ordering::Relaxed);
117             }
118             r
119         };
120         check!(unstable_book, &src_path, collected);
121     });
122
123     if bad.load(Ordering::Relaxed) {
124         eprintln!("some tidy checks failed");
125         process::exit(1);
126     }
127 }