diff --git a/Cargo.lock b/Cargo.lock index 0dbddc5..60b0c95 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,15 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi", - "libc", - "winapi", -] +version = 3 [[package]] name = "autocfg" @@ -17,57 +8,26 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" -[[package]] -name = "bitflags" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" - [[package]] name = "ci_info" -version = "0.14.2" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98f1c9ee4939df5d42c01815f1fb783ab203c1dea7cee5e051ede261c4049b1f" +checksum = "1f0e2864372242f01b92c1b882a904f6fb8b57f16e81e148a35b6368b1ea7323" dependencies = [ "envmnt", ] [[package]] -name = "clap" -version = "3.0.0-beta.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcd70aa5597dbc42f7217a543f9ef2768b2ef823ba29036072d30e1d88e98406" -dependencies = [ - "atty", - "bitflags", - "clap_derive", - "indexmap", - "lazy_static", - "os_str_bytes", - "strsim", - "termcolor", - "textwrap", - "vec_map", -] - -[[package]] -name = "clap_derive" -version = "3.0.0-beta.4" +name = "dunce" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b5bb0d655624a0b8770d1c178fb8ffcb1f91cc722cb08f451e3dc72465421ac" -dependencies = [ - "heck", - "proc-macro-error", - "proc-macro2", - "quote", - "syn", -] +checksum = "453440c271cf5577fd2a40e4942540cb7d0d2f85e27c8d07dd0023c925a67541" [[package]] name = "envmnt" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbfac51e9996e41d78a943227b7f313efcebf545b21584a0e213b956a062e11e" +checksum = "0f96dd862f12fac698dec3932dff0e6fb34bffeb5515ae5932d620cfe076571e" dependencies = [ "fsio", "indexmap", @@ -75,160 +35,59 @@ dependencies = [ [[package]] name = "fsio" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a50045aa8931ae01afbc5d72439e8f57f326becb8c70d07dfc816778eff3d167" - -[[package]] -name = "hashbrown" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00d63df3d41950fb462ed38308eea019113ad1508da725bbedcd0fa5a85ef5f7" +checksum = "09e87827efaf94c7a44b562ff57de06930712fe21b530c3797cdede26e6377eb" +dependencies = [ + "dunce", +] [[package]] -name = "heck" -version = "0.3.1" +name = "getopts" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" +checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" dependencies = [ - "unicode-segmentation", + "unicode-width", ] [[package]] -name = "hermit-abi" -version = "0.1.16" +name = "hashbrown" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c30f6d0bc6b00693347368a67d41b58f2fb851215ff1da49e90fe2c5c667151" -dependencies = [ - "libc", -] +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" [[package]] name = "indexmap" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55e2e4c765aa53a0424761bf9f41aa7a6ac1efa87238f59560640e27fca028f2" +checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5" dependencies = [ "autocfg", "hashbrown", ] -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "libc" -version = "0.2.77" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2f96b10ec2560088a8e76961b00d47107b3a625fecb76dedb29ee7ccbf98235" - [[package]] name = "nias" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0135fd396265547ac8bd1aa38616bd1b39d9e8e9d5c9c7d8ef72fc945ba5b122" -[[package]] -name = "os_str_bytes" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6acbef58a60fe69ab50510a55bc8cdd4d6cf2283d27ad338f54cb52747a9cf2d" - -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - -[[package]] -name = "proc-macro2" -version = "1.0.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c7ed8b8c7b886ea3ed7dde405212185f423ab44682667c8c6dd14aa1d9f6612" -dependencies = [ - "unicode-xid", -] - -[[package]] -name = "quote" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" -dependencies = [ - "proc-macro2", -] - [[package]] name = "rusty-hook" version = "0.12.0" dependencies = [ "ci_info", - "clap", + "getopts", "nias", "toml", ] [[package]] name = "serde" -version = "1.0.116" +version = "1.0.130" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96fe57af81d28386a513cbc6858332abc6117cfdb5999647c6444b8f43a370a5" - -[[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - -[[package]] -name = "syn" -version = "1.0.74" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1873d832550d4588c3dbc20f01361ab00bfe741048f71e3fecf145a7cc18b29c" -dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", -] - -[[package]] -name = "termcolor" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb6bfa289a4d7c5766392812c0a1f4c1ba45afa1ad47803c11e1f407d846d75f" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "textwrap" -version = "0.14.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80" -dependencies = [ - "unicode-width", -] +checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913" [[package]] name = "toml" @@ -239,63 +98,8 @@ dependencies = [ "serde", ] -[[package]] -name = "unicode-segmentation" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0" - [[package]] name = "unicode-width" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" - -[[package]] -name = "unicode-xid" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" - -[[package]] -name = "vec_map" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" - -[[package]] -name = "version_check" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-util" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" -dependencies = [ - "winapi", -] - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" diff --git a/Cargo.toml b/Cargo.toml index 9e7429f..54767cb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,8 +7,8 @@ license = "MIT" repository = "https://github.com/swellaby/rusty-hook" readme = "README.md" edition = "2018" -keywords = [ "hooks", "githook", "git", "hook", "commit" ] -categories = [ "development-tools" ] +keywords = ["hooks", "githook", "git", "hook", "commit"] +categories = ["development-tools"] exclude = [ ".coverage/**", ".testresults/**", @@ -32,9 +32,9 @@ exclude = [ [dependencies] ci_info = "0.14.2" -clap = "3.0.0-beta.4" -toml = "0.5.8" +getopts = "0.2.21" nias = "0.7.0" +toml = "0.5.8" [build-dependencies] ci_info = "0.14.2" @@ -42,6 +42,6 @@ toml = "0.5.8" nias = "0.7.0" [badges] -azure-devops = { project = "swellaby/opensource", pipeline = "rusty-hook.linux-pr", build="49" } +azure-devops = { project = "swellaby/opensource", pipeline = "rusty-hook.linux-pr", build = "49" } codecov = { repository = "swellaby/rusty-hook", branch = "master", service = "github" } maintenance = { status = "actively-developed" } diff --git a/build.rs b/build.rs index c40b15d..bda5e8e 100644 --- a/build.rs +++ b/build.rs @@ -2,8 +2,8 @@ #[path = "src/rusty_hook.rs"] mod rusty_hook; +use std::env; use std::process::exit; -use std::{env, vec}; fn main() { if ci_info::is_ci() { @@ -16,7 +16,7 @@ fn main() { nias::get_file_writer(), nias::get_file_existence_checker(), Some(&target_directory), - vec![], + &[], ) { println!( "Fatal error encountered during initialization. Details: {}", diff --git a/src/git.rs b/src/git.rs index 181253e..af37c35 100644 --- a/src/git.rs +++ b/src/git.rs @@ -47,7 +47,7 @@ pub fn setup_hooks( run_command: F, write_file: G, root_directory_path: &str, - hook_file_skip_list: &[&str], + hook_file_skip_list: &[String], ) -> Result<(), String> where F: Fn( diff --git a/src/hook_files/hook_script.sh b/src/hook_files/hook_script.sh index f5f7db8..a940a22 100644 --- a/src/hook_files/hook_script.sh +++ b/src/hook_files/hook_script.sh @@ -22,5 +22,5 @@ else fi # shellcheck disable=SC2046 -rusty-hook run --hook "${hookName}" $([ -z "$gitParams" ] && echo "" || echo "-- $gitParams") +rusty-hook run --hook "${hookName}" "${gitParams}" handleRustyHookCliResult $? "${hookName}" diff --git a/src/hooks.rs b/src/hooks.rs index 735f155..104f107 100644 --- a/src/hooks.rs +++ b/src/hooks.rs @@ -67,7 +67,7 @@ pub fn create_hook_files( write_file: F, root_directory_path: &str, hooks_directory: &str, - hook_file_skip_list: &[&str], + hook_file_skip_list: &[String], ) -> Result<(), String> where F: Fn(&str, &str, bool) -> Result<(), String>, @@ -75,7 +75,7 @@ where let hook_file_contents = get_hook_file_contents(); for hook in HOOK_NAMES .iter() - .filter(|h| !hook_file_skip_list.contains(h)) + .filter(|h| !hook_file_skip_list.contains(&h.to_string())) { let path = get_file_path(root_directory_path, hooks_directory, hook); if write_file(&path, &hook_file_contents, true).is_err() { diff --git a/src/hooks_test.rs b/src/hooks_test.rs index 2aab990..b9761f6 100644 --- a/src/hooks_test.rs +++ b/src/hooks_test.rs @@ -221,7 +221,12 @@ mod create_hook_files_tests { assert!(make_executable); Ok(()) }; - let result = create_hook_files(write_file, root_dir, git_hooks, &[EXP_SKIPPED_HOOK]); + let result = create_hook_files( + write_file, + root_dir, + git_hooks, + &[String::from(EXP_SKIPPED_HOOK)], + ); assert_eq!(result, Ok(())); } } diff --git a/src/main.rs b/src/main.rs index a90a145..11a5bf7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,58 +1,84 @@ use std::env; use std::process::exit; -use clap::Clap; +use getopts::{Matches, Options}; mod rusty_hook; -#[derive(Clap)] -#[clap(author, about, version)] -enum RustyHookOpts { - /// Initialize rusty-hook's git hooks in the current directory. - #[clap(author, version)] - Init { - #[clap(long)] - skip_hook_list: Option, - }, - /// Print the current version of rusty-hook. - #[clap(author, version, alias = "-v")] - Version, - /// Run a git hook using the current directory's configuration. - /// Ran automatically by rusty-hook's git hooks. - #[clap(author, version)] - Run { - #[clap(long)] - hook: String, - #[clap(name = "git args", raw(true))] - args: Option, - }, +const INIT_BRIEF: &str = r#" +Usage: + rusty-hook init +"#; +const RUN_BRIEF: &str = r#" +Usage: + rusty-hook run --hook [NAME] [git_args] + +Args: + Arguments that will replace "%rh!" token in hook +"#; +const DEFAULT_BRIEF: &str = r#" +Usage: + rusty-hook + +Subcommands: + run Run a git hook using the current directory's configuration. Ran automatically by rusty-hook's git hooks + init Initialize rusty-hook's git hooks in the current directory +"#; + +fn print_version() { + println!(env!("CARGO_PKG_VERSION")); +} + +fn print_usage(brief: &str, opts: &Options) { + print!("{}", opts.usage(brief)); +} + +fn parse_list_args(opts: &Options, args: &[String]) -> Matches { + match opts.parse(args) { + Ok(m) => m, + Err(e) => { + eprintln!("{}", e); + exit(1); + } + } } -fn init(skip_hook_list: Option) { +fn init(matches: Matches) { if ci_info::is_ci() { println!("[rusty-hook] CI Environment detected. Skipping hook install"); exit(0); } - let skip_hook_list = skip_hook_list - .as_deref() - .map_or(vec![], |s| s.split(',').collect()); + let skip_hook_list = matches.free; if let Err(err) = rusty_hook::init( nias::get_command_runner(), nias::get_file_writer(), nias::get_file_existence_checker(), - skip_hook_list, + &skip_hook_list, ) { eprintln!( - "[rusty-hook] Fatal error encountered during initialization. Details: {}", + "[rusty] Fatal error encountered during initialization. Details: {}", err ); exit(1); }; } -fn run(hook: String, args: Option) { +fn run(matches: Matches) { + if !matches.opt_present("hook") { + eprintln!("Hook name option missing"); + exit(1); + } + + let hook = matches.opt_str("hook").unwrap(); + + let args = if matches.free.is_empty() { + None + } else { + Some(matches.free.join(" ")) + }; + if let Err(err) = rusty_hook::run( nias::get_command_runner(), nias::get_file_existence_checker(), @@ -74,11 +100,54 @@ fn run(hook: String, args: Option) { } } +fn parse_args(args: &[String], opts: &mut Options) -> (Matches, String) { + let first_opt = &args[1]; + + let (arg_slice, brief_ref) = match first_opt.as_ref() { + "init" => { + opts.optopt( + "", + "skip_hook_list", + "A hook that should be skipped", + "SKIP_HOOK_LIST", + ); + + (&args[2..], INIT_BRIEF) + } + "run" => { + opts.optopt("", "hook", "The git hook name", "NAME"); + + (&args[2..], RUN_BRIEF) + } + _ => (&args[1..], DEFAULT_BRIEF), + }; + + let matches = parse_list_args(opts, arg_slice); + + (matches, brief_ref.to_string()) +} + fn main() { - let opts = RustyHookOpts::parse(); - match opts { - RustyHookOpts::Init { skip_hook_list } => init(skip_hook_list), - RustyHookOpts::Version => println!(env!("CARGO_PKG_VERSION")), - RustyHookOpts::Run { hook, args } => run(hook, args), + let args: Vec = env::args().collect(); + let mut opts = Options::new(); + opts.optflag("h", "help", "Print help information"); + opts.optflag("V", "version", "Print version information"); + + let (matches, brief) = parse_args(&args, &mut opts); + + if matches.opt_present("h") { + print_usage(&brief, &opts); + exit(0) + }; + + if matches.opt_present("V") { + print_version(); + exit(0) + }; + + match args[1].as_ref() { + "init" => init(matches), + "run" => run(matches), + cmd => eprintln!("Unknown command: {}", cmd), } } diff --git a/src/rusty_hook.rs b/src/rusty_hook.rs index 0e1b94c..e014518 100644 --- a/src/rusty_hook.rs +++ b/src/rusty_hook.rs @@ -13,7 +13,7 @@ pub fn init_directory( write_file: G, file_exists: H, target_directory: Option<&str>, - hook_file_skip_list: Vec<&str>, + hook_file_skip_list: &[String], ) -> Result<(), String> where F: Fn( @@ -33,7 +33,7 @@ where &run_command, &write_file, &root_directory_path, - &hook_file_skip_list, + hook_file_skip_list, ) .is_err() { @@ -52,7 +52,7 @@ pub fn init( run_command: F, write_file: G, file_exists: H, - hook_file_skip_list: Vec<&str>, + hook_file_skip_list: &[String], ) -> Result<(), String> where F: Fn( diff --git a/src/rusty_hook_test.rs b/src/rusty_hook_test.rs index 6b21cc6..46776c2 100644 --- a/src/rusty_hook_test.rs +++ b/src/rusty_hook_test.rs @@ -39,7 +39,7 @@ mod init_directory_tests { panic!("Should not get here"); }; let file_exists = |_path: &str| panic!("Should not get here"); - let result = init(run_command, write_file, file_exists, vec![]); + let result = init(run_command, write_file, file_exists, &[]); assert_eq!(result, Err(String::from(exp_err))); } @@ -48,7 +48,7 @@ mod init_directory_tests { let run_command = build_simple_command_runner(Ok(Some(String::from("")))); let write_file = |_file_path: &str, _contents: &str, _x: bool| Err(String::from("")); let file_exists = |_path: &str| panic!("Should not get here"); - let result = init(run_command, write_file, file_exists, vec![]); + let result = init(run_command, write_file, file_exists, &[]); assert_eq!(result, Err(String::from("Unable to create git hooks"))); } @@ -57,7 +57,7 @@ mod init_directory_tests { let run_command = build_simple_command_runner(Ok(Some(String::from("")))); let write_file = |_file_path: &str, _contents: &str, _x: bool| Ok(()); let file_exists = |_path: &str| Err(()); - let result = init(run_command, write_file, file_exists, vec![]); + let result = init(run_command, write_file, file_exists, &[]); assert_eq!(result, Err(String::from("Unable to create config file"))); } @@ -66,7 +66,7 @@ mod init_directory_tests { let run_command = build_simple_command_runner(Ok(Some(String::from("")))); let write_file = |_file_path: &str, _contents: &str, _x: bool| Ok(()); let file_exists = |_path: &str| Ok(false); - let result = init(run_command, write_file, file_exists, vec![]); + let result = init(run_command, write_file, file_exists, &[]); assert_eq!(result, Ok(())); } } @@ -91,7 +91,7 @@ mod init_tests { }; let write_file = |_file_path: &str, _contents: &str, _x: bool| Ok(()); let file_exists = |_path: &str| Ok(false); - let result = init(run_command, write_file, file_exists, vec![]); + let result = init(run_command, write_file, file_exists, &[]); assert_eq!(result, Ok(())); } }