Skip to content

Commit

Permalink
fix(derive): Detect escaped ambiguous subcommands (unstable)
Browse files Browse the repository at this point in the history
  • Loading branch information
epage committed May 6, 2022
1 parent 20ff4ce commit 65538e2
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 3 deletions.
14 changes: 11 additions & 3 deletions clap_derive/src/derives/subcommand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -484,9 +484,17 @@ fn gen_from_arg_matches(
Unnamed(..) => abort_call_site!("{}: tuple enums are not supported", variant.ident),
};

quote! {
if #sub_name == #subcommand_name_var {
return ::std::result::Result::Ok(#name :: #variant_name #constructor_block)
if cfg!(feature = "unstable-v4") {
quote! {
if #sub_name == #subcommand_name_var && !#sub_arg_matches_var.is_present("") {
return ::std::result::Result::Ok(#name :: #variant_name #constructor_block)
}
}
} else {
quote! {
if #sub_name == #subcommand_name_var {
return ::std::result::Result::Ok(#name :: #variant_name #constructor_block)
}
}
}
});
Expand Down
56 changes: 56 additions & 0 deletions tests/derive/subcommands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -547,3 +547,59 @@ fn skip_subcommand() {
let res = Opt::try_parse_from(&["test", "skip"]);
assert_eq!(res.unwrap_err().kind(), clap::ErrorKind::UnknownArgument,);
}

#[test]
#[cfg(feature = "unstable-v4")]
fn built_in_subcommand_escaped() {
#[derive(Debug, PartialEq, Parser)]
enum Command {
Install {
arg: Option<String>,
},
#[clap(external_subcommand)]
Custom(Vec<String>),
}

assert_eq!(
Command::try_parse_from(&["test", "install", "arg"]).unwrap(),
Command::Install {
arg: Some(String::from("arg"))
}
);
assert_eq!(
Command::try_parse_from(&["test", "--", "install"]).unwrap(),
Command::Custom(vec![String::from("install")])
);
assert_eq!(
Command::try_parse_from(&["test", "--", "install", "arg"]).unwrap(),
Command::Custom(vec![String::from("install"), String::from("arg")])
);
}

#[test]
#[cfg(not(feature = "unstable-v4"))]
fn built_in_subcommand_escaped() {
#[derive(Debug, PartialEq, Parser)]
enum Command {
Install {
arg: Option<String>,
},
#[clap(external_subcommand)]
Custom(Vec<String>),
}

assert_eq!(
Command::try_parse_from(&["test", "install", "arg"]).unwrap(),
Command::Install {
arg: Some(String::from("arg"))
}
);
assert_eq!(
Command::try_parse_from(&["test", "--", "install"]).unwrap(),
Command::Install { arg: None }
);
assert_eq!(
Command::try_parse_from(&["test", "--", "install", "arg"]).unwrap(),
Command::Install { arg: None }
);
}

0 comments on commit 65538e2

Please sign in to comment.