From 8369a1a31a5c08e818283250d9e1cef3bfc04476 Mon Sep 17 00:00:00 2001 From: Adam Perry Date: Tue, 29 Oct 2019 08:33:11 -0700 Subject: [PATCH 1/7] Add individual crates to rustfmt ignore list. Co-Authored-By: Mark Rousskov --- rustfmt.toml | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/rustfmt.toml b/rustfmt.toml index df230cde9b7..a25324273f2 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -4,3 +4,86 @@ # be picked up automatically). version = "Two" use_small_heuristics = "Max" + +# by default we ignore everything in the repository +# tidy only checks files which are not ignored, each entry follows gitignore style +ignore = [ + # remove directories below, or opt out their subdirectories, as they are formatted + "src/bootstrap/", + "src/build_helper/", + "src/liballoc/", + "src/libarena/", + "src/libcore/", + "src/libfmt_macros/", + "src/libgraphviz/", + "src/libpanic_abort/", + "src/libpanic_unwind/", + "src/libproc_macro/", + "src/libprofiler_builtins/", + "src/librustc/", + "src/librustc_apfloat/", + "src/librustc_asan/", + "src/librustc_codegen_llvm/", + "src/librustc_codegen_ssa/", + "src/librustc_codegen_utils/", + "src/librustc_data_structures/", + "src/librustc_driver/", + "src/librustc_errors/", + "src/librustc_fs_util/", + "src/librustc_feature/", + "src/librustc_incremental/", + "src/librustc_index/", + "src/librustc_interface/", + "src/librustc_lexer/", + "src/librustc_lint/", + "src/librustc_llvm/", + "src/librustc_lsan/", + "src/librustc_macros/", + "src/librustc_metadata/", + "src/librustc_mir/", + "src/librustc_msan/", + "src/librustc_parse/", + "src/librustc_passes/", + "src/librustc_plugin/", + "src/librustc_plugin_impl/", + "src/librustc_privacy/", + "src/librustc_resolve/", + "src/librustc_save_analysis/", + "src/librustc_session/", + "src/librustc_target/", + "src/librustc_traits/", + "src/librustc_tsan/", + "src/librustc_typeck/", + "src/librustdoc/", + "src/libserialize/", + "src/libstd/", + "src/libsyntax/", + "src/libsyntax_expand/", + "src/libsyntax_ext/", + "src/libsyntax_pos/", + "src/libterm/", + "src/libtest/", + "src/libunwind/", + "src/rtstartup/", + "src/rustc/", + "src/rustllvm/", + "src/test/", + "src/tools/", + + # do not format submodules + "src/doc/book", + "src/doc/edition-guide", + "src/doc/embedded-book", + "src/doc/nomicon", + "src/doc/reference", + "src/doc/rust-by-example", + "src/doc/rustc-guide", + "src/llvm-project", + "src/stdarch", + "src/tools/cargo", + "src/tools/clippy", + "src/tools/miri", + "src/tools/rls", + "src/tools/rust-installer", + "src/tools/rustfmt", +] From 72a844dee7a095f34ead247fd38d9eb03686a722 Mon Sep 17 00:00:00 2001 From: Adam Perry Date: Tue, 29 Oct 2019 19:43:37 -0700 Subject: [PATCH 2/7] bootstrap.py fetches rustfmt. Co-Authored-By: Mark Rousskov --- src/bootstrap/bootstrap.py | 45 ++++++++++++++++++++++++++++++--- src/bootstrap/bootstrap_test.py | 4 +-- src/stage0.txt | 5 ++++ 3 files changed, 49 insertions(+), 5 deletions(-) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index bb169414886..6737086f6e5 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -322,6 +322,7 @@ class RustBuild(object): self.date = '' self._download_url = '' self.rustc_channel = '' + self.rustfmt_channel = '' self.build = '' self.build_dir = os.path.join(os.getcwd(), "build") self.clean = False @@ -344,6 +345,7 @@ class RustBuild(object): """ rustc_channel = self.rustc_channel cargo_channel = self.cargo_channel + rustfmt_channel = self.rustfmt_channel def support_xz(): try: @@ -393,13 +395,29 @@ class RustBuild(object): with output(self.cargo_stamp()) as cargo_stamp: cargo_stamp.write(self.date) - def _download_stage0_helper(self, filename, pattern, tarball_suffix): + if self.rustfmt() and self.rustfmt().startswith(self.bin_root()) and ( + not os.path.exists(self.rustfmt()) + or self.program_out_of_date(self.rustfmt_stamp()) + ): + if rustfmt_channel: + tarball_suffix = '.tar.xz' if support_xz() else '.tar.gz' + [channel, date] = rustfmt_channel.split('-', 1) + filename = "rustfmt-{}-{}{}".format(channel, self.build, tarball_suffix) + self._download_stage0_helper(filename, "rustfmt-preview", tarball_suffix, date) + self.fix_executable("{}/bin/rustfmt".format(self.bin_root())) + self.fix_executable("{}/bin/cargo-fmt".format(self.bin_root())) + with output(self.rustfmt_stamp()) as rustfmt_stamp: + rustfmt_stamp.write(self.date) + + def _download_stage0_helper(self, filename, pattern, tarball_suffix, date=None): + if date is None: + date = self.date cache_dst = os.path.join(self.build_dir, "cache") - rustc_cache = os.path.join(cache_dst, self.date) + rustc_cache = os.path.join(cache_dst, date) if not os.path.exists(rustc_cache): os.makedirs(rustc_cache) - url = "{}/dist/{}".format(self._download_url, self.date) + url = "{}/dist/{}".format(self._download_url, date) tarball = os.path.join(rustc_cache, filename) if not os.path.exists(tarball): get("{}/{}".format(url, filename), tarball, verbose=self.verbose) @@ -493,6 +511,16 @@ class RustBuild(object): """ return os.path.join(self.bin_root(), '.cargo-stamp') + def rustfmt_stamp(self): + """Return the path for .rustfmt-stamp + + >>> rb = RustBuild() + >>> rb.build_dir = "build" + >>> rb.rustfmt_stamp() == os.path.join("build", "stage0", ".rustfmt-stamp") + True + """ + return os.path.join(self.bin_root(), '.rustfmt-stamp') + def program_out_of_date(self, stamp_path): """Check if the given program stamp is out of date""" if not os.path.exists(stamp_path) or self.clean: @@ -565,6 +593,12 @@ class RustBuild(object): """Return config path for rustc""" return self.program_config('rustc') + def rustfmt(self): + """Return config path for rustfmt""" + if not self.rustfmt_channel: + return None + return self.program_config('rustfmt') + def program_config(self, program): """Return config path for the given program @@ -868,6 +902,9 @@ def bootstrap(help_triggered): build.rustc_channel = data['rustc'] build.cargo_channel = data['cargo'] + if "rustfmt" in data: + build.rustfmt_channel = data['rustfmt'] + if 'dev' in data: build.set_dev_environment() else: @@ -895,6 +932,8 @@ def bootstrap(help_triggered): env["RUSTC_BOOTSTRAP"] = '1' env["CARGO"] = build.cargo() env["RUSTC"] = build.rustc() + if build.rustfmt(): + env["RUSTFMT"] = build.rustfmt() run(args, env=env, verbose=build.verbose) diff --git a/src/bootstrap/bootstrap_test.py b/src/bootstrap/bootstrap_test.py index 689298f32d0..0e941e13676 100644 --- a/src/bootstrap/bootstrap_test.py +++ b/src/bootstrap/bootstrap_test.py @@ -20,14 +20,14 @@ class Stage0DataTestCase(unittest.TestCase): os.mkdir(os.path.join(self.rust_root, "src")) with open(os.path.join(self.rust_root, "src", "stage0.txt"), "w") as stage0: - stage0.write("#ignore\n\ndate: 2017-06-15\nrustc: beta\ncargo: beta") + stage0.write("#ignore\n\ndate: 2017-06-15\nrustc: beta\ncargo: beta\nrustfmt: beta") def tearDown(self): rmtree(self.rust_root) def test_stage0_data(self): """Extract data from stage0.txt""" - expected = {"date": "2017-06-15", "rustc": "beta", "cargo": "beta"} + expected = {"date": "2017-06-15", "rustc": "beta", "cargo": "beta", "rustfmt": "beta"} data = bootstrap.stage0_data(self.rust_root) self.assertDictEqual(data, expected) diff --git a/src/stage0.txt b/src/stage0.txt index 999218efa29..2eb46e4e17b 100644 --- a/src/stage0.txt +++ b/src/stage0.txt @@ -16,6 +16,11 @@ date: 2019-12-18 rustc: beta 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 + # When making a stable release the process currently looks like: # # 1. Produce stable build, upload it to dev-static From a08c56295ad132c8f2153f19439462b726452e22 Mon Sep 17 00:00:00 2001 From: Adam Perry Date: Wed, 30 Oct 2019 16:56:27 -0700 Subject: [PATCH 3/7] Implement `./x.py fmt [--check]`. --- src/bootstrap/builder.rs | 5 +++-- src/bootstrap/config.rs | 11 +++++++++-- src/bootstrap/flags.rs | 26 +++++++++++++++++++++++++- src/bootstrap/format.rs | 28 ++++++++++++++++++++++++++++ src/bootstrap/lib.rs | 5 +++++ 5 files changed, 70 insertions(+), 5 deletions(-) create mode 100644 src/bootstrap/format.rs diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 2093a49c6f9..bd0462fca6d 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -314,6 +314,7 @@ pub enum Kind { Check, Clippy, Fix, + Format, Test, Bench, Dist, @@ -353,7 +354,7 @@ impl<'a> Builder<'a> { tool::Miri, native::Lld ), - Kind::Check | Kind::Clippy | Kind::Fix => describe!( + Kind::Check | Kind::Clippy | Kind::Fix | Kind::Format => describe!( check::Std, check::Rustc, check::Rustdoc @@ -514,7 +515,7 @@ impl<'a> Builder<'a> { Subcommand::Bench { ref paths, .. } => (Kind::Bench, &paths[..]), Subcommand::Dist { ref paths } => (Kind::Dist, &paths[..]), Subcommand::Install { ref paths } => (Kind::Install, &paths[..]), - Subcommand::Clean { .. } => panic!(), + Subcommand::Format { .. } | Subcommand::Clean { .. } => panic!(), }; let builder = Builder { diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 5f2ef01bd5c..3e67734e690 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -5,6 +5,7 @@ use std::collections::{HashMap, HashSet}; use std::env; +use std::ffi::OsString; use std::fs; use std::path::{Path, PathBuf}; use std::process; @@ -149,6 +150,7 @@ pub struct Config { // These are either the stage0 downloaded binaries or the locally installed ones. pub initial_cargo: PathBuf, pub initial_rustc: PathBuf, + pub initial_rustfmt: Option, pub out: PathBuf, } @@ -348,12 +350,16 @@ struct TomlTarget { impl Config { fn path_from_python(var_key: &str) -> PathBuf { match env::var_os(var_key) { - // Do not trust paths from Python and normalize them slightly (#49785). - Some(var_val) => Path::new(&var_val).components().collect(), + Some(var_val) => Self::normalize_python_path(var_val), _ => panic!("expected '{}' to be set", var_key), } } + /// Normalizes paths from Python slightly. We don't trust paths from Python (#49785). + fn normalize_python_path(path: OsString) -> PathBuf { + Path::new(&path).components().collect() + } + pub fn default_opts() -> Config { let mut config = Config::default(); config.llvm_optimize = true; @@ -380,6 +386,7 @@ impl Config { config.initial_rustc = Config::path_from_python("RUSTC"); config.initial_cargo = Config::path_from_python("CARGO"); + config.initial_rustfmt = env::var_os("RUSTFMT").map(Config::normalize_python_path); config } diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index 7b49cc0a929..b98e2c1bf24 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -53,6 +53,9 @@ pub enum Subcommand { Fix { paths: Vec, }, + Format { + check: bool, + }, Doc { paths: Vec, }, @@ -102,6 +105,7 @@ Subcommands: check Compile either the compiler or libraries, using cargo check clippy Run clippy fix Run cargo fix + fmt Run rustfmt test Build and run some test suites bench Build and run some benchmarks doc Build documentation @@ -160,6 +164,7 @@ To learn more about a subcommand, run `./x.py -h`" || (s == "check") || (s == "clippy") || (s == "fix") + || (s == "fmt") || (s == "test") || (s == "bench") || (s == "doc") @@ -222,6 +227,9 @@ To learn more about a subcommand, run `./x.py -h`" "clean" => { opts.optflag("", "all", "clean all build artifacts"); } + "fmt" => { + opts.optflag("", "check", "check formatting instead of applying."); + } _ => {} }; @@ -323,6 +331,17 @@ Arguments: ./x.py fix src/libcore src/libproc_macro", ); } + "fmt" => { + subcommand_help.push_str( + "\n +Arguments: + This subcommand optionally accepts a `--check` flag which succeeds if formatting is correct and + fails if it is not. For example: + + ./x.py fmt + ./x.py fmt --check", + ); + } "test" => { subcommand_help.push_str( "\n @@ -388,7 +407,7 @@ Arguments: let maybe_rules_help = Builder::get_help(&build, subcommand.as_str()); extra_help.push_str(maybe_rules_help.unwrap_or_default().as_str()); - } else if subcommand.as_str() != "clean" { + } else if !(subcommand.as_str() == "clean" || subcommand.as_str() == "fmt") { extra_help.push_str( format!( "Run `./x.py {} -h -v` to see a list of available paths.", @@ -439,6 +458,11 @@ Arguments: all: matches.opt_present("all"), } } + "fmt" => { + Subcommand::Format { + check: matches.opt_present("check"), + } + } "dist" => Subcommand::Dist { paths }, "install" => Subcommand::Install { paths }, _ => { diff --git a/src/bootstrap/format.rs b/src/bootstrap/format.rs new file mode 100644 index 00000000000..0c542594eff --- /dev/null +++ b/src/bootstrap/format.rs @@ -0,0 +1,28 @@ +//! Runs rustfmt on the repository. + +use crate::{util, Build}; +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"); + 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"); + + if check { + cmd.arg("--"); + cmd.arg("--check"); + } + + let status = cmd.status().expect("executing cargo-fmt"); + assert!(status.success(), "cargo-fmt errored with status {:?}", status); +} diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 080bef6853a..ff9a55afa29 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -147,6 +147,7 @@ mod builder; mod cache; mod tool; mod toolstate; +mod format; #[cfg(windows)] mod job; @@ -421,6 +422,10 @@ impl Build { job::setup(self); } + if let Subcommand::Format { check } = self.config.cmd { + return format::format(self, check); + } + if let Subcommand::Clean { all } = self.config.cmd { return clean::clean(self, all); } From 5f17b63dacabc45620d9021a033e064ccffa30c7 Mon Sep 17 00:00:00 2001 From: Adam Perry Date: Mon, 4 Nov 2019 08:28:40 -0800 Subject: [PATCH 4/7] Format src/librustc_fs_util. In total it's about 100 lines of code and has received less than 5 commits in 2019 -- a good starting point. --- rustfmt.toml | 1 - src/librustc_fs_util/lib.rs | 37 +++++++++++++++++-------------------- 2 files changed, 17 insertions(+), 21 deletions(-) diff --git a/rustfmt.toml b/rustfmt.toml index a25324273f2..bb656891446 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -29,7 +29,6 @@ ignore = [ "src/librustc_data_structures/", "src/librustc_driver/", "src/librustc_errors/", - "src/librustc_fs_util/", "src/librustc_feature/", "src/librustc_incremental/", "src/librustc_index/", diff --git a/src/librustc_fs_util/lib.rs b/src/librustc_fs_util/lib.rs index eaf08d76b99..289b9f30c3b 100644 --- a/src/librustc_fs_util/lib.rs +++ b/src/librustc_fs_util/lib.rs @@ -1,7 +1,7 @@ -use std::path::{Path, PathBuf}; use std::ffi::CString; use std::fs; use std::io; +use std::path::{Path, PathBuf}; // Unfortunately, on windows, it looks like msvcrt.dll is silently translating // verbatim paths under the hood to non-verbatim paths! This manifests itself as @@ -21,8 +21,8 @@ use std::io; // https://github.com/rust-lang/rust/issues/25505#issuecomment-102876737 #[cfg(windows)] pub fn fix_windows_verbatim_for_gcc(p: &Path) -> PathBuf { - use std::path; use std::ffi::OsString; + use std::path; let mut components = p.components(); let prefix = match components.next() { Some(path::Component::Prefix(p)) => p, @@ -68,12 +68,10 @@ pub fn link_or_copy, Q: AsRef>(p: P, q: Q) -> io::Result
  • Ok(LinkOrCopy::Link), - Err(_) => { - match fs::copy(p, q) { - Ok(_) => Ok(LinkOrCopy::Copy), - Err(e) => Err(e), - } - } + Err(_) => match fs::copy(p, q) { + Ok(_) => Ok(LinkOrCopy::Copy), + Err(e) => Err(e), + }, } } @@ -86,29 +84,28 @@ pub enum RenameOrCopyRemove { /// Rename `p` into `q`, preferring to use `rename` if possible. /// If `rename` fails (rename may fail for reasons such as crossing /// filesystem), fallback to copy & remove -pub fn rename_or_copy_remove, Q: AsRef>(p: P, - q: Q) - -> io::Result { +pub fn rename_or_copy_remove, Q: AsRef>( + p: P, + q: Q, +) -> io::Result { let p = p.as_ref(); let q = q.as_ref(); match fs::rename(p, q) { Ok(()) => Ok(RenameOrCopyRemove::Rename), - Err(_) => { - match fs::copy(p, q) { - Ok(_) => { - fs::remove_file(p)?; - Ok(RenameOrCopyRemove::CopyRemove) - } - Err(e) => Err(e), + Err(_) => match fs::copy(p, q) { + Ok(_) => { + fs::remove_file(p)?; + Ok(RenameOrCopyRemove::CopyRemove) } - } + Err(e) => Err(e), + }, } } #[cfg(unix)] pub fn path_to_c_string(p: &Path) -> CString { - use std::os::unix::ffi::OsStrExt; use std::ffi::OsStr; + use std::os::unix::ffi::OsStrExt; let p: &OsStr = p.as_ref(); CString::new(p.as_bytes()).unwrap() } From 2b081abe944a7915013e15ae602ac8cfe9f52a77 Mon Sep 17 00:00:00 2001 From: Adam Perry Date: Wed, 30 Oct 2019 19:23:50 -0700 Subject: [PATCH 5/7] Include formatting check in the test step for tidy. --- src/bootstrap/test.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index f3b2a73d3c5..17aea17e69e 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -779,6 +779,9 @@ impl Step for Tidy { /// This tool in `src/tools` checks up on various bits and pieces of style and /// otherwise just implements a few lint-like checks that are specific to the /// compiler itself. + /// + /// Once tidy passes, this step also runs `fmt --check` if tests are being run + /// for the `dev` or `nightly` channels. fn run(self, builder: &Builder<'_>) { let mut cmd = builder.tool_cmd(Tool::Tidy); cmd.arg(builder.src.join("src")); @@ -792,6 +795,11 @@ impl Step for Tidy { builder.info("tidy check"); try_run(builder, &mut cmd); + + if builder.config.channel == "dev" || builder.config.channel == "nightly" { + builder.info("fmt check"); + crate::format::format(&builder.build, true); + } } fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { From dddd8724271a2a38ce552f5b1062a7ea070ec126 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Wed, 18 Dec 2019 10:52:10 -0500 Subject: [PATCH 6/7] 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 | 63 ++++++++++++++++++++++++++++++---------- src/stage0.txt | 2 +- 5 files changed, 53 insertions(+), 19 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"); } - - 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, +} + +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); + } + } } 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: # From b9e4174d8cf03fdcd0f9f128422b1f565d6b6607 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sun, 22 Dec 2019 07:44:09 -0500 Subject: [PATCH 7/7] Do not run if rustfmt.toml does not exist distcheck (and generally publishing tarballs) will not package rustfmt.toml and we for now still support running tidy etc in those tarballs. --- src/bootstrap/format.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/format.rs b/src/bootstrap/format.rs index e253e525526..c8ae2f4e688 100644 --- a/src/bootstrap/format.rs +++ b/src/bootstrap/format.rs @@ -37,8 +37,13 @@ pub fn format(build: &Build, check: bool) { 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 = 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 {