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.
This commit is contained in:
Mark Rousskov 2019-12-18 10:52:10 -05:00
parent 2b081abe94
commit dddd872427
5 changed files with 53 additions and 19 deletions

View File

@ -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",

View File

@ -68,6 +68,7 @@ ignore = [
"src/rustllvm/",
"src/test/",
"src/tools/",
"src/etc",
# do not format submodules
"src/doc/book",

View File

@ -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"

View File

@ -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");
}
let status = cmd.status().expect("executing cargo-fmt");
assert!(status.success(), "cargo-fmt errored with status {:?}", status);
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 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);
}
}
}

View File

@ -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:
#