summary refs log tree commit diff
path: root/src/bootstrap
diff options
context:
space:
mode:
authorMark Rousskov <mark.simulacrum@gmail.com>2019-12-18 10:52:10 -0500
committerMark Rousskov <mark.simulacrum@gmail.com>2019-12-21 20:23:55 -0500
commitdddd8724271a2a38ce552f5b1062a7ea070ec126 (patch)
tree8cfcd9fccb826db1dc7bf5646c45ce7ee000bcae /src/bootstrap
parent2b081abe944a7915013e15ae602ac8cfe9f52a77 (diff)
downloadrust-dddd8724271a2a38ce552f5b1062a7ea070ec126.tar.gz
rust-dddd8724271a2a38ce552f5b1062a7ea070ec126.zip
Implement rustfmt running manually using ignore crate
This replaces cargo-fmt with rustfmt with --skip-children which should
allow us to format code without running into rust-lang/rustfmt#3930.

This also bumps up the version of rustfmt used to a more recent one.
Diffstat (limited to 'src/bootstrap')
-rw-r--r--src/bootstrap/Cargo.toml1
-rw-r--r--src/bootstrap/format.rs61
2 files changed, 47 insertions, 15 deletions
diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml
index 7be16cf3f17..3ab00a6e147 100644
--- a/src/bootstrap/Cargo.toml
+++ b/src/bootstrap/Cargo.toml
@@ -47,6 +47,7 @@ serde_json = "1.0.2"
 toml = "0.5"
 lazy_static = "1.3.0"
 time = "0.1"
+ignore = "0.4.10"
 
 [dev-dependencies]
 pretty_assertions = "0.5"
diff --git a/src/bootstrap/format.rs b/src/bootstrap/format.rs
index 0c542594eff..e253e525526 100644
--- a/src/bootstrap/format.rs
+++ b/src/bootstrap/format.rs
@@ -1,28 +1,59 @@
 //! Runs rustfmt on the repository.
 
-use crate::{util, Build};
+use crate::Build;
 use std::process::Command;
+use ignore::WalkBuilder;
+use std::path::Path;
+use build_helper::t;
 
-pub fn format(build: &Build, check: bool) {
-    let target = &build.build;
+fn rustfmt(build: &Build, path: &Path, check: bool) {
     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);
-    }).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");
+    });
 
+    let mut cmd = Command::new(&rustfmt_path);
+    // 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(&build.src.canonicalize().unwrap());
+    cmd.arg("--unstable-features");
+    cmd.arg("--skip-children");
     if check {
-        cmd.arg("--");
         cmd.arg("--check");
     }
+    cmd.arg(&path);
+    let cmd_debug = format!("{:?}", cmd);
+    let status = cmd.status().expect("executing rustfmt");
+    assert!(status.success(), "running {} successful", cmd_debug);
+}
+
+#[derive(serde::Deserialize)]
+struct RustfmtConfig {
+    ignore: Vec<String>,
+}
+
+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 = t!(std::fs::read_to_string(build.src.join("rustfmt.toml")));
+    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 walker = WalkBuilder::new(&build.src)
+        .types(matcher)
+        .overrides(ignore_fmt)
+        .build();
+    for entry in walker {
+        let entry = t!(entry);
+        if entry.file_type().map_or(false, |t| t.is_file()) {
+            rustfmt(build, &entry.path(), check);
+        }
+    }
 }