about summary refs log tree commit diff
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
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.
-rw-r--r--Cargo.lock5
-rw-r--r--rustfmt.toml1
-rw-r--r--src/bootstrap/Cargo.toml1
-rw-r--r--src/bootstrap/format.rs61
-rw-r--r--src/stage0.txt2
5 files changed, 52 insertions, 18 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 6a2cc847662..4c819e88809 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -192,6 +192,7 @@ dependencies = [
  "cmake",
  "filetime",
  "getopts",
+ "ignore",
  "lazy_static 1.3.0",
  "libc",
  "num_cpus",
@@ -1525,9 +1526,9 @@ checksum = "c3360c7b59e5ffa2653671fb74b4741a5d343c03f331c0a4aeda42b5c2b0ec7d"
 
 [[package]]
 name = "ignore"
-version = "0.4.7"
+version = "0.4.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8dc57fa12805f367736a38541ac1a9fc6a52812a0ca959b1d4d4b640a89eb002"
+checksum = "0ec16832258409d571aaef8273f3c3cc5b060d784e159d1a0f3b0017308f84a7"
 dependencies = [
  "crossbeam-channel",
  "globset",
diff --git a/rustfmt.toml b/rustfmt.toml
index bb656891446..4e38aace15d 100644
--- a/rustfmt.toml
+++ b/rustfmt.toml
@@ -68,6 +68,7 @@ ignore = [
     "src/rustllvm/",
     "src/test/",
     "src/tools/",
+    "src/etc",
 
     # do not format submodules
     "src/doc/book",
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);
+        }
+    }
 }
diff --git a/src/stage0.txt b/src/stage0.txt
index 2eb46e4e17b..494944720d9 100644
--- a/src/stage0.txt
+++ b/src/stage0.txt
@@ -19,7 +19,7 @@ cargo: beta
 # We use a nightly rustfmt to format the source because it solves some bootstrapping
 # issues with use of new syntax in this repo. If you're looking at the beta/stable branch, this key should be omitted,
 # as we don't want to depend on rustfmt from nightly there.
-rustfmt: nightly-2019-11-05
+rustfmt: nightly-2019-12-18
 
 # When making a stable release the process currently looks like:
 #