From 18dca6f68614431cd649e94281d55b1194f1d029 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 17 Aug 2022 12:17:20 -0500 Subject: [PATCH] refactor(cli): Switch to clap_derive This will make it easier to evolve the CLI for issues like #54 --- Cargo.lock | 50 ++++++++++++++++++ Cargo.toml | 2 +- src/main.rs | 148 +++++++++++++++++----------------------------------- 3 files changed, 99 insertions(+), 101 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ea7764cf..d640d0e5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -174,6 +174,7 @@ checksum = "69c5a7f9997be616e47f0577ee38c91decb33392c5be4866494f34cdf329a9aa" dependencies = [ "atty", "bitflags", + "clap_derive", "clap_lex", "indexmap", "once_cell", @@ -182,6 +183,19 @@ dependencies = [ "textwrap", ] +[[package]] +name = "clap_derive" +version = "3.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "759bf187376e1afa7b85b959e6a664a3e7a95203415dba952ad19139e798f902" +dependencies = [ + "heck", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "clap_lex" version = "0.2.4" @@ -260,6 +274,12 @@ version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "607c8a29735385251a339424dd462993c0fed8fa09d378f259377df08c126022" +[[package]] +name = "heck" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" + [[package]] name = "hermit-abi" version = "0.1.19" @@ -408,6 +428,30 @@ dependencies = [ "sha-1", ] +[[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.40" @@ -679,6 +723,12 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5bd2fe26506023ed7b5e1e315add59d6f584c621d037f9368fea9cfb988f368c" +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + [[package]] name = "walkdir" version = "2.3.2" diff --git a/Cargo.toml b/Cargo.toml index ff060625..c200be10 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,7 +15,7 @@ categories = ["command-line-utilities", "development-tools::cargo-plugins"] [dependencies] trustfall_core = "0.0.4" rustdoc-types = "0.14.0" -clap = { version = "3.2.8", features = ["cargo"] } +clap = { version = "3.2.8", features = ["derive", "cargo"] } serde_json = "1.0.82" anyhow = "1.0.58" ron = "0.7.1" diff --git a/src/main.rs b/src/main.rs index b66fb4d4..007d45fb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,10 +7,9 @@ mod query; mod templating; mod util; -use std::env; use std::path::PathBuf; -use clap::{crate_version, value_parser, Arg, ArgAction, Command}; +use clap::{Args, Parser, Subcommand}; use termcolor::{ColorChoice, StandardStream}; use crate::{ @@ -52,117 +51,66 @@ impl GlobalConfig { } fn main() -> anyhow::Result<()> { - let matches = cmd().get_matches(); - - // Descend one level: from `cargo semver-checks` to just `semver-checks`. - let semver_check = matches - .subcommand_matches("semver-checks") - .expect("semver-checks is missing"); + let Cargo::SemverChecks(args) = Cargo::parse(); let config = GlobalConfig::new(); - match semver_check.subcommand() { - Some(("diff-files", diff_files)) => { - let current_rustdoc_path = diff_files - .get_one::("current_rustdoc_path") - .expect("current_rustdoc_path is required but was not present") - .as_path(); - let baseline_rustdoc_path = diff_files - .get_one::("baseline_rustdoc_path") - .expect("baseline_rustdoc_path is required but was not present") - .as_path(); - - let current_crate = load_rustdoc_from_file(current_rustdoc_path)?; - let baseline_crate = load_rustdoc_from_file(baseline_rustdoc_path)?; + match args { + SemverChecks::DiffFiles(args) => { + let current_crate = load_rustdoc_from_file(&args.current_rustdoc_path)?; + let baseline_crate = load_rustdoc_from_file(&args.baseline_rustdoc_path)?; return run_check_release(config, current_crate, baseline_crate); } - Some(("check-release", check_release)) => { - let current_rustdoc_path = check_release - .get_one::("current_rustdoc_path") - .expect("current_rustdoc_path is required but was not present") - .as_path(); - let baseline_rustdoc_path = check_release - .get_one::("baseline_rustdoc_path") - .expect("baseline_rustdoc_path is required but was not present") - .as_path(); - - let current_crate = load_rustdoc_from_file(current_rustdoc_path)?; - let baseline_crate = load_rustdoc_from_file(baseline_rustdoc_path)?; + SemverChecks::CheckRelease(args) => { + let current_crate = load_rustdoc_from_file(&args.current_rustdoc_path)?; + let baseline_crate = load_rustdoc_from_file(&args.baseline_rustdoc_path)?; return run_check_release(config, current_crate, baseline_crate); } - Some(_) => { - unreachable!("external subcommands were not enabled with clap") - } - None => { - unreachable!("arg_required_else_help is set with clap") - } } } -fn cmd() -> Command<'static> { - Command::new("cargo-semver-checks") - .bin_name("cargo") - .version(crate_version!()) - .propagate_version(true) - .subcommand( - Command::new("semver-checks") - .about("Check your crate for semver violations.") - .subcommand_required(true) - .arg_required_else_help(true) - .subcommand( - Command::new("diff-files") - .arg_required_else_help(true) - .arg( - Arg::new("current_rustdoc_path") - .short('c') - .long("current") - .value_name("CURRENT_RUSTDOC_JSON") - .help("The current rustdoc json output to test for semver violations. Required.") - .action(ArgAction::Set) - .value_parser(value_parser!(PathBuf)) - .required(true) - ) - .arg( - Arg::new("baseline_rustdoc_path") - .short('b') - .long("baseline") - .value_name("BASELINE_RUSTDOC_JSON") - .help("The rustdoc json file to use as a semver baseline. Required.") - .action(ArgAction::Set) - .value_parser(value_parser!(PathBuf)) - .required(true) - ) - ) - .subcommand( - Command::new("check-release") - .arg_required_else_help(true) - .arg( - Arg::new("current_rustdoc_path") - .short('c') - .long("current") - .value_name("CURRENT_RUSTDOC_JSON") - .help("The current rustdoc json output to test for semver violations. Required.") - .action(ArgAction::Set) - .value_parser(value_parser!(PathBuf)) - .required(true) - ) - .arg( - Arg::new("baseline_rustdoc_path") - .short('b') - .long("baseline") - .value_name("BASELINE_RUSTDOC_JSON") - .help("The rustdoc json file to use as a semver baseline. Required.") - .action(ArgAction::Set) - .value_parser(value_parser!(PathBuf)) - .required(true) - ) - ) - ) +#[derive(Parser)] +#[clap(name = "cargo")] +#[clap(bin_name = "cargo")] +#[clap(version, propagate_version = true)] +enum Cargo { + #[clap(subcommand)] + SemverChecks(SemverChecks), +} + +/// Check your crate for semver violations. +#[derive(Subcommand)] +enum SemverChecks { + DiffFiles(DiffFiles), + CheckRelease(CheckRelease), +} + +#[derive(Args)] +struct DiffFiles { + /// The current rustdoc json output to test for semver violations. Required. + #[clap(short, long = "current", value_name = "CURRENT_RUSTDOC_JSON")] + current_rustdoc_path: PathBuf, + + /// The rustdoc json file to use as a semver baseline. Required. + #[clap(short, long = "baseline", value_name = "BASELINE_RUSTDOC_JSON")] + baseline_rustdoc_path: PathBuf, +} + +#[derive(Args)] +struct CheckRelease { + /// The current rustdoc json output to test for semver violations. Required. + #[clap(short, long = "current", value_name = "CURRENT_RUSTDOC_JSON")] + current_rustdoc_path: PathBuf, + + /// The rustdoc json file to use as a semver baseline. Required. + #[clap(short, long = "baseline", value_name = "BASELINE_RUSTDOC_JSON")] + baseline_rustdoc_path: PathBuf, } #[test] -fn verify_cmd() { - cmd().debug_assert(); +fn verify_cli() { + use clap::CommandFactory; + Cargo::command().debug_assert() }