1use std::num::NonZeroUsize;
8use std::thread::{self, 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 ci = parsed_args.ci;
44 let extra_checks = parsed_args.extra_checks;
45 let pos_args = parsed_args.pos_args;
46
47 let tidy_ctx = TidyCtx::new(&root_path, verbose, ci, TidyFlags::new(bless));
48
49 let sem = Semaphore::new(NonZeroUsize::new(concurrency).unwrap());
50
51 scope(|s| {
52 macro_rules! check {
53 ($p:ident) => {
54 check!(@ $p, name=format!("{}", stringify!($p)));
55 };
56 ($p:ident, $path:expr $(, $args:expr)* ) => {
57 let shortened = $path.strip_prefix(&root_path).unwrap();
58 let name = if shortened == std::path::Path::new("") {
59 format!("{} (.)", stringify!($p))
60 } else {
61 format!("{} ({})", stringify!($p), shortened.display())
62 };
63 check!(@ $p, name=name, $path $(,$args)*);
64 };
65 (@ $p:ident, name=$name:expr $(, $args:expr)* ) => {
66 let guard = sem.acquire();
67 let tidy_ctx = tidy_ctx.clone();
68 thread::Builder::new().name($name).spawn_scoped(s, || {
69 $p::check($($args, )* tidy_ctx);
70 let _guard = guard;
71 }).unwrap();
72 }
73 }
74
75 check!(target_specific_tests, &tests_path);
76
77 check!(deps, &root_path, &cargo, &sem);
79 check!(extdeps, &root_path);
80
81 check!(tests_placement, &root_path);
83 check!(tests_revision_unpaired_stdout_stderr, &tests_path);
84 check!(debug_artifacts, &tests_path);
85 check!(ui_tests, &root_path);
86 check!(mir_opt_tests, &tests_path);
87 check!(rustdoc_gui_tests, &tests_path);
88 check!(rustdoc_css_themes, &librustdoc_path);
89 check!(rustdoc_templates, &librustdoc_path);
90 check!(rustdoc_json, &src_path);
91 check!(rustdoc_html_tests, &tests_path);
92 check!(known_bug, &crashes_path);
93 check!(unknown_revision, &tests_path);
94
95 check!(error_codes, &root_path, &[&compiler_path, &librustdoc_path]);
97 check!(target_policy, &root_path);
98 check!(gcc_submodule, &root_path, &compiler_path);
99 check!(codegen, &compiler_path);
100
101 check!(pal, &library_path);
103
104 check!(unit_tests, &src_path, false);
106 check!(unit_tests, &compiler_path, false);
107 check!(unit_tests, &library_path, true);
108
109 if bins::check_filesystem_support(&[&root_path], &output_directory) {
110 check!(bins, &root_path);
111 }
112
113 check!(style, &tests_path);
114 check!(style, &src_path);
115 check!(style, &compiler_path);
116 check!(style, &library_path);
117
118 check!(edition, &src_path);
119 check!(edition, &compiler_path);
120 check!(edition, &library_path);
121
122 check!(alphabetical, &root_manifest);
123 check!(alphabetical, &typos_toml);
124 check!(alphabetical, &src_path);
125 check!(alphabetical, &tests_path);
126 check!(alphabetical, &compiler_path);
127 check!(alphabetical, &library_path);
128
129 check!(x_version, &root_path, &cargo);
130
131 check!(triagebot, &root_path);
132 check!(filenames, &root_path);
133
134 let collected = {
135 features::check(&src_path, &tests_path, &compiler_path, &library_path, tidy_ctx.clone())
136 };
137 check!(unstable_book, &src_path, collected);
138
139 check!(
140 extra_checks,
141 &root_path,
142 &output_directory,
143 &librustdoc_path,
144 &tools_path,
145 &npm,
146 &cargo,
147 extra_checks,
148 pos_args
149 );
150 });
151
152 let failed_checks = tidy_ctx.into_failed_checks();
153 if !failed_checks.is_empty() {
154 let mut failed: Vec<String> =
155 failed_checks.into_iter().map(|c| c.id().to_string()).collect();
156 failed.sort();
157 output_message(
158 &format!(
159 "The following check{} failed: {}",
160 if failed.len() > 1 { "s" } else { "" },
161 failed.join(", ")
162 ),
163 None,
164 Some(COLOR_ERROR),
165 );
166 process::exit(1);
167 } else {
168 output_message("All tidy checks succeeded", None, Some(COLOR_SUCCESS));
169 }
170}