From dddd8724271a2a38ce552f5b1062a7ea070ec126 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Wed, 18 Dec 2019 10:52:10 -0500 Subject: [PATCH] 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. --- Cargo.lock | 5 ++-- rustfmt.toml | 1 + src/bootstrap/Cargo.toml | 1 + src/bootstrap/format.rs | 61 ++++++++++++++++++++++++++++++---------- src/stage0.txt | 2 +- 5 files changed, 52 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6a2cc8476628c..4c819e88809b2 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 bb656891446a2..4e38aace15d1b 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 7be16cf3f171f..3ab00a6e147fc 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 0c542594effeb..e253e525526aa 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, +} + +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 2eb46e4e17bf2..494944720d9e8 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: #