]> git.lizzy.rs Git - rust.git/blobdiff - src/bootstrap/format.rs
Rollup merge of #68279 - GuillaumeGomez:clean-up-e0198, r=Dylan-DPC
[rust.git] / src / bootstrap / format.rs
index 0c542594effebd7f71a05d119af9d4370c0aa835..6e5e3fe07e7467065abd36bbef79a49863ce1c33 100644 (file)
@@ -1,28 +1,75 @@
 //! Runs rustfmt on the repository.
 
-use crate::{util, Build};
+use crate::Build;
+use build_helper::t;
+use ignore::WalkBuilder;
+use std::path::Path;
 use std::process::Command;
 
-pub fn format(build: &Build, check: bool) {
-    let target = &build.build;
-    let rustfmt_path = build.config.initial_rustfmt.as_ref().unwrap_or_else(|| {
-        eprintln!("./x.py fmt is not supported on this channel");
+fn rustfmt(src: &Path, rustfmt: &Path, path: &Path, check: bool) {
+    let mut cmd = Command::new(&rustfmt);
+    // avoid the submodule config paths from coming into play,
+    // we only allow a single global config for the workspace for now
+    cmd.arg("--config-path").arg(&src.canonicalize().unwrap());
+    cmd.arg("--edition").arg("2018");
+    cmd.arg("--unstable-features");
+    cmd.arg("--skip-children");
+    if check {
+        cmd.arg("--check");
+    }
+    cmd.arg(&path);
+    let cmd_debug = format!("{:?}", cmd);
+    let status = cmd.status().expect("executing rustfmt");
+    if !status.success() {
+        eprintln!(
+            "Running `{}` failed.\nIf you're running `tidy`, \
+            try again with `--bless` flag. Or, you just want to format \
+            code, run `./x.py fmt` instead.",
+            cmd_debug,
+        );
         std::process::exit(1);
-    }).clone();
-    let cargo_fmt_path = rustfmt_path.with_file_name(util::exe("cargo-fmt", &target));
-    assert!(cargo_fmt_path.is_file(), "{} not a file", cargo_fmt_path.display());
+    }
+}
 
-    let mut cmd = Command::new(&cargo_fmt_path);
-    // cargo-fmt calls rustfmt as a bare command, so we need it to only find the correct one
-    cmd.env("PATH", cargo_fmt_path.parent().unwrap());
-    cmd.current_dir(&build.src);
-    cmd.arg("fmt");
+#[derive(serde::Deserialize)]
+struct RustfmtConfig {
+    ignore: Vec<String>,
+}
 
-    if check {
-        cmd.arg("--");
-        cmd.arg("--check");
+pub fn format(build: &Build, check: bool) {
+    let mut builder = ignore::types::TypesBuilder::new();
+    builder.add_defaults();
+    builder.select("rust");
+    let matcher = builder.build().unwrap();
+    let rustfmt_config = build.src.join("rustfmt.toml");
+    if !rustfmt_config.exists() {
+        eprintln!("Not running formatting checks; rustfmt.toml does not exist.");
+        eprintln!("This may happen in distributed tarballs.");
+        return;
     }
+    let rustfmt_config = t!(std::fs::read_to_string(&rustfmt_config));
+    let rustfmt_config: RustfmtConfig = t!(toml::from_str(&rustfmt_config));
+    let mut ignore_fmt = ignore::overrides::OverrideBuilder::new(&build.src);
+    for ignore in rustfmt_config.ignore {
+        ignore_fmt.add(&format!("!{}", ignore)).expect(&ignore);
+    }
+    let ignore_fmt = ignore_fmt.build().unwrap();
 
-    let status = cmd.status().expect("executing cargo-fmt");
-    assert!(status.success(), "cargo-fmt errored with status {:?}", status);
+    let rustfmt_path = build.config.initial_rustfmt.as_ref().unwrap_or_else(|| {
+        eprintln!("./x.py fmt is not supported on this channel");
+        std::process::exit(1);
+    });
+    let src = build.src.clone();
+    let walker = WalkBuilder::new(&build.src).types(matcher).overrides(ignore_fmt).build_parallel();
+    walker.run(|| {
+        let src = src.clone();
+        let rustfmt_path = rustfmt_path.clone();
+        Box::new(move |entry| {
+            let entry = t!(entry);
+            if entry.file_type().map_or(false, |t| t.is_file()) {
+                rustfmt(&src, &rustfmt_path, &entry.path(), check);
+            }
+            ignore::WalkState::Continue
+        })
+    });
 }