From 746eb9d7bd29b864461170c43cccaf29f0ebb161 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Mon, 19 Jul 2021 13:42:07 -0500 Subject: [PATCH] fix(derive): Allow partial update of Sub-Subcommands When using `#[clap(subcommand)]` inside of a Subcommand, we didn't properly do an `update` but a `from`. This is a part of #2605 --- clap_derive/src/derives/subcommand.rs | 14 ++++-- clap_derive/tests/subcommands.rs | 64 +++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 3 deletions(-) diff --git a/clap_derive/src/derives/subcommand.rs b/clap_derive/src/derives/subcommand.rs index 161e4e44..4b5bdd5d 100644 --- a/clap_derive/src/derives/subcommand.rs +++ b/clap_derive/src/derives/subcommand.rs @@ -154,9 +154,17 @@ fn gen_augment( Unit => quote!( #app_var ), Unnamed(FieldsUnnamed { ref unnamed, .. }) if unnamed.len() == 1 => { let ty = &unnamed[0]; - quote_spanned! { ty.span()=> - { - <#ty as clap::Subcommand>::augment_subcommands(#app_var) + if override_required { + quote_spanned! { ty.span()=> + { + <#ty as clap::Subcommand>::augment_subcommands_for_update(#app_var) + } + } + } else { + quote_spanned! { ty.span()=> + { + <#ty as clap::Subcommand>::augment_subcommands(#app_var) + } } } } diff --git a/clap_derive/tests/subcommands.rs b/clap_derive/tests/subcommands.rs index 3464f241..2d909fcf 100644 --- a/clap_derive/tests/subcommands.rs +++ b/clap_derive/tests/subcommands.rs @@ -349,3 +349,67 @@ fn update_subcommands() { opt.try_update_from(&["test", "command2", "43"]).unwrap(); assert_eq!(Opt::parse_from(&["test", "command2", "43"]), opt); } + +#[test] +fn update_sub_subcommands() { + #[derive(Clap, PartialEq, Debug)] + enum Opt { + #[clap(subcommand)] + Child1(Child1), + #[clap(subcommand)] + Child2(Child2), + } + + #[derive(Clap, PartialEq, Debug)] + enum Child1 { + Command1(Command1), + Command2(Command2), + } + + #[derive(Clap, PartialEq, Debug)] + enum Child2 { + Command1(Command1), + Command2(Command2), + } + + #[derive(Clap, PartialEq, Debug)] + struct Command1 { + arg1: i32, + arg2: i32, + } + + #[derive(Clap, PartialEq, Debug)] + struct Command2 { + arg2: i32, + } + + // Full subcommand update + let mut opt = Opt::Child1(Child1::Command1(Command1 { arg1: 12, arg2: 14 })); + opt.try_update_from(&["test", "child1", "command1", "42", "44"]) + .unwrap(); + assert_eq!( + Opt::parse_from(&["test", "child1", "command1", "42", "44"]), + opt + ); + + // Partial subcommand update + let mut opt = Opt::Child1(Child1::Command1(Command1 { arg1: 12, arg2: 14 })); + opt.try_update_from(&["test", "child1", "command1", "42"]) + .unwrap(); + assert_eq!( + Opt::parse_from(&["test", "child1", "command1", "42", "14"]), + opt + ); + + // Partial subcommand update + let mut opt = Opt::Child1(Child1::Command1(Command1 { arg1: 12, arg2: 14 })); + opt.try_update_from(&["test", "child1", "command2", "43"]) + .unwrap(); + assert_eq!(Opt::parse_from(&["test", "child1", "command2", "43"]), opt); + + // Change subcommand + let mut opt = Opt::Child1(Child1::Command1(Command1 { arg1: 12, arg2: 14 })); + opt.try_update_from(&["test", "child2", "command2", "43"]) + .unwrap(); + assert_eq!(Opt::parse_from(&["test", "child2", "command2", "43"]), opt); +}