diff --git a/src/parse/arg_matcher.rs b/src/parse/arg_matcher.rs index 323fb5b9abc..bda95eb4b5c 100644 --- a/src/parse/arg_matcher.rs +++ b/src/parse/arg_matcher.rs @@ -85,6 +85,7 @@ impl ArgMatcher { } } + #[cfg(not(feature = "unstable-v4"))] pub(crate) fn get_mut(&mut self, arg: &Id) -> Option<&mut MatchedArg> { self.0.args.get_mut(arg) } @@ -142,6 +143,19 @@ impl ArgMatcher { ma.inc_occurrences(); } + #[cfg(feature = "unstable-v4")] + pub(crate) fn inc_occurrence_of_external(&mut self, allow_invalid_utf8: bool) { + let id = &Id::empty_hash(); + debug!( + "ArgMatcher::inc_occurrence_of_external: id={:?}, allow_invalid_utf8={}", + id, allow_invalid_utf8 + ); + let ma = self.entry(id).or_insert(MatchedArg::new()); + ma.update_ty(ValueSource::CommandLine); + ma.invalid_utf8_allowed(allow_invalid_utf8); + ma.inc_occurrences(); + } + pub(crate) fn add_val_to(&mut self, arg: &Id, val: OsString, ty: ValueSource, append: bool) { if append { self.append_val_to(arg, val, ty); diff --git a/src/parse/parser.rs b/src/parse/parser.rs index 5ca9cfe8d0d..6262d18d887 100644 --- a/src/parse/parser.rs +++ b/src/parse/parser.rs @@ -428,26 +428,34 @@ impl<'help, 'cmd> Parser<'help, 'cmd> { // Collect the external subcommand args let mut sc_m = ArgMatcher::new(self.cmd); + let allow_invalid_utf8 = self + .cmd + .is_allow_invalid_utf8_for_external_subcommands_set(); + #[cfg(feature = "unstable-v4")] + { + sc_m.inc_occurrence_of_external(allow_invalid_utf8); + } for v in raw_args.remaining(&mut args_cursor) { - let allow_invalid_utf8 = self - .cmd - .is_allow_invalid_utf8_for_external_subcommands_set(); if !allow_invalid_utf8 && v.to_str().is_none() { return Err(ClapError::invalid_utf8( self.cmd, Usage::new(self.cmd).create_usage_with_title(&[]), )); } + let external_id = &Id::empty_hash(); sc_m.add_val_to( - &Id::empty_hash(), + external_id, v.to_os_string(), ValueSource::CommandLine, false, ); - sc_m.get_mut(&Id::empty_hash()) - .expect("just inserted") - .invalid_utf8_allowed(allow_invalid_utf8); + #[cfg(not(feature = "unstable-v4"))] + { + sc_m.get_mut(external_id) + .expect("just inserted") + .invalid_utf8_allowed(allow_invalid_utf8); + } } matcher.subcommand(SubCommand { diff --git a/tests/builder/app_settings.rs b/tests/builder/app_settings.rs index 3013406b816..50d305afd91 100644 --- a/tests/builder/app_settings.rs +++ b/tests/builder/app_settings.rs @@ -851,6 +851,46 @@ fn issue_1093_allow_ext_sc() { utils::assert_output(cmd, "clap-test --help", ALLOW_EXT_SC, false); } +#[test] +#[cfg(not(feature = "unstable-v4"))] +fn allow_ext_sc_empty_args() { + let res = Command::new("clap-test") + .version("v1.4.8") + .allow_external_subcommands(true) + .allow_invalid_utf8_for_external_subcommands(true) + .try_get_matches_from(vec!["clap-test", "external-cmd"]); + + assert!(res.is_ok(), "{}", res.unwrap_err()); + + match res.unwrap().subcommand() { + Some((name, args)) => { + assert_eq!(name, "external-cmd"); + assert_eq!(args.values_of_lossy(""), None); + } + _ => unreachable!(), + } +} + +#[test] +#[cfg(feature = "unstable-v4")] +fn allow_ext_sc_empty_args() { + let res = Command::new("clap-test") + .version("v1.4.8") + .allow_external_subcommands(true) + .allow_invalid_utf8_for_external_subcommands(true) + .try_get_matches_from(vec!["clap-test", "external-cmd"]); + + assert!(res.is_ok(), "{}", res.unwrap_err()); + + match res.unwrap().subcommand() { + Some((name, args)) => { + assert_eq!(name, "external-cmd"); + assert_eq!(args.values_of_lossy(""), Some(vec![])); + } + _ => unreachable!(), + } +} + #[test] fn allow_ext_sc_when_sc_required() { let res = Command::new("clap-test")