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!(fluent_alphabetical, &compiler_path);
111 check!(fluent_period, &compiler_path);
112 check!(fluent_lowercase, &compiler_path);
113 check!(target_policy, &root_path);
114 check!(gcc_submodule, &root_path, &compiler_path);
115
116 check!(pal, &library_path);
118
119 check!(unit_tests, &src_path, false);
121 check!(unit_tests, &compiler_path, false);
122 check!(unit_tests, &library_path, true);
123
124 if bins::check_filesystem_support(&[&root_path], &output_directory) {
125 check!(bins, &root_path);
126 }
127
128 check!(style, &src_path);
129 check!(style, &tests_path);
130 check!(style, &compiler_path);
131 check!(style, &library_path);
132
133 check!(edition, &src_path);
134 check!(edition, &compiler_path);
135 check!(edition, &library_path);
136
137 check!(alphabetical, &root_manifest);
138 check!(alphabetical, &typos_toml);
139 check!(alphabetical, &src_path);
140 check!(alphabetical, &tests_path);
141 check!(alphabetical, &compiler_path);
142 check!(alphabetical, &library_path);
143
144 check!(x_version, &root_path, &cargo);
145
146 check!(triagebot, &root_path);
147 check!(filenames, &root_path);
148
149 let collected = {
150 drain_handles(&mut handles);
151
152 features::check(&src_path, &tests_path, &compiler_path, &library_path, tidy_ctx.clone())
153 };
154 check!(unstable_book, &src_path, collected);
155
156 check!(
157 extra_checks,
158 &root_path,
159 &output_directory,
160 &ci_info,
161 &librustdoc_path,
162 &tools_path,
163 &npm,
164 &cargo,
165 extra_checks,
166 pos_args
167 );
168 });
169
170 let failed_checks = tidy_ctx.into_failed_checks();
171 if !failed_checks.is_empty() {
172 let mut failed: Vec<String> =
173 failed_checks.into_iter().map(|c| c.id().to_string()).collect();
174 failed.sort();
175 output_message(
176 &format!(
177 "The following check{} failed: {}",
178 if failed.len() > 1 { "s" } else { "" },
179 failed.join(", ")
180 ),
181 None,
182 Some(COLOR_ERROR),
183 );
184 process::exit(1);
185 } else {
186 output_message("All tidy checks succeeded", None, Some(COLOR_SUCCESS));
187 }
188}