1use std::collections::VecDeque;
8use std::thread::{self, ScopedJoinHandle, scope};
9use std::{env, process};
10
11use tidy::arg_parser::TidyArgParser;
12use tidy::diagnostics::{COLOR_ERROR, COLOR_SUCCESS, TidyCtx, TidyFlags, output_message};
13use tidy::*;
14
15fn main() {
16 unsafe {
20 env::set_var("RUSTC_BOOTSTRAP", "1");
21 }
22
23 let parsed_args = TidyArgParser::parse();
24
25 let root_path = parsed_args.root_path;
26 let cargo = parsed_args.cargo;
27 let output_directory = parsed_args.output_directory;
28 let concurrency = parsed_args.concurrency.get();
29 let npm = parsed_args.npm;
30
31 let root_manifest = root_path.join("Cargo.toml");
32 let typos_toml = root_path.join("typos.toml");
33 let src_path = root_path.join("src");
34 let tests_path = root_path.join("tests");
35 let library_path = root_path.join("library");
36 let compiler_path = root_path.join("compiler");
37 let librustdoc_path = src_path.join("librustdoc");
38 let tools_path = src_path.join("tools");
39 let crashes_path = tests_path.join("crashes");
40
41 let verbose = parsed_args.verbose;
42 let bless = parsed_args.bless;
43 let extra_checks = parsed_args.extra_checks;
44 let pos_args = parsed_args.pos_args;
45
46 let tidy_ctx = TidyCtx::new(&root_path, verbose, TidyFlags::new(bless));
47 let ci_info = CiInfo::new(tidy_ctx.clone());
48
49 let drain_handles = |handles: &mut VecDeque<ScopedJoinHandle<'_, ()>>| {
50 for i in (0..handles.len()).rev() {
52 if handles[i].is_finished() {
53 handles.swap_remove_back(i).unwrap().join().unwrap();
54 }
55 }
56
57 while handles.len() >= concurrency {
58 handles.pop_front().unwrap().join().unwrap();
59 }
60 };
61
62 scope(|s| {
63 let mut handles: VecDeque<ScopedJoinHandle<'_, ()>> = VecDeque::with_capacity(concurrency);
64
65 macro_rules! check {
66 ($p:ident) => {
67 check!(@ $p, name=format!("{}", stringify!($p)));
68 };
69 ($p:ident, $path:expr $(, $args:expr)* ) => {
70 let shortened = $path.strip_prefix(&root_path).unwrap();
71 let name = if shortened == std::path::Path::new("") {
72 format!("{} (.)", stringify!($p))
73 } else {
74 format!("{} ({})", stringify!($p), shortened.display())
75 };
76 check!(@ $p, name=name, $path $(,$args)*);
77 };
78 (@ $p:ident, name=$name:expr $(, $args:expr)* ) => {
79 drain_handles(&mut handles);
80
81 let tidy_ctx = tidy_ctx.clone();
82 let handle = thread::Builder::new().name($name).spawn_scoped(s, || {
83 $p::check($($args, )* tidy_ctx);
84 }).unwrap();
85 handles.push_back(handle);
86 }
87 }
88
89 check!(target_specific_tests, &tests_path);
90
91 check!(deps, &root_path, &cargo);
93 check!(extdeps, &root_path);
94
95 check!(tests_placement, &root_path);
97 check!(tests_revision_unpaired_stdout_stderr, &tests_path);
98 check!(debug_artifacts, &tests_path);
99 check!(ui_tests, &root_path);
100 check!(mir_opt_tests, &tests_path);
101 check!(rustdoc_gui_tests, &tests_path);
102 check!(rustdoc_css_themes, &librustdoc_path);
103 check!(rustdoc_templates, &librustdoc_path);
104 check!(rustdoc_json, &src_path, &ci_info);
105 check!(known_bug, &crashes_path);
106 check!(unknown_revision, &tests_path);
107
108 check!(error_codes, &root_path, &[&compiler_path, &librustdoc_path], &ci_info);
110 check!(target_policy, &root_path);
111 check!(gcc_submodule, &root_path, &compiler_path);
112
113 check!(pal, &library_path);
115
116 check!(unit_tests, &src_path, false);
118 check!(unit_tests, &compiler_path, false);
119 check!(unit_tests, &library_path, true);
120
121 if bins::check_filesystem_support(&[&root_path], &output_directory) {
122 check!(bins, &root_path);
123 }
124
125 check!(style, &src_path);
126 check!(style, &tests_path);
127 check!(style, &compiler_path);
128 check!(style, &library_path);
129
130 check!(edition, &src_path);
131 check!(edition, &compiler_path);
132 check!(edition, &library_path);
133
134 check!(alphabetical, &root_manifest);
135 check!(alphabetical, &typos_toml);
136 check!(alphabetical, &src_path);
137 check!(alphabetical, &tests_path);
138 check!(alphabetical, &compiler_path);
139 check!(alphabetical, &library_path);
140
141 check!(x_version, &root_path, &cargo);
142
143 check!(triagebot, &root_path);
144 check!(filenames, &root_path);
145
146 let collected = {
147 drain_handles(&mut handles);
148
149 features::check(&src_path, &tests_path, &compiler_path, &library_path, tidy_ctx.clone())
150 };
151 check!(unstable_book, &src_path, collected);
152
153 check!(
154 extra_checks,
155 &root_path,
156 &output_directory,
157 &ci_info,
158 &librustdoc_path,
159 &tools_path,
160 &npm,
161 &cargo,
162 extra_checks,
163 pos_args
164 );
165 });
166
167 let failed_checks = tidy_ctx.into_failed_checks();
168 if !failed_checks.is_empty() {
169 let mut failed: Vec<String> =
170 failed_checks.into_iter().map(|c| c.id().to_string()).collect();
171 failed.sort();
172 output_message(
173 &format!(
174 "The following check{} failed: {}",
175 if failed.len() > 1 { "s" } else { "" },
176 failed.join(", ")
177 ),
178 None,
179 Some(COLOR_ERROR),
180 );
181 process::exit(1);
182 } else {
183 output_message("All tidy checks succeeded", None, Some(COLOR_SUCCESS));
184 }
185}