From c09b0e38ca9aa3e3cd0154733bd15b10d6ad5912 Mon Sep 17 00:00:00 2001 From: Martin Pool Date: Sat, 27 Aug 2022 13:34:47 -0700 Subject: [PATCH] Switch from Argh to Clap Fixes #61 --- Cargo.lock | 156 ++++++++++++++++++++++++++++++++++------------- Cargo.toml | 2 +- NEWS.md | 4 ++ src/exit_code.rs | 2 +- src/main.rs | 73 ++++++++++++---------- 5 files changed, 162 insertions(+), 75 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b83260a1..bf0437ad 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -26,35 +26,6 @@ version = "1.0.62" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1485d4d2cc45e7b201ee3767015c96faa5904387c9d87c6efdd0fb511f12d305" -[[package]] -name = "argh" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7e7e4aa7e40747e023c0761dafcb42333a9517575bbf1241747f68dd3177a62" -dependencies = [ - "argh_derive", - "argh_shared", -] - -[[package]] -name = "argh_derive" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69f2bd7ff6ed6414f4e5521bd509bae46454bbd513801767ced3f21a751ab4bc" -dependencies = [ - "argh_shared", - "heck", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "argh_shared" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47253b98986dafc7a3e1cf3259194f1f47ac61abb57a57f46ec09e48d004ecda" - [[package]] name = "assert_cmd" version = "2.0.4" @@ -123,10 +94,10 @@ name = "cargo-mutants" version = "1.0.1-pre" dependencies = [ "anyhow", - "argh", "assert_cmd", "camino", "cargo_metadata", + "clap", "console", "cp_r", "ctrlc", @@ -193,6 +164,45 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "clap" +version = "3.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29e724a68d9319343bb3328c9cc2dfde263f4b3142ee1059a9980580171c954b" +dependencies = [ + "atty", + "bitflags", + "clap_derive", + "clap_lex", + "indexmap", + "once_cell", + "strsim", + "termcolor", + "textwrap", +] + +[[package]] +name = "clap_derive" +version = "3.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13547f7012c01ab4a0e8f8967730ada8f9fdf419e8b6c792788f39cf4e46eefa" +dependencies = [ + "heck", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" +dependencies = [ + "os_str_bytes", +] + [[package]] name = "console" version = "0.15.1" @@ -377,14 +387,17 @@ dependencies = [ "regex", ] +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + [[package]] name = "heck" -version = "0.3.3" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" -dependencies = [ - "unicode-segmentation", -] +checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" [[package]] name = "hermit-abi" @@ -395,6 +408,16 @@ dependencies = [ "libc", ] +[[package]] +name = "indexmap" +version = "1.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" +dependencies = [ + "autocfg", + "hashbrown", +] + [[package]] name = "insta" version = "1.19.0" @@ -565,6 +588,12 @@ version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "074864da206b4973b84eb91683020dbefd6a8c3f0f38e054d93954e891935e4e" +[[package]] +name = "os_str_bytes" +version = "6.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ff7415e9ae3fff1225851df9e0d9e4e5479f947619774677a63572e55e80eff" + [[package]] name = "output_vt100" version = "0.1.3" @@ -663,6 +692,30 @@ dependencies = [ "output_vt100", ] +[[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.43" @@ -848,6 +901,12 @@ version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1" +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + [[package]] name = "subprocess" version = "0.2.9" @@ -883,6 +942,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "termcolor" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" +dependencies = [ + "winapi-util", +] + [[package]] name = "terminal_size" version = "0.1.17" @@ -909,6 +977,12 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "507e9898683b6c43a9aa55b64259b721b52ba226e0f3779137e50ad114a4c90b" +[[package]] +name = "textwrap" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" + [[package]] name = "thread_local" version = "1.1.4" @@ -1013,12 +1087,6 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf" -[[package]] -name = "unicode-segmentation" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99" - [[package]] name = "unicode-width" version = "0.1.9" @@ -1031,6 +1099,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + [[package]] name = "wait-timeout" version = "0.2.0" diff --git a/Cargo.toml b/Cargo.toml index c402c1be..9b90a9e7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,7 +14,6 @@ rust-version = "1.59" [dependencies] anyhow = "1.0" -argh = "0.1" camino = "1.0" cargo_metadata = "0.15" console = "0.15" @@ -37,6 +36,7 @@ tracing-appender = "0.2" tracing-subscriber = "0.3" walkdir = "2.3" whoami = "1.2" +clap = { version = "3.2.17", features = ["derive"] } [dependencies.cp_r] version = "0.5.1" diff --git a/NEWS.md b/NEWS.md index ccfd4c25..05e589f5 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,9 @@ # cargo-mutants changelog +## Unreleased + +- Internal: Switched from Argh to Clap for command-line parsing. There may be some small changes in CLI behavior and help formatting. + ## 1.0.0 Released 2022-08-21 diff --git a/src/exit_code.rs b/src/exit_code.rs index 886a58b7..80e32865 100644 --- a/src/exit_code.rs +++ b/src/exit_code.rs @@ -14,7 +14,7 @@ pub const SUCCESS: i32 = 0; /// The wrong arguments, etc. /// -/// (1 is also the value returned by argh.) +/// (1 is also the value returned by Clap.) pub const USAGE: i32 = 1; /// Found one or mutants that were not caught by tests. diff --git a/src/main.rs b/src/main.rs index e2c6a60e..8fa3d838 100644 --- a/src/main.rs +++ b/src/main.rs @@ -27,8 +27,9 @@ use std::process::exit; use std::time::Duration; use anyhow::Result; -use argh::FromArgs; +use camino::Utf8Path; use camino::Utf8PathBuf; +use clap::Parser; use path_slash::PathExt; use serde_json::json; use serde_json::Value; @@ -52,109 +53,117 @@ const NAME: &str = env!("CARGO_PKG_NAME"); const DEFAULT_MINIMUM_TEST_TIMEOUT: Duration = Duration::from_secs(20); const MINIMUM_TEST_TIMEOUT_ENV_VAR: &str = "CARGO_MUTANTS_MINIMUM_TEST_TIMEOUT"; +#[derive(Parser)] +#[clap(name = "cargo", bin_name = "cargo")] +enum Cargo { + #[clap(name = "mutants")] + Mutants(Args), +} + /// Find inadequately-tested code that can be removed without any tests failing. /// /// See for more information. -#[derive(FromArgs, PartialEq, Debug)] +#[derive(Parser, PartialEq, Debug)] +#[clap(author, about)] struct Args { /// show cargo output for all invocations (very verbose). - #[argh(switch)] + #[clap(long)] all_logs: bool, /// print mutants that were caught by tests. - #[argh(switch, short = 'v')] + #[clap(long, short = 'v')] caught: bool, /// cargo check generated mutants, but don't run tests. - #[argh(switch)] + #[clap(long)] check: bool, /// show the mutation diffs. - #[argh(switch)] + #[clap(long)] diff: bool, /// rust crate directory to examine. - #[argh(option, short = 'd', default = r#"Utf8PathBuf::from(".")"#)] - dir: Utf8PathBuf, + #[clap(long, short = 'd')] + dir: Option, /// glob for files to examine; with no glob, all files are examined; globs containing /// slash match the entire path. If used together with `--exclude` argument, then the files to be examined are matched before the files to be excluded. - #[argh(option, short = 'f')] + #[clap(long, short = 'f')] file: Vec, /// glob for files to exclude; with no glob, all files are included; globs containing /// slash match the entire path. If used together with `--file` argument, then the files to be examined are matched before the files to be excluded. - #[argh(option, short = 'e')] + #[clap(long, short = 'e')] exclude: Vec, /// output json (only for --list). - #[argh(switch)] + #[clap(long)] json: bool, /// just list possible mutants, don't run them. - #[argh(switch)] + #[clap(long)] list: bool, /// list source files, don't run anything. - #[argh(switch)] + #[clap(long)] list_files: bool, /// don't copy the /target directory, and don't build the source tree first. - #[argh(switch)] + #[clap(long)] no_copy_target: bool, /// don't print times or tree sizes, to make output deterministic. - #[argh(switch)] + #[clap(long)] no_times: bool, /// create mutants.out within this directory. - #[argh(option, short = 'o')] + #[clap(long, short = 'o')] output: Option, /// run mutants in random order. - #[argh(switch)] + #[clap(long)] shuffle: bool, /// run mutants in the fixed order they occur in the source tree. - #[argh(switch)] + #[clap(long)] no_shuffle: bool, /// maximum run time for all cargo commands, in seconds. - #[argh(option, short = 't')] + #[clap(long, short = 't')] timeout: Option, /// print mutations that failed to check or build. - #[argh(switch, short = 'V')] + #[clap(long, short = 'V')] unviable: bool, /// show version and quit. - #[argh(switch)] + #[clap(long, action = clap::ArgAction::SetTrue)] version: bool, /// additional args for all cargo invocations. - #[argh(option, short = 'C')] + #[clap(long, short = 'C', takes_value = true, allow_hyphen_values = true)] cargo_arg: Vec, // The following option captures all the remaining non-option args, to // send to cargo. /// pass remaining arguments to cargo test after all options and after `--`. - #[argh(positional)] + #[clap(last = true)] cargo_test_args: Vec, } fn main() -> Result<()> { - if let Some(subcommand) = env::args().nth(1) { - if subcommand != "mutants" { - eprintln!("unrecognized cargo subcommand {:?}", subcommand); + let args = match Cargo::try_parse() { + Ok(Cargo::Mutants(args)) => args, + Err(e) => { + eprintln!("{}", e); exit(exit_code::USAGE); } - } else { - eprintln!("usage: cargo mutants \n or: cargo-mutants mutants "); - exit(exit_code::USAGE); - } - let args: Args = argh::cargo_from_env(); + }; + // dbg!(&args); let options = Options::try_from(&args)?; - let source_tree = SourceTree::new(&args.dir)?; + // dbg!(&options); + let source_path = args.dir.unwrap_or_else(|| Utf8Path::new(".").to_owned()); + let source_tree = SourceTree::new(&source_path)?; interrupt::install_handler(); if args.version { println!("{} {}", NAME, VERSION);