diff --git a/command.go b/command.go index a6195716..78ea679d 100644 --- a/command.go +++ b/command.go @@ -209,7 +209,7 @@ type Command struct { } // Context returns underlying command context. If command wasn't -// executed with ExecuteContext the returned context will be nil. +// executed with ExecuteContext Context returns Background context. func (c *Command) Context() context.Context { return c.ctx } @@ -886,6 +886,10 @@ func (c *Command) Execute() error { // ExecuteC executes the command. func (c *Command) ExecuteC() (cmd *Command, err error) { + if c.ctx == nil { + c.ctx = context.Background() + } + // Regardless of what command execute is called on, run on Root only if c.HasParent() { return c.Root().ExecuteC() diff --git a/command_test.go b/command_test.go index 2d9b5847..05a3c0f2 100644 --- a/command_test.go +++ b/command_test.go @@ -147,7 +147,7 @@ func TestSubcommandExecuteC(t *testing.T) { } func TestExecuteContext(t *testing.T) { - ctx := context.Background() + ctx := context.TODO() ctxRun := func(cmd *Command, args []string) { if cmd.Context() != ctx { @@ -175,6 +175,33 @@ func TestExecuteContext(t *testing.T) { } } +func TestExecute_NoContext(t *testing.T) { + run := func(cmd *Command, args []string) { + if cmd.Context() != context.Background() { + t.Errorf("Command %s must have background context", cmd.Use) + } + } + + rootCmd := &Command{Use: "root", Run: run, PreRun: run} + childCmd := &Command{Use: "child", Run: run, PreRun: run} + granchildCmd := &Command{Use: "grandchild", Run: run, PreRun: run} + + childCmd.AddCommand(granchildCmd) + rootCmd.AddCommand(childCmd) + + if _, err := executeCommand(rootCmd, ""); err != nil { + t.Errorf("Root command must not fail: %+v", err) + } + + if _, err := executeCommand(rootCmd, "child"); err != nil { + t.Errorf("Subcommand must not fail: %+v", err) + } + + if _, err := executeCommand(rootCmd, "child", "grandchild"); err != nil { + t.Errorf("Command child must not fail: %+v", err) + } +} + func TestRootUnknownCommandSilenced(t *testing.T) { rootCmd := &Command{Use: "root", Run: emptyRun} rootCmd.SilenceErrors = true