Address comments

Signed-off-by: Marc Khouzam <marc.khouzam@gmail.com>
This commit is contained in:
Marc Khouzam 2024-06-11 10:45:02 -04:00
parent 8e517009e7
commit 9fbba57c76
2 changed files with 104 additions and 99 deletions

View file

@ -469,10 +469,8 @@ func (c *Command) HelpFunc() func(*Command, []string) {
} }
} }
// Help puts out the help for the command. // Help invokes the HelpFunc without arguments.
// Kept for backwards compatibility. // Kept for backwards compatibility.
// No longer used because it does not allow
// to pass arguments to the help command.
// Can be a simple way to trigger the help // Can be a simple way to trigger the help
// if arguments are not needed. // if arguments are not needed.
func (c *Command) Help() error { func (c *Command) Help() error {
@ -1124,11 +1122,14 @@ func (c *Command) ExecuteC() (cmd *Command, err error) {
if errors.Is(err, flag.ErrHelp) { if errors.Is(err, flag.ErrHelp) {
// The call to execute() above has parsed the flags. // The call to execute() above has parsed the flags.
// We therefore only pass the remaining arguments to the help function. // We therefore only pass the remaining arguments to the help function.
argWoFlags := cmd.Flags().Args() remainingArgs := cmd.Flags().Args()
if cmd.DisableFlagParsing { if cmd.DisableFlagParsing {
argWoFlags = flags // For commands that have DisableFlagParsing == true, the flag parsing
// was not done and cmd.Flags().Args() is not filled. We therefore
// use the full set of arguments, which include flags.
remainingArgs = flags
} }
cmd.HelpFunc()(cmd, argWoFlags) cmd.HelpFunc()(cmd, remainingArgs)
return cmd, nil return cmd, nil
} }

View file

@ -12,7 +12,6 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
//nolint:goconst
package cobra package cobra
import ( import (
@ -1080,83 +1079,108 @@ func TestHelpExecutedOnNonRunnableChild(t *testing.T) {
checkStringContains(t, output, childCmd.Long) checkStringContains(t, output, childCmd.Long)
} }
type overridingHelp struct {
expectedCmdName string
expectedArgs []string
helpCalled bool
err error
}
func (o *overridingHelp) helpFunc() func(c *Command, args []string) {
return func(c *Command, args []string) {
o.helpCalled = true
if c.Name() != o.expectedCmdName {
o.err = fmt.Errorf("Expected command name: %q, got %q", o.expectedCmdName, c.Name())
return
}
if len(args) != len(o.expectedArgs) {
o.err = fmt.Errorf("Expected args %v, got %v", o.expectedArgs, args)
return
}
for i, arg := range o.expectedArgs {
if args[i] != arg {
o.err = fmt.Errorf("Expected args %v, got %v", o.expectedArgs, args)
return
}
}
}
}
func (o *overridingHelp) checkError() error {
if o.err != nil {
return o.err
}
if !o.helpCalled {
return fmt.Errorf("Overridden help function not called")
}
return nil
}
func TestHelpOverrideOnRoot(t *testing.T) { func TestHelpOverrideOnRoot(t *testing.T) {
var helpCalled bool
rootCmd := &Command{Use: "root"} rootCmd := &Command{Use: "root"}
rootCmd.SetHelpFunc(func(c *Command, args []string) {
helpCalled = true override := overridingHelp{
if c.Name() != "root" { expectedCmdName: rootCmd.Name(),
t.Errorf(`Expected command name: "root", got %q`, c.Name()) expectedArgs: []string{"arg1", "arg2"},
} }
if len(args) != 2 || args[0] != "arg1" || args[1] != "arg2" { rootCmd.SetHelpFunc(override.helpFunc())
t.Errorf("Expected args [args1 arg2], got %v", args)
}
})
_, err := executeCommand(rootCmd, "arg1", "arg2", "--help") _, err := executeCommand(rootCmd, "arg1", "arg2", "--help")
if err != nil { if err != nil {
t.Errorf("Unexpected error: %v", err) t.Errorf("Unexpected error executing command: %v", err)
} }
if !helpCalled { if err = override.checkError(); err != nil {
t.Error("Overridden help function not called") t.Errorf("Unexpected error from help function: %v", err)
} }
} }
func TestHelpOverrideOnChild(t *testing.T) { func TestHelpOverrideOnChild(t *testing.T) {
var helpCalled bool
rootCmd := &Command{Use: "root"} rootCmd := &Command{Use: "root"}
subCmd := &Command{Use: "child"} subCmd := &Command{Use: "child"}
rootCmd.AddCommand(subCmd) rootCmd.AddCommand(subCmd)
subCmd.SetHelpFunc(func(c *Command, args []string) { override := overridingHelp{
helpCalled = true expectedCmdName: subCmd.Name(),
if c.Name() != "child" { expectedArgs: []string{"arg1", "arg2"},
t.Errorf(`Expected command name: "child", got %q`, c.Name())
} }
if len(args) != 2 || args[0] != "arg1" || args[1] != "arg2" { subCmd.SetHelpFunc(override.helpFunc())
t.Errorf("Expected args [args1 arg2], got %v", args)
}
})
_, err := executeCommand(rootCmd, "child", "arg1", "arg2", "--help") _, err := executeCommand(rootCmd, "child", "arg1", "arg2", "--help")
if err != nil { if err != nil {
t.Errorf("Unexpected error: %v", err) t.Errorf("Unexpected error executing command: %v", err)
} }
if !helpCalled { if err = override.checkError(); err != nil {
t.Error("Overridden help function not called") t.Errorf("Unexpected error from help function: %v", err)
} }
} }
func TestHelpOverrideOnRootWithChild(t *testing.T) { func TestHelpOverrideOnRootWithChild(t *testing.T) {
var helpCalled bool
rootCmd := &Command{Use: "root"} rootCmd := &Command{Use: "root"}
subCmd := &Command{Use: "child"} subCmd := &Command{Use: "child"}
rootCmd.AddCommand(subCmd) rootCmd.AddCommand(subCmd)
rootCmd.SetHelpFunc(func(c *Command, args []string) { override := overridingHelp{
helpCalled = true expectedCmdName: subCmd.Name(),
if c.Name() != "child" { expectedArgs: []string{"arg1", "arg2"},
t.Errorf(`Expected command name: "child", got %q`, c.Name())
} }
if len(args) != 2 || args[0] != "arg1" || args[1] != "arg2" { rootCmd.SetHelpFunc(override.helpFunc())
t.Errorf("Expected args [args1 arg2], got %v", args)
}
})
_, err := executeCommand(rootCmd, "child", "arg1", "arg2", "--help") _, err := executeCommand(rootCmd, "child", "arg1", "arg2", "--help")
if err != nil { if err != nil {
t.Errorf("Unexpected error: %v", err) t.Errorf("Unexpected error executing command: %v", err)
} }
if !helpCalled { if err = override.checkError(); err != nil {
t.Error("Overridden help function not called") t.Errorf("Unexpected error from help function: %v", err)
} }
} }
func TestHelpOverrideOnRootWithChildAndFlags(t *testing.T) { func TestHelpOverrideOnRootWithChildAndFlags(t *testing.T) {
var helpCalled bool
rootCmd := &Command{Use: "root"} rootCmd := &Command{Use: "root"}
subCmd := &Command{Use: "child"} subCmd := &Command{Use: "child"}
rootCmd.AddCommand(subCmd) rootCmd.AddCommand(subCmd)
@ -1164,28 +1188,23 @@ func TestHelpOverrideOnRootWithChildAndFlags(t *testing.T) {
var myFlag bool var myFlag bool
subCmd.Flags().BoolVar(&myFlag, "myflag", false, "") subCmd.Flags().BoolVar(&myFlag, "myflag", false, "")
rootCmd.SetHelpFunc(func(c *Command, args []string) { override := overridingHelp{
helpCalled = true expectedCmdName: subCmd.Name(),
if c.Name() != "child" { expectedArgs: []string{"arg1", "arg2"},
t.Errorf(`Expected command name: "child", got %q`, c.Name())
} }
if len(args) != 2 || args[0] != "arg1" || args[1] != "arg2" { rootCmd.SetHelpFunc(override.helpFunc())
t.Errorf("Expected args [args1 arg2], got %v", args)
}
})
_, err := executeCommand(rootCmd, "child", "arg1", "--myflag", "arg2", "--help") _, err := executeCommand(rootCmd, "child", "arg1", "--myflag", "arg2", "--help")
if err != nil { if err != nil {
t.Errorf("Unexpected error: %v", err) t.Errorf("Unexpected error executing command: %v", err)
} }
if !helpCalled { if err = override.checkError(); err != nil {
t.Error("Overridden help function not called") t.Errorf("Unexpected error from help function: %v", err)
} }
} }
func TestHelpOverrideOnRootWithChildAndFlagsButParsingDisabled(t *testing.T) { func TestHelpOverrideOnRootWithChildAndFlagsButParsingDisabled(t *testing.T) {
var helpCalled bool
rootCmd := &Command{Use: "root"} rootCmd := &Command{Use: "root"}
subCmd := &Command{Use: "child", DisableFlagParsing: true} subCmd := &Command{Use: "child", DisableFlagParsing: true}
rootCmd.AddCommand(subCmd) rootCmd.AddCommand(subCmd)
@ -1193,76 +1212,61 @@ func TestHelpOverrideOnRootWithChildAndFlagsButParsingDisabled(t *testing.T) {
var myFlag bool var myFlag bool
subCmd.Flags().BoolVar(&myFlag, "myflag", false, "") subCmd.Flags().BoolVar(&myFlag, "myflag", false, "")
rootCmd.SetHelpFunc(func(c *Command, args []string) { override := overridingHelp{
helpCalled = true expectedCmdName: subCmd.Name(),
if c.Name() != "child" { expectedArgs: []string{"arg1", "--myflag", "arg2", "--help"},
t.Errorf(`Expected command name: "child", got %q`, c.Name())
} }
if len(args) != 4 || rootCmd.SetHelpFunc(override.helpFunc())
args[0] != "arg1" || args[1] != "--myflag" || args[2] != "arg2" || args[3] != "--help" {
t.Errorf("Expected args [args1 --myflag arg2 --help], got %v", args)
}
})
_, err := executeCommand(rootCmd, "child", "arg1", "--myflag", "arg2", "--help") _, err := executeCommand(rootCmd, "child", "arg1", "--myflag", "arg2", "--help")
if err != nil { if err != nil {
t.Errorf("Unexpected error: %v", err) t.Errorf("Unexpected error executing command: %v", err)
} }
if !helpCalled { if err = override.checkError(); err != nil {
t.Error("Overridden help function not called") t.Errorf("Unexpected error from help function: %v", err)
} }
} }
func TestHelpCommandOverrideOnChild(t *testing.T) { func TestHelpCommandOverrideOnChild(t *testing.T) {
var helpCalled bool
rootCmd := &Command{Use: "root"} rootCmd := &Command{Use: "root"}
subCmd := &Command{Use: "child"} subCmd := &Command{Use: "child"}
rootCmd.AddCommand(subCmd) rootCmd.AddCommand(subCmd)
subCmd.SetHelpFunc(func(c *Command, args []string) { override := overridingHelp{
helpCalled = true expectedCmdName: subCmd.Name(),
if c.Name() != "child" { expectedArgs: []string{"arg1", "arg2"},
t.Errorf(`Expected command name: "child", got %q`, c.Name())
} }
if len(args) != 2 || args[0] != "arg1" || args[1] != "arg2" { subCmd.SetHelpFunc(override.helpFunc())
t.Errorf("Expected args [args1 arg2], got %v", args)
}
})
_, err := executeCommand(rootCmd, "help", "child", "arg1", "arg2") _, err := executeCommand(rootCmd, "help", "child", "arg1", "arg2")
if err != nil { if err != nil {
t.Errorf("Unexpected error: %v", err) t.Errorf("Unexpected error executing command: %v", err)
} }
if !helpCalled { if err = override.checkError(); err != nil {
t.Error("Overridden help function not called") t.Errorf("Unexpected error from help function: %v", err)
} }
} }
func TestHelpCommandOverrideOnRootWithChild(t *testing.T) { func TestHelpCommandOverrideOnRootWithChild(t *testing.T) {
var helpCalled bool
rootCmd := &Command{Use: "root"} rootCmd := &Command{Use: "root"}
subCmd := &Command{Use: "child"} subCmd := &Command{Use: "child"}
rootCmd.AddCommand(subCmd) rootCmd.AddCommand(subCmd)
rootCmd.SetHelpFunc(func(c *Command, args []string) { override := overridingHelp{
helpCalled = true expectedCmdName: subCmd.Name(),
if c.Name() != "child" { expectedArgs: []string{"arg1", "arg2"},
t.Errorf(`Expected command name: "child", got %q`, c.Name())
} }
if len(args) != 2 || args[0] != "arg1" || args[1] != "arg2" { rootCmd.SetHelpFunc(override.helpFunc())
t.Errorf("Expected args [args1 arg2], got %v", args)
}
})
_, err := executeCommand(rootCmd, "help", "child", "arg1", "arg2") _, err := executeCommand(rootCmd, "help", "child", "arg1", "arg2")
if err != nil { if err != nil {
t.Errorf("Unexpected error: %v", err) t.Errorf("Unexpected error executing command: %v", err)
} }
if !helpCalled { if err = override.checkError(); err != nil {
t.Error("Overridden help function not called") t.Errorf("Unexpected error from help function: %v", err)
} }
} }