diff --git a/plugin/generate_docs.go b/plugin/generate_docs.go index e2f1fef3..d796b59f 100644 --- a/plugin/generate_docs.go +++ b/plugin/generate_docs.go @@ -67,17 +67,33 @@ func mapCommand(tanzuCmd, subCommand *cobra.Command, mapEntry *CommandMapEntry) } } +func cloneCommand(sourceCommand *cobra.Command) *cobra.Command { + // TODO(vuil): before cloning the command, we need the inherited flags + // (persistent flags from command's ancestors) to be captured in the + // command because once the clone is remapped and has a different + // ancestry, some of the inherited flags may not be dynamically + // discoverable anymore. Somewhat dubiously, until there is a means to + // better dictate what a cobra Command's inherited flags are, we rely + // on the side-effect of InheritedFlags() to populate the discovered + // inherited flags in Command.iFlags + _ = sourceCommand.InheritedFlags() + + clone := *sourceCommand + return &clone +} + func cloneChildCommands(parentCloneCmd *cobra.Command) { childCommands := parentCloneCmd.Commands() for _, child := range childCommands { - newChild := *child - cloneChildCommands(&newChild) + newChild := cloneCommand(child) + + cloneChildCommands(newChild) childParent := child.Parent() // child's parent pointer is wrong (still point to childParent, the // source that parentCloneCmd is cloned from), so remove said child parentCloneCmd.RemoveCommand(child) // and add the properly updated clone of child instead - parentCloneCmd.AddCommand(&newChild) + parentCloneCmd.AddCommand(newChild) // however, the removal has the side-effect of wiping the child's // parent link, so remove then re-add back as child of the clone source childParent.RemoveCommand(child) @@ -89,15 +105,15 @@ func cloneChildCommands(parentCloneCmd *cobra.Command) { // generated for the clone (tanzu_xxx_help.md), something that is // extraneous but not incorrect. if child.Use == "help [command]" { - parentCloneCmd.SetHelpCommand(&newChild) + parentCloneCmd.SetHelpCommand(newChild) } } } func deepCopy(cmd *cobra.Command) *cobra.Command { - clone := *cmd - cloneChildCommands(&clone) - return &clone + clone := cloneCommand(cmd) + cloneChildCommands(clone) + return clone } // rebuildTanzuCommandTree reconstructs the tanzu CLI's placement of the diff --git a/plugin/generate_docs_test.go b/plugin/generate_docs_test.go index 9e05ee3b..d95c3f7e 100644 --- a/plugin/generate_docs_test.go +++ b/plugin/generate_docs_test.go @@ -135,6 +135,7 @@ func genDocsTestPlugin(t *testing.T, mapEntries []CommandMapEntry, hiddenCommand var value string var bvalue string + var noColor bool fooCmd.Flags().StringVarP(&value, "value", "v", "", "value to pass") bazCmd.Flags().StringVarP(&bvalue, "bvalue", "b", "", "bvalue to pass") @@ -155,6 +156,9 @@ func genDocsTestPlugin(t *testing.T, mapEntries []CommandMapEntry, hiddenCommand cmd.Hidden = true } + // for testing the effect of inherited flags + p.Cmd.PersistentFlags().BoolVar(&noColor, "n", false, "deactivate color, bold") + return p } @@ -294,13 +298,20 @@ func TestGenerateDocsWithPlugin(t *testing.T) { }, }, "tanzu_foo.md": fileContent{ - contains: []string{"foo command", "[tanzu](tanzu.md)"}, - omits: []string{"tanzu plug foo"}, + contains: []string{ + "foo command", + "[tanzu](tanzu.md)", + // also check that inherited flags are captured + "### Options inherited from parent commands", + "deactivate color", + }, + omits: []string{"tanzu plug foo"}, }, }, }, }, { + // includes check that global flags are fully propagated test: "command and plugin level mapping", commandMap: []CommandMapEntry{ { @@ -320,15 +331,35 @@ func TestGenerateDocsWithPlugin(t *testing.T) { contains: []string{"tanzu", "[tanzu pi](tanzu_pi.md)", "[tanzu foo](tanzu_foo.md)"}, }, "tanzu_pi.md": fileContent{ - contains: []string{"[tanzu pi bar](tanzu_pi_bar.md)"}, + contains: []string{ + "[tanzu pi bar](tanzu_pi_bar.md)", + "deactivate color", + }, omits: []string{ "tanzu pi deeper", "tanzu pi foo", + // this is the command where the nocolor persistent flag is + // defined, so flag is show in the regular options + // section, not under "Options inherited..." + "### Options inherited from parent commands", + }, + }, + "tanzu_pi_bar.md": fileContent{ + contains: []string{ + "[tanzu pi](tanzu_pi.md)", + "### Options inherited from parent commands", + "deactivate color", }, }, "tanzu_foo.md": fileContent{ - contains: []string{"foo command", "[tanzu](tanzu.md)"}, - omits: []string{"tanzu pi foo"}, + contains: []string{ + "foo command", + "[tanzu](tanzu.md)", + "### Options inherited from parent commands", + "deactivate color"}, + omits: []string{ + "tanzu pi foo", + }, }, }, },