summaryrefslogtreecommitdiffstats
path: root/src/tools/tidy/src/main.rs
blob: aa8d8b4f64d7d0ee3a4e4f5f524480809e8af69b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
//! 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 crossbeam_utils::thread::{scope, ScopedJoinHandle};
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};

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 bad = std::sync::Arc::new(AtomicBool::new(false));

    scope(|s| {
        let mut handles: VecDeque<ScopedJoinHandle<'_, ()>> =
            VecDeque::with_capacity(concurrency.get());

        macro_rules! check {
            ($p:ident $(, $args:expr)* ) => {
                while handles.len() >= concurrency.get() {
                    handles.pop_front().unwrap().join().unwrap();
                }

                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);

        // 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);

        let collected = {
            while handles.len() >= concurrency.get() {
                handles.pop_front().unwrap().join().unwrap();
            }
            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);
    }
}