From eb7a34b7e9308c7f86f5020c04820b81c1112202 Mon Sep 17 00:00:00 2001 From: cat_in_136 Date: Sun, 2 Jun 2024 01:45:30 +0900 Subject: [PATCH] fix bug where `--auto-req` option does not accept `auto` and the script path --- Cargo.toml | 1 + src/auto_req/mod.rs | 17 +++--- src/cli.rs | 123 ++++++++++++++++++++++++++------------------ src/config/mod.rs | 3 +- 4 files changed, 82 insertions(+), 62 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 0b145187..29bd1f5c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,7 @@ rpm = { version = "0.13.1", default-features = false } toml = "0.7" cargo_toml = "0.15" clap = { version = "4.3", features = ["derive"] } +color-print = "0.3" thiserror = "1" elf = "0.7" diff --git a/src/auto_req/mod.rs b/src/auto_req/mod.rs index ca7bfb47..7c769718 100644 --- a/src/auto_req/mod.rs +++ b/src/auto_req/mod.rs @@ -19,17 +19,14 @@ pub enum AutoReqMode { BuiltIn, } -impl From<&Option> for AutoReqMode { - fn from(value: &Option) -> Self { - use cli::AutoReqMode as M; - use AutoReqMode::*; - +impl From for AutoReqMode { + fn from(value: cli::AutoReqMode) -> Self { match value { - None => Auto, - Some(M::Disabled) => Disabled, - Some(M::Builtin) => BuiltIn, - Some(M::Script(path)) => Script(path.into()), - Some(M::FindRequires) => Script(PathBuf::from(RPM_FIND_REQUIRES)), + cli::AutoReqMode::Auto => AutoReqMode::Auto, + cli::AutoReqMode::Disabled => AutoReqMode::Disabled, + cli::AutoReqMode::Builtin => AutoReqMode::BuiltIn, + cli::AutoReqMode::FindRequires => AutoReqMode::Script(PathBuf::from(RPM_FIND_REQUIRES)), + cli::AutoReqMode::Script(path) => AutoReqMode::Script(path), } } } diff --git a/src/cli.rs b/src/cli.rs index a4531edb..f06cc9ee 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -1,4 +1,8 @@ -use clap::{builder::PossibleValue, Parser, ValueEnum}; +use clap::{ + builder::{PathBufValueParser, PossibleValuesParser, TypedValueParser, ValueParserFactory}, + Arg, Command, Parser, ValueEnum, +}; +use std::ffi::OsStr; use std::path::PathBuf; /// Wrapper used when the application is executed as Cargo plugin @@ -29,7 +33,18 @@ pub struct Cli { pub package: Option, /// Automatic dependency processing mode. - #[arg(long)] + #[arg(long, + help = "Automatic dependency processing mode. \ + [default: auto] \ + [possible values: auto, disabled, builtin, find-requires, /path/to/find-requires]", + long_help = color_print::cstr!("Automatic dependency processing mode.\n\n\ + [default: auto]\n\ + Possible values:\n\ + - auto: Automatic discovery of dependencies.\n\ + - disabled: Disable automatic discovery of dependencies. [alias: no]\n\ + - builtin: Use the builtin procedure based on ldd.\n\ + - find-requires: Use the external program specified in RPM_FIND_REQUIRES.\n\ + - /path/to/find-requires: Use the specified external program."))] pub auto_req: Option, /// Sub-directory name for all generated artifacts. May be @@ -102,54 +117,59 @@ impl From for rpm::CompressionWithLevel { } } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq, Eq)] pub enum AutoReqMode { + Auto, Disabled, Builtin, FindRequires, - Script(String), + Script(PathBuf), } -static AUTO_REQ_VARIANTS: &[AutoReqMode] = &[ - AutoReqMode::Disabled, - AutoReqMode::Builtin, - AutoReqMode::FindRequires, - AutoReqMode::Script(String::new()), -]; +impl ValueParserFactory for AutoReqMode { + type Parser = AutoReqModeParser; -impl ValueEnum for AutoReqMode { - fn value_variants<'a>() -> &'a [Self] { - AUTO_REQ_VARIANTS + fn value_parser() -> Self::Parser { + AutoReqModeParser } +} - fn to_possible_value(&self) -> Option { - use AutoReqMode::*; - - let val = match self { - Disabled => PossibleValue::new("disabled") - .help("Disable automatic discovery of dependencies") - .alias("no"), - Builtin => { - PossibleValue::new("builtin").help("Use the builtin procedure based on ldd.") +#[derive(Clone, Debug)] +pub struct AutoReqModeParser; + +impl TypedValueParser for AutoReqModeParser { + type Value = AutoReqMode; + fn parse_ref( + &self, + cmd: &Command, + arg: Option<&Arg>, + value: &OsStr, + ) -> Result { + const VALUES: [(&str, AutoReqMode); 5] = [ + ("auto", AutoReqMode::Auto), + ("disabled", AutoReqMode::Disabled), + ("no", AutoReqMode::Disabled), + ("builtin", AutoReqMode::Builtin), + ("find-requires", AutoReqMode::FindRequires), + ]; + + let inner = PossibleValuesParser::new(VALUES.iter().map(|(k, _v)| k)); + match inner.parse_ref(cmd, arg, value) { + Ok(name) => Ok(VALUES + .iter() + .find(|(k, _v)| name.as_str() == (k.as_ref() as &str)) + .unwrap() + .1 + .clone()), + Err(e) if e.kind() == clap::error::ErrorKind::InvalidValue => { + let inner = PathBufValueParser::new(); + match inner.parse_ref(cmd, arg, value) { + Ok(v) => Ok(AutoReqMode::Script(v)), + Err(e) => Err(e), + } } - FindRequires => PossibleValue::new("find-requires") - .help("Use the external program specified in RPM_FIND_REQUIRES."), - _ => PossibleValue::new("/path/to/find-requires") - .help("Use the specified external program."), - }; - Some(val) - } - - // Provided method - fn from_str(input: &str, ignore_case: bool) -> Result { - let lowercase = String::from(input).to_lowercase(); - let val = if ignore_case { &lowercase } else { input }; - Ok(match val { - "disabled" => Self::Disabled, - "builtin" => Self::Builtin, - "find-requires" => Self::FindRequires, - _ => Self::Script(input.into()), - }) + Err(e) => Err(e), + } } } @@ -188,23 +208,24 @@ mod tests { "toml \"text2\"", ]) .unwrap(); - assert_eq!( - args.set_metadata, - vec!["TOML_FILE.toml", "TOML_FILE.toml#TOML.PATH"] - ); + assert_eq!(args.set_metadata, vec!["toml \"text1\"", "toml \"text2\""]); } #[test] fn test_auto_req() { - //let args = Cli::try_parse_from(["", "--auto-req", "auto"]).unwrap(); - //assert!(matches!(args.auto_req, Some(AutoReqMode::Auto))); + let args = Cli::try_parse_from([""]).unwrap(); + assert_eq!(args.auto_req, None); + let args = Cli::try_parse_from(["", "--auto-req", "auto"]).unwrap(); + assert_eq!(args.auto_req, Some(AutoReqMode::Auto)); let args = Cli::try_parse_from(["", "--auto-req", "builtin"]).unwrap(); - assert!(matches!(args.auto_req, Some(AutoReqMode::Builtin))); + assert_eq!(args.auto_req, Some(AutoReqMode::Builtin)); let args = Cli::try_parse_from(["", "--auto-req", "find-requires"]).unwrap(); - assert!(matches!(args.auto_req, Some(AutoReqMode::FindRequires))); - //let args = Cli::try_parse_from(["", "--auto-req", "/usr/lib/rpm/find-requires"]).unwrap(); - //assert!(matches!(args.auto_req, Some(AutoReqMode::Script(v)) if v.eq("/usr/lib/rpm/find-requires"))); + assert_eq!(args.auto_req, Some(AutoReqMode::FindRequires)); + let args = Cli::try_parse_from(["", "--auto-req", "/usr/lib/rpm/find-requires"]).unwrap(); + assert!( + matches!(args.auto_req, Some(AutoReqMode::Script(v)) if v == PathBuf::from("/usr/lib/rpm/find-requires")) + ); let args = Cli::try_parse_from(["", "--auto-req", "no"]).unwrap(); - assert!(matches!(args.auto_req, Some(AutoReqMode::Disabled))); + assert_eq!(args.auto_req, Some(AutoReqMode::Disabled)); } } diff --git a/src/config/mod.rs b/src/config/mod.rs index 1ad8d15f..69e74a6a 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -303,7 +303,8 @@ impl Config { let meta_aut_req = metadata.get_str("auto-req")?; let auto_req = match (&cfg.args.auto_req, meta_aut_req) { (None, Some("no" | "disabled")) => AutoReqMode::Disabled, - (r, _) => r.into(), + (None, _) => AutoReqMode::Auto, + (Some(v), _) => AutoReqMode::from(v.clone()), }; for requires in find_requires(expanded_file_paths, auto_req)? {