From a08c56295ad132c8f2153f19439462b726452e22 Mon Sep 17 00:00:00 2001 From: Adam Perry Date: Wed, 30 Oct 2019 16:56:27 -0700 Subject: [PATCH] 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); }