mirror of
https://github.com/spf13/cobra
synced 2025-04-27 17:17:20 +00:00
Merge e86f3862de
into 09d5664f34
This commit is contained in:
commit
72f699a553
4 changed files with 105 additions and 3 deletions
24
command.go
24
command.go
|
@ -32,6 +32,7 @@ import (
|
|||
const (
|
||||
FlagSetByCobraAnnotation = "cobra_annotation_flag_set_by_cobra"
|
||||
CommandDisplayNameAnnotation = "cobra_annotation_command_display_name"
|
||||
trueString = "true"
|
||||
)
|
||||
|
||||
// FParseErrWhitelist configures Flag parse errors to be ignored
|
||||
|
@ -1161,7 +1162,7 @@ func (c *Command) ValidateRequiredFlags() error {
|
|||
if !found {
|
||||
return
|
||||
}
|
||||
if (requiredAnnotation[0] == "true") && !pflag.Changed {
|
||||
if (requiredAnnotation[0] == trueString) && !pflag.Changed {
|
||||
missingFlagNames = append(missingFlagNames, pflag.Name)
|
||||
}
|
||||
})
|
||||
|
@ -1199,7 +1200,7 @@ func (c *Command) InitDefaultHelpFlag() {
|
|||
usage += name
|
||||
}
|
||||
c.Flags().BoolP("help", "h", false, usage)
|
||||
_ = c.Flags().SetAnnotation("help", FlagSetByCobraAnnotation, []string{"true"})
|
||||
_ = c.Flags().SetAnnotation("help", FlagSetByCobraAnnotation, []string{trueString})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1225,7 +1226,7 @@ func (c *Command) InitDefaultVersionFlag() {
|
|||
} else {
|
||||
c.Flags().Bool("version", false, usage)
|
||||
}
|
||||
_ = c.Flags().SetAnnotation("version", FlagSetByCobraAnnotation, []string{"true"})
|
||||
_ = c.Flags().SetAnnotation("version", FlagSetByCobraAnnotation, []string{trueString})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1262,6 +1263,23 @@ Simply type ` + c.DisplayName() + ` help [path to command] for full details.`,
|
|||
}
|
||||
return completions, ShellCompDirectiveNoFileComp
|
||||
},
|
||||
PersistentPreRunE: func(cmd *Command, args []string) error {
|
||||
cmd.Flags().VisitAll(func(pflag *flag.Flag) {
|
||||
requiredAnnotation, found := pflag.Annotations[BashCompOneRequiredFlag]
|
||||
if found && requiredAnnotation[0] == trueString {
|
||||
// Disable any persistent required flags for the help command
|
||||
pflag.Annotations[BashCompOneRequiredFlag] = []string{"false"}
|
||||
}
|
||||
})
|
||||
// Adding PersistentPreRun on sub-commands prevents root's PersistentPreRun from being called.
|
||||
// So it is intentionally called here.
|
||||
if cmd.Root().PersistentPreRunE != nil {
|
||||
return cmd.Root().PersistentPreRunE(cmd, args)
|
||||
} else if cmd.Root().PersistentPreRun != nil {
|
||||
cmd.Root().PersistentPreRun(cmd, args)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
Run: func(c *Command, args []string) {
|
||||
cmd, _, e := c.Root().Find(args)
|
||||
if cmd == nil || e != nil {
|
||||
|
|
|
@ -950,6 +950,18 @@ func TestHelpCommandExecuted(t *testing.T) {
|
|||
checkStringContains(t, output, rootCmd.Long)
|
||||
}
|
||||
|
||||
func TestHelpCommandExecutedWithPersistentRequiredFlags(t *testing.T) {
|
||||
rootCmd := &Command{Use: "root", Run: emptyRun}
|
||||
rootCmd.PersistentFlags().Bool("foo", false, "")
|
||||
childCmd := &Command{Use: "child", Run: emptyRun}
|
||||
rootCmd.AddCommand(childCmd)
|
||||
assertNoErr(t, rootCmd.MarkPersistentFlagRequired("foo"))
|
||||
|
||||
if _, err := executeCommand(rootCmd, "help"); err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHelpCommandExecutedOnChild(t *testing.T) {
|
||||
rootCmd := &Command{Use: "root", Run: emptyRun}
|
||||
childCmd := &Command{Use: "child", Long: "Long description", Run: emptyRun}
|
||||
|
@ -1703,6 +1715,25 @@ func testPersistentHooks(t *testing.T, expectedHookRunOrder []string) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestPersistentPreRunHooksForHelpCommand(t *testing.T) {
|
||||
executed := false
|
||||
|
||||
rootCmd := &Command{
|
||||
Use: "root",
|
||||
PersistentPreRun: func(*Command, []string) { executed = true },
|
||||
Run: emptyRun,
|
||||
}
|
||||
childCmd := &Command{Use: "child", Run: emptyRun}
|
||||
rootCmd.AddCommand(childCmd)
|
||||
|
||||
if _, err := executeCommand(rootCmd, "help"); err != nil {
|
||||
t.Errorf("Unexpected error: %v", err)
|
||||
}
|
||||
if !executed {
|
||||
t.Error("Root PersistentPreRun should have been executed")
|
||||
}
|
||||
}
|
||||
|
||||
// Related to https://github.com/spf13/cobra/issues/521.
|
||||
func TestGlobalNormFuncPropagation(t *testing.T) {
|
||||
normFunc := func(f *pflag.FlagSet, name string) pflag.NormalizedName {
|
||||
|
|
|
@ -735,6 +735,23 @@ See each sub-command's help for details on how to use the generated script.
|
|||
ValidArgsFunction: NoFileCompletions,
|
||||
Hidden: c.CompletionOptions.HiddenDefaultCmd,
|
||||
GroupID: c.completionCommandGroupID,
|
||||
PersistentPreRunE: func(cmd *Command, args []string) error {
|
||||
cmd.Flags().VisitAll(func(flag *pflag.Flag) {
|
||||
requiredAnnotation, found := flag.Annotations[BashCompOneRequiredFlag]
|
||||
if found && requiredAnnotation[0] == "true" {
|
||||
// Disable any persistent required flags for the completion command
|
||||
flag.Annotations[BashCompOneRequiredFlag] = []string{"false"}
|
||||
}
|
||||
})
|
||||
// Adding PersistentPreRun on sub-commands prevents root's PersistentPreRun from being called.
|
||||
// So it is intentionally called here.
|
||||
if cmd.Root().PersistentPreRunE != nil {
|
||||
return cmd.Root().PersistentPreRunE(cmd, args)
|
||||
} else if cmd.Root().PersistentPreRun != nil {
|
||||
cmd.Root().PersistentPreRun(cmd, args)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
c.AddCommand(completionCmd)
|
||||
|
||||
|
|
|
@ -2591,6 +2591,42 @@ func TestDefaultCompletionCmd(t *testing.T) {
|
|||
rootCmd.CompletionOptions.HiddenDefaultCmd = false
|
||||
// Remove completion command for the next test
|
||||
removeCompCmd(rootCmd)
|
||||
|
||||
// Test that required flag will be ignored
|
||||
rootCmd.PersistentFlags().Bool("foo", false, "")
|
||||
assertNoErr(t, rootCmd.MarkPersistentFlagRequired("foo"))
|
||||
for _, shell := range []string{"bash", "fish", "powershell", "zsh"} {
|
||||
if _, err = executeCommand(rootCmd, compCmdName, shell); err != nil {
|
||||
t.Errorf("Unexpected error: %v", err)
|
||||
}
|
||||
}
|
||||
// Remove completion command for the next test
|
||||
removeCompCmd(rootCmd)
|
||||
}
|
||||
|
||||
func TestPersistentPreRunHooksForCompletionCommand(t *testing.T) {
|
||||
executed := false
|
||||
|
||||
rootCmd := &Command{
|
||||
Use: "root",
|
||||
PersistentPreRun: func(*Command, []string) { executed = true },
|
||||
Run: emptyRun,
|
||||
}
|
||||
subCmd := &Command{
|
||||
Use: "sub",
|
||||
Run: emptyRun,
|
||||
}
|
||||
rootCmd.AddCommand(subCmd)
|
||||
|
||||
for _, shell := range []string{"bash", "fish", "powershell", "zsh"} {
|
||||
if _, err := executeCommand(rootCmd, compCmdName, shell); err != nil {
|
||||
t.Errorf("Unexpected error: %v", err)
|
||||
}
|
||||
if !executed {
|
||||
t.Error("Root PersistentPreRun should have been executed")
|
||||
}
|
||||
executed = false
|
||||
}
|
||||
}
|
||||
|
||||
func TestCompleteCompletion(t *testing.T) {
|
||||
|
|
Loading…
Add table
Reference in a new issue