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 (
|
const (
|
||||||
FlagSetByCobraAnnotation = "cobra_annotation_flag_set_by_cobra"
|
FlagSetByCobraAnnotation = "cobra_annotation_flag_set_by_cobra"
|
||||||
CommandDisplayNameAnnotation = "cobra_annotation_command_display_name"
|
CommandDisplayNameAnnotation = "cobra_annotation_command_display_name"
|
||||||
|
trueString = "true"
|
||||||
)
|
)
|
||||||
|
|
||||||
// FParseErrWhitelist configures Flag parse errors to be ignored
|
// FParseErrWhitelist configures Flag parse errors to be ignored
|
||||||
|
@ -1161,7 +1162,7 @@ func (c *Command) ValidateRequiredFlags() error {
|
||||||
if !found {
|
if !found {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (requiredAnnotation[0] == "true") && !pflag.Changed {
|
if (requiredAnnotation[0] == trueString) && !pflag.Changed {
|
||||||
missingFlagNames = append(missingFlagNames, pflag.Name)
|
missingFlagNames = append(missingFlagNames, pflag.Name)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -1199,7 +1200,7 @@ func (c *Command) InitDefaultHelpFlag() {
|
||||||
usage += name
|
usage += name
|
||||||
}
|
}
|
||||||
c.Flags().BoolP("help", "h", false, usage)
|
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 {
|
} else {
|
||||||
c.Flags().Bool("version", false, usage)
|
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
|
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) {
|
Run: func(c *Command, args []string) {
|
||||||
cmd, _, e := c.Root().Find(args)
|
cmd, _, e := c.Root().Find(args)
|
||||||
if cmd == nil || e != nil {
|
if cmd == nil || e != nil {
|
||||||
|
|
|
@ -950,6 +950,18 @@ func TestHelpCommandExecuted(t *testing.T) {
|
||||||
checkStringContains(t, output, rootCmd.Long)
|
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) {
|
func TestHelpCommandExecutedOnChild(t *testing.T) {
|
||||||
rootCmd := &Command{Use: "root", Run: emptyRun}
|
rootCmd := &Command{Use: "root", Run: emptyRun}
|
||||||
childCmd := &Command{Use: "child", Long: "Long description", 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.
|
// Related to https://github.com/spf13/cobra/issues/521.
|
||||||
func TestGlobalNormFuncPropagation(t *testing.T) {
|
func TestGlobalNormFuncPropagation(t *testing.T) {
|
||||||
normFunc := func(f *pflag.FlagSet, name string) pflag.NormalizedName {
|
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,
|
ValidArgsFunction: NoFileCompletions,
|
||||||
Hidden: c.CompletionOptions.HiddenDefaultCmd,
|
Hidden: c.CompletionOptions.HiddenDefaultCmd,
|
||||||
GroupID: c.completionCommandGroupID,
|
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)
|
c.AddCommand(completionCmd)
|
||||||
|
|
||||||
|
|
|
@ -2591,6 +2591,42 @@ func TestDefaultCompletionCmd(t *testing.T) {
|
||||||
rootCmd.CompletionOptions.HiddenDefaultCmd = false
|
rootCmd.CompletionOptions.HiddenDefaultCmd = false
|
||||||
// Remove completion command for the next test
|
// Remove completion command for the next test
|
||||||
removeCompCmd(rootCmd)
|
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) {
|
func TestCompleteCompletion(t *testing.T) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue