Skip to content

Commit

Permalink
Merge pull request clap-rs#3429 from epage/global
Browse files Browse the repository at this point in the history
fix: Detect deeply recursed global args
  • Loading branch information
epage committed Feb 9, 2022
2 parents 117c9ed + 81092b5 commit 519fcc2
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 16 deletions.
28 changes: 12 additions & 16 deletions src/build/app/mod.rs
Expand Up @@ -2704,23 +2704,18 @@ impl<'help> App<'help> {

// Internally used only
impl<'help> App<'help> {
fn get_used_global_args(&self, matcher: &ArgMatcher) -> Vec<Id> {
let global_args: Vec<_> = self
.args
.args()
.filter(|a| a.get_global())
.map(|ga| ga.id.clone())
.collect();
if let Some(used_subcommand) = matcher.subcommand.as_ref() {
if let Some(used_subcommand) = self
.subcommands
.iter()
.find(|subcommand| subcommand.id == used_subcommand.id)
{
return [global_args, used_subcommand.get_used_global_args(matcher)].concat();
fn get_used_global_args(&self, matches: &ArgMatches, global_arg_vec: &mut Vec<Id>) {
global_arg_vec.extend(
self.args
.args()
.filter(|a| a.get_global())
.map(|ga| ga.id.clone()),
);
if let Some((id, matches)) = matches.subcommand() {
if let Some(used_sub) = self.find_subcommand(id) {
used_sub.get_used_global_args(matches, global_arg_vec);
}
}
global_args
}

fn _do_parse(&mut self, it: &mut Input) -> ClapResult<ArgMatches> {
Expand All @@ -2742,7 +2737,8 @@ impl<'help> App<'help> {
}
}

let global_arg_vec: Vec<Id> = self.get_used_global_args(&matcher);
let mut global_arg_vec = Default::default();
self.get_used_global_args(&matcher, &mut global_arg_vec);

matcher.propagate_globals(&global_arg_vec);

Expand Down
20 changes: 20 additions & 0 deletions tests/builder/global_args.rs
Expand Up @@ -88,3 +88,23 @@ fn global_arg_available_in_subcommand() {
assert!(m.is_present("global"));
assert!(m.subcommand_matches("ping").unwrap().is_present("global"));
}

#[test]
fn deeply_nested_discovery() {
let app = App::new("a").arg(arg!(--"long-a").global(true)).subcommand(
App::new("b").arg(arg!(--"long-b").global(true)).subcommand(
App::new("c")
.arg(arg!(--"long-c").global(true))
.subcommand(App::new("d")),
),
);

let m = app
.try_get_matches_from(["a", "b", "c", "d", "--long-a", "--long-b", "--long-c"])
.unwrap();
assert!(m.is_present("long-a"));
let m = m.subcommand_matches("b").unwrap();
assert!(m.is_present("long-b"));
let m = m.subcommand_matches("c").unwrap();
assert!(m.is_present("long-c"));
}

0 comments on commit 519fcc2

Please sign in to comment.