From a009e2838b25df2761093d727d322a59f69d8f68 Mon Sep 17 00:00:00 2001 From: Cassandra Fridkin Date: Fri, 4 Sep 2020 21:00:58 -0400 Subject: [PATCH 1/6] There isn't a way to pass --remove yet, but you can rm if u like --- Cargo.lock | 4 ++++ Cargo.toml | 1 + src/bootstrap/builder.rs | 2 +- src/bootstrap/run.rs | 24 ++++++++++++++++++++ src/bootstrap/tool.rs | 1 + src/tools/install-git-hook/Cargo.toml | 5 ++++ src/tools/install-git-hook/src/main.rs | 16 +++++++++++++ src/tools/install-git-hook/src/pre-commit.sh | 18 +++++++++++++++ 8 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 src/tools/install-git-hook/Cargo.toml create mode 100644 src/tools/install-git-hook/src/main.rs create mode 100755 src/tools/install-git-hook/src/pre-commit.sh diff --git a/Cargo.lock b/Cargo.lock index f94d95d2dc838..4e6c1fca35123 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1407,6 +1407,10 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "install-git-hook" +version = "0.1.0" + [[package]] name = "installer" version = "0.0.0" diff --git a/Cargo.toml b/Cargo.toml index fde1cb5a35c2e..4156ef8f124a7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,7 @@ members = [ "src/tools/clippy", "src/tools/compiletest", "src/tools/error_index_generator", + "src/tools/install-git-hook", "src/tools/linkchecker", "src/tools/rustbook", "src/tools/unstable-book-gen", diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index cecc9ef75ea86..0a7df6e595c6c 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -487,7 +487,7 @@ impl<'a> Builder<'a> { install::Src, install::Rustc ), - Kind::Run => describe!(run::ExpandYamlAnchors,), + Kind::Run => describe!(run::ExpandYamlAnchors, run::InstallGitHook), } } diff --git a/src/bootstrap/run.rs b/src/bootstrap/run.rs index 900534714277c..34170898a548f 100644 --- a/src/bootstrap/run.rs +++ b/src/bootstrap/run.rs @@ -41,3 +41,27 @@ fn try_run(builder: &Builder<'_>, cmd: &mut Command) -> bool { } true } + +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct InstallGitHook; + +impl Step for InstallGitHook { + type Output = (); + + /// Runs the `install-git-hook` tool. + /// + /// This tool in `src/tools` installs a git hook to automatically run + /// `tidy --bless` before each commit, so you don't forget to do it + fn run(self, builder: &Builder<'_>) { + builder.info("Installing git hook"); + try_run(builder, &mut builder.tool_cmd(Tool::InstallGitHook).arg(&builder.src)); + } + + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + run.path("src/tools/install-git-hook") + } + + fn make_run(run: RunConfig<'_>) { + run.builder.ensure(InstallGitHook); + } +} diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index fe3f1e78029d7..5d9bdc9d843f0 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -365,6 +365,7 @@ bootstrap_tool!( RustInstaller, "src/tools/rust-installer", "fabricate", is_external_tool = true; RustdocTheme, "src/tools/rustdoc-themes", "rustdoc-themes"; ExpandYamlAnchors, "src/tools/expand-yaml-anchors", "expand-yaml-anchors"; + InstallGitHook, "src/tools/install-git-hook", "install-git-hook"; ); #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Ord, PartialOrd)] diff --git a/src/tools/install-git-hook/Cargo.toml b/src/tools/install-git-hook/Cargo.toml new file mode 100644 index 0000000000000..1b089a84da880 --- /dev/null +++ b/src/tools/install-git-hook/Cargo.toml @@ -0,0 +1,5 @@ +[package] +name = "install-git-hook" +version = "0.1.0" +authors = ["Cass Fridkin "] +edition = "2018" \ No newline at end of file diff --git a/src/tools/install-git-hook/src/main.rs b/src/tools/install-git-hook/src/main.rs new file mode 100644 index 0000000000000..64b5233dfb398 --- /dev/null +++ b/src/tools/install-git-hook/src/main.rs @@ -0,0 +1,16 @@ +//! Small helper program to install a git hook to automatically run +//! `x.py test tidy --bless` before each commit. + +use std::env; +use std::fs; +use std::path::PathBuf; + +fn main() { + let root_path: PathBuf = env::args_os().nth(1).expect("need path to root of repo").into(); + let script_path: PathBuf = root_path.join("src/tools/install-git-hook/src/pre-commit.sh"); + let hook_path: PathBuf = root_path.join(".git/hooks/pre-commit"); + + fs::copy(&script_path, &hook_path).expect( + format!("Failed to copy pre-commit script to {}", &hook_path.to_string_lossy()).as_str(), + ); +} diff --git a/src/tools/install-git-hook/src/pre-commit.sh b/src/tools/install-git-hook/src/pre-commit.sh new file mode 100755 index 0000000000000..f47ca3e039ac9 --- /dev/null +++ b/src/tools/install-git-hook/src/pre-commit.sh @@ -0,0 +1,18 @@ +#!/bin/sh +# +# Call `tidy --bless` before each commit +# +# To enable this hook, run `./x.py run install-git-hook`. +# To disable it, run `./x.py run install-git-hook --remove` +set -Eeuo pipefail + +ROOT_DIR=$(git rev-parse --show-toplevel); +COMMAND="$ROOT_DIR/x.py test tidy --bless"; + +if [[ "$OSTYPE" == "msys" || "$OSTYPE" == "win32" ]]; then + COMMAND="python $COMMAND" +fi + +echo "Running pre-commit script $COMMAND"; + +$COMMAND; From 7de557bf9c550623ce6493b8af940cb9b08c2293 Mon Sep 17 00:00:00 2001 From: Cassandra Fridkin Date: Mon, 5 Oct 2020 18:57:48 -0400 Subject: [PATCH 2/6] Move script to src/etc --- .../install-git-hook/src => etc}/pre-commit.sh | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) rename src/{tools/install-git-hook/src => etc}/pre-commit.sh (50%) diff --git a/src/tools/install-git-hook/src/pre-commit.sh b/src/etc/pre-commit.sh similarity index 50% rename from src/tools/install-git-hook/src/pre-commit.sh rename to src/etc/pre-commit.sh index f47ca3e039ac9..32af70ec8d40e 100755 --- a/src/tools/install-git-hook/src/pre-commit.sh +++ b/src/etc/pre-commit.sh @@ -1,12 +1,16 @@ -#!/bin/sh +#!/bin/env bash # # Call `tidy --bless` before each commit +# Copy this scripts to .git/hooks to activate, +# and remove it from .git/hooks to deactivate. # -# To enable this hook, run `./x.py run install-git-hook`. -# To disable it, run `./x.py run install-git-hook --remove` +# For help running bash scripts on Windows, +# see https://stackoverflow.com/a/6413405/6894799 +# + set -Eeuo pipefail -ROOT_DIR=$(git rev-parse --show-toplevel); +ROOT_DIR="$(git rev-parse --show-toplevel)"; COMMAND="$ROOT_DIR/x.py test tidy --bless"; if [[ "$OSTYPE" == "msys" || "$OSTYPE" == "win32" ]]; then From f53d43663814f63f1979c27085abb27aa9a183df Mon Sep 17 00:00:00 2001 From: Cassandra Fridkin Date: Mon, 5 Oct 2020 18:59:47 -0400 Subject: [PATCH 3/6] Remove the rust stuff and just make it a simple shell script It's ok, now I'm writing enough Rust that i'm able to get my fix elsewhere --- Cargo.lock | 4 ---- Cargo.toml | 1 - src/bootstrap/builder.rs | 2 +- src/bootstrap/run.rs | 23 ----------------------- src/bootstrap/tool.rs | 1 - src/tools/install-git-hook/Cargo.toml | 5 ----- src/tools/install-git-hook/src/main.rs | 16 ---------------- 7 files changed, 1 insertion(+), 51 deletions(-) delete mode 100644 src/tools/install-git-hook/Cargo.toml delete mode 100644 src/tools/install-git-hook/src/main.rs diff --git a/Cargo.lock b/Cargo.lock index 6bff377a660ee..d216b09c66a60 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1458,10 +1458,6 @@ dependencies = [ "hashbrown", ] -[[package]] -name = "install-git-hook" -version = "0.1.0" - [[package]] name = "installer" version = "0.0.0" diff --git a/Cargo.toml b/Cargo.toml index 35e26695bdcab..02794d1028b50 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,6 @@ members = [ "src/tools/clippy", "src/tools/compiletest", "src/tools/error_index_generator", - "src/tools/install-git-hook", "src/tools/linkchecker", "src/tools/lint-docs", "src/tools/rustbook", diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 1359b16285395..4bc162abee6c1 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -477,7 +477,7 @@ impl<'a> Builder<'a> { install::Src, install::Rustc ), - Kind::Run => describe!(run::ExpandYamlAnchors, run::BuildManifest, run::InstallGitHook), + Kind::Run => describe!(run::ExpandYamlAnchors, run::BuildManifest), } } diff --git a/src/bootstrap/run.rs b/src/bootstrap/run.rs index da34d8b9d70be..80c093e713eff 100644 --- a/src/bootstrap/run.rs +++ b/src/bootstrap/run.rs @@ -44,29 +44,6 @@ fn try_run(builder: &Builder<'_>, cmd: &mut Command) -> bool { true } -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -pub struct InstallGitHook; - -impl Step for InstallGitHook { - type Output = (); - - /// Runs the `install-git-hook` tool. - /// - /// This tool in `src/tools` installs a git hook to automatically run - /// `tidy --bless` before each commit, so you don't forget to do it - fn run(self, builder: &Builder<'_>) { - builder.info("Installing git hook"); - try_run(builder, &mut builder.tool_cmd(Tool::InstallGitHook).arg(&builder.src)); - } - - fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.path("src/tools/install-git-hook") - } - - fn make_run(run: RunConfig<'_>) { - run.builder.ensure(InstallGitHook); - } -} #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)] pub struct BuildManifest; diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 790e324a55f0c..290e3744852f4 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -366,7 +366,6 @@ bootstrap_tool!( RustInstaller, "src/tools/rust-installer", "fabricate", is_external_tool = true; RustdocTheme, "src/tools/rustdoc-themes", "rustdoc-themes"; ExpandYamlAnchors, "src/tools/expand-yaml-anchors", "expand-yaml-anchors"; - InstallGitHook, "src/tools/install-git-hook", "install-git-hook"; LintDocs, "src/tools/lint-docs", "lint-docs"; ); diff --git a/src/tools/install-git-hook/Cargo.toml b/src/tools/install-git-hook/Cargo.toml deleted file mode 100644 index 1b089a84da880..0000000000000 --- a/src/tools/install-git-hook/Cargo.toml +++ /dev/null @@ -1,5 +0,0 @@ -[package] -name = "install-git-hook" -version = "0.1.0" -authors = ["Cass Fridkin "] -edition = "2018" \ No newline at end of file diff --git a/src/tools/install-git-hook/src/main.rs b/src/tools/install-git-hook/src/main.rs deleted file mode 100644 index 64b5233dfb398..0000000000000 --- a/src/tools/install-git-hook/src/main.rs +++ /dev/null @@ -1,16 +0,0 @@ -//! Small helper program to install a git hook to automatically run -//! `x.py test tidy --bless` before each commit. - -use std::env; -use std::fs; -use std::path::PathBuf; - -fn main() { - let root_path: PathBuf = env::args_os().nth(1).expect("need path to root of repo").into(); - let script_path: PathBuf = root_path.join("src/tools/install-git-hook/src/pre-commit.sh"); - let hook_path: PathBuf = root_path.join(".git/hooks/pre-commit"); - - fs::copy(&script_path, &hook_path).expect( - format!("Failed to copy pre-commit script to {}", &hook_path.to_string_lossy()).as_str(), - ); -} From 68ca4742c58f97b4078357e297e963dec031a1a9 Mon Sep 17 00:00:00 2001 From: Cassandra Fridkin Date: Mon, 5 Oct 2020 19:35:06 -0400 Subject: [PATCH 4/6] Clean up pre-commit.sh --- src/etc/pre-commit.sh | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/etc/pre-commit.sh b/src/etc/pre-commit.sh index 32af70ec8d40e..5c5922a7e63ec 100755 --- a/src/etc/pre-commit.sh +++ b/src/etc/pre-commit.sh @@ -1,12 +1,9 @@ -#!/bin/env bash +#!/usr/bin/env bash # # Call `tidy --bless` before each commit # Copy this scripts to .git/hooks to activate, # and remove it from .git/hooks to deactivate. # -# For help running bash scripts on Windows, -# see https://stackoverflow.com/a/6413405/6894799 -# set -Eeuo pipefail @@ -17,6 +14,8 @@ if [[ "$OSTYPE" == "msys" || "$OSTYPE" == "win32" ]]; then COMMAND="python $COMMAND" fi -echo "Running pre-commit script $COMMAND"; +echo "Running pre-commit script '$COMMAND'"; + +cd "$ROOT_DIR" $COMMAND; From d585c96eaf5ba0d719b7385f15f241a4be765b20 Mon Sep 17 00:00:00 2001 From: Cassandra Fridkin Date: Mon, 5 Oct 2020 20:14:11 -0400 Subject: [PATCH 5/6] Add install_git_hook_maybe to setup.rs --- src/bootstrap/setup.rs | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/bootstrap/setup.rs b/src/bootstrap/setup.rs index 9d3a889aa008e..f5ec1d6d247d7 100644 --- a/src/bootstrap/setup.rs +++ b/src/bootstrap/setup.rs @@ -46,6 +46,8 @@ pub fn setup(src_path: &Path, include_name: &str) { _ => return, }; + t!(install_git_hook_maybe(src_path)); + println!("To get started, try one of the following commands:"); for cmd in suggestions { println!("- `x.py {}`", cmd); @@ -86,3 +88,41 @@ d) Install Rust from source" }; Ok(template.to_owned()) } + +// install a git hook to automatically run tidy --bless, if they want +fn install_git_hook_maybe(src_path: &Path) -> io::Result<()> { + let mut input = String::new(); + println!( + "Rust's CI will automatically fail if it doesn't pass `tidy`, the internal tool for ensuring code quality. +If you'd like, x.py can install a git hook for you that will automatically run `tidy --bless` on each commit +to ensure your code is up to par. If you decide later that this behavior is undesirable, +simply delete the `pre-commit` file from .git/hooks." + ); + + let should_install = loop { + print!("Would you like to install the git hook?: [y/N] "); + io::stdout().flush()?; + io::stdin().read_line(&mut input)?; + break match input.trim().to_lowercase().as_str() { + "y" | "yes" => true, + // is this the right way to check for "entered nothing"? + "n" | "no" | "" => false, + _ => { + println!("error: unrecognized option '{}'", input.trim()); + println!("note: press Ctrl+C to exit"); + continue; + } + }; + }; + + if should_install { + let src = src_path.join("/etc/pre-commit.rs"); + let dst = src_path.join("/.git/hooks/pre-commit"); + fs::hard_link(src, dst)?; + println!("Linked `src/etc/pre-commit.sh` to `.git/hooks/pre-commit`"); + } else { + println!("Ok, skipping installation!"); + }; + + Ok(()) +} From 0845627f73faa2322bc24421cf3dd1f5dd3005df Mon Sep 17 00:00:00 2001 From: Cassandra Fridkin Date: Mon, 5 Oct 2020 22:00:43 -0400 Subject: [PATCH 6/6] Make changes based on @jyn514's comments --- src/bootstrap/setup.rs | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/src/bootstrap/setup.rs b/src/bootstrap/setup.rs index f5ec1d6d247d7..cbf53dae80608 100644 --- a/src/bootstrap/setup.rs +++ b/src/bootstrap/setup.rs @@ -46,8 +46,12 @@ pub fn setup(src_path: &Path, include_name: &str) { _ => return, }; + println!(); + t!(install_git_hook_maybe(src_path)); + println!(); + println!("To get started, try one of the following commands:"); for cmd in suggestions { println!("- `x.py {}`", cmd); @@ -102,10 +106,10 @@ simply delete the `pre-commit` file from .git/hooks." let should_install = loop { print!("Would you like to install the git hook?: [y/N] "); io::stdout().flush()?; + input.clear(); io::stdin().read_line(&mut input)?; break match input.trim().to_lowercase().as_str() { "y" | "yes" => true, - // is this the right way to check for "entered nothing"? "n" | "no" | "" => false, _ => { println!("error: unrecognized option '{}'", input.trim()); @@ -115,14 +119,17 @@ simply delete the `pre-commit` file from .git/hooks." }; }; - if should_install { - let src = src_path.join("/etc/pre-commit.rs"); - let dst = src_path.join("/.git/hooks/pre-commit"); - fs::hard_link(src, dst)?; - println!("Linked `src/etc/pre-commit.sh` to `.git/hooks/pre-commit`"); + Ok(if should_install { + let src = src_path.join("src").join("etc").join("pre-commit.sh"); + let dst = src_path.join(".git").join("hooks").join("pre-commit"); + match fs::hard_link(src, dst) { + Err(e) => println!( + "x.py encountered an error -- do you already have the git hook installed?\n{}", + e + ), + Ok(_) => println!("Linked `src/etc/pre-commit.sh` to `.git/hooks/pre-commit`"), + }; } else { println!("Ok, skipping installation!"); - }; - - Ok(()) + }) }