]> git.lizzy.rs Git - rust.git/blob - src/bootstrap/format.rs
Rollup merge of #66045 - mzabaluev:unwrap-infallible, r=dtolnay
[rust.git] / src / bootstrap / format.rs
1 //! Runs rustfmt on the repository.
2
3 use crate::Build;
4 use build_helper::t;
5 use ignore::WalkBuilder;
6 use std::path::Path;
7 use std::process::Command;
8
9 fn rustfmt(src: &Path, rustfmt: &Path, path: &Path, check: bool) {
10     let mut cmd = Command::new(&rustfmt);
11     // avoid the submodule config paths from coming into play,
12     // we only allow a single global config for the workspace for now
13     cmd.arg("--config-path").arg(&src.canonicalize().unwrap());
14     cmd.arg("--edition").arg("2018");
15     cmd.arg("--unstable-features");
16     cmd.arg("--skip-children");
17     if check {
18         cmd.arg("--check");
19     }
20     cmd.arg(&path);
21     let cmd_debug = format!("{:?}", cmd);
22     let status = cmd.status().expect("executing rustfmt");
23     assert!(status.success(), "running {} successful", cmd_debug);
24 }
25
26 #[derive(serde::Deserialize)]
27 struct RustfmtConfig {
28     ignore: Vec<String>,
29 }
30
31 pub fn format(build: &Build, check: bool) {
32     let mut builder = ignore::types::TypesBuilder::new();
33     builder.add_defaults();
34     builder.select("rust");
35     let matcher = builder.build().unwrap();
36     let rustfmt_config = build.src.join("rustfmt.toml");
37     if !rustfmt_config.exists() {
38         eprintln!("Not running formatting checks; rustfmt.toml does not exist.");
39         eprintln!("This may happen in distributed tarballs.");
40         return;
41     }
42     let rustfmt_config = t!(std::fs::read_to_string(&rustfmt_config));
43     let rustfmt_config: RustfmtConfig = t!(toml::from_str(&rustfmt_config));
44     let mut ignore_fmt = ignore::overrides::OverrideBuilder::new(&build.src);
45     for ignore in rustfmt_config.ignore {
46         ignore_fmt.add(&format!("!{}", ignore)).expect(&ignore);
47     }
48     let ignore_fmt = ignore_fmt.build().unwrap();
49
50     let rustfmt_path = build.config.initial_rustfmt.as_ref().unwrap_or_else(|| {
51         eprintln!("./x.py fmt is not supported on this channel");
52         std::process::exit(1);
53     });
54     let src = build.src.clone();
55     let walker = WalkBuilder::new(&build.src).types(matcher).overrides(ignore_fmt).build_parallel();
56     walker.run(|| {
57         let src = src.clone();
58         let rustfmt_path = rustfmt_path.clone();
59         Box::new(move |entry| {
60             let entry = t!(entry);
61             if entry.file_type().map_or(false, |t| t.is_file()) {
62                 rustfmt(&src, &rustfmt_path, &entry.path(), check);
63             }
64             ignore::WalkState::Continue
65         })
66     });
67 }