diff options
| author | xFrednet <xFrednet@gmail.com> | 2021-06-11 01:05:51 +0200 |
|---|---|---|
| committer | flip1995 <philipp.krones@embecosm.com> | 2021-06-25 11:16:59 +0200 |
| commit | 0a5f28c4b0c78c030956afe77b7a5c0c3e33ef5b (patch) | |
| tree | 02ce45765b6286d7991ad67d7e61815fff505b3a /clippy_dev/src/setup | |
| parent | 0941d9f14d9c446f9d7a465485652a3dc131de1e (diff) | |
Added `cargo dev setup git-hook`
Diffstat (limited to 'clippy_dev/src/setup')
| -rw-r--r-- | clippy_dev/src/setup/git_hook.rs | 61 | ||||
| -rw-r--r-- | clippy_dev/src/setup/mod.rs | 31 |
2 files changed, 91 insertions, 1 deletions
diff --git a/clippy_dev/src/setup/git_hook.rs b/clippy_dev/src/setup/git_hook.rs new file mode 100644 index 00000000000..741738e37fb --- /dev/null +++ b/clippy_dev/src/setup/git_hook.rs @@ -0,0 +1,61 @@ +use std::fs; +use std::path::Path; + +/// Rusts setup uses `git rev-parse --git-common-dir` to get the root directory of the repo. +/// I've decided against this for the sake of simplicity and to make sure that it doesn't install +/// the hook if `clippy_dev` would be used in the rust tree. The hook also references this tool +/// for formatting and should therefor only be used in a normal clone of clippy +const REPO_GIT_DIR: &str = ".git"; +const HOOK_SOURCE_PATH: &str = "util/etc/pre-commit.sh"; +const HOOK_TARGET_PATH: &str = ".git/hooks/pre-commit"; + +pub fn run(force_override: bool) { + if let Err(_) = check_precondition(force_override) { + return; + } + + // So a little bit of a funny story. Git on unix requires the pre-commit file + // to have the `execute` permission to be set. The Rust functions for modifying + // these flags doesn't seem to work when executed with normal user permissions. + // + // However, there is a little hack that is also being used by Rust itself in their + // setup script. Git saves the `execute` flag when syncing files. This means + // that we can check in a file with execution permissions and the sync it to create + // a file with the flag set. We then copy this file here. The copy function will also + // include the `execute` permission. + match fs::copy(HOOK_SOURCE_PATH, HOOK_TARGET_PATH) { + Ok(_) => println!("Git hook successfully installed :)"), + Err(err) => println!( + "error: unable to copy `{}` to `{}` ({})", + HOOK_SOURCE_PATH, HOOK_TARGET_PATH, err + ), + } +} + +fn check_precondition(force_override: bool) -> Result<(), ()> { + // Make sure that we can find the git repository + let git_path = Path::new(REPO_GIT_DIR); + if !git_path.exists() || !git_path.is_dir() { + println!("error: clippy_dev was unable to find the `.git` directory"); + return Err(()); + } + + // Make sure that we don't override an existing hook by accident + let path = Path::new(HOOK_TARGET_PATH); + if path.exists() { + if !force_override { + println!("warn: The found `.git` directory already has a commit hook"); + } + + if force_override || super::ask_yes_no_question("Do you want to override it?") { + if fs::remove_file(path).is_err() { + println!("error: unable to delete existing pre-commit git hook"); + return Err(()); + } + } else { + return Err(()); + } + } + + Ok(()) +} diff --git a/clippy_dev/src/setup/mod.rs b/clippy_dev/src/setup/mod.rs index cab4e386fc2..5db545c0ff1 100644 --- a/clippy_dev/src/setup/mod.rs +++ b/clippy_dev/src/setup/mod.rs @@ -1 +1,30 @@ -pub mod intellij; \ No newline at end of file +use std::io::{self, Write}; +pub mod git_hook; +pub mod intellij; + +/// This function will asked the user the given question and wait for user input +/// either `true` for yes and `false` for no. +fn ask_yes_no_question(question: &str) -> bool { + // This code was proudly stolen from rusts bootstrapping tool. + + fn ask_with_result(question: &str) -> io::Result<bool> { + let mut input = String::new(); + Ok(loop { + print!("{}: [y/N] ", question); + io::stdout().flush()?; + input.clear(); + io::stdin().read_line(&mut input)?; + break match input.trim().to_lowercase().as_str() { + "y" | "yes" => true, + "n" | "no" | "" => false, + _ => { + println!("error: unrecognized option '{}'", input.trim()); + println!("note: press Ctrl+C to exit"); + continue; + }, + }; + }) + } + + ask_with_result(question).unwrap_or_default() +} |
