Skip to content

Commit 183b3a2

Browse files
authored
Merge pull request #2363 from dearchap/issue_2250
fix: skip After hook when help is displayed on subcommand
2 parents 2c38e7b + 2f7149e commit 183b3a2

2 files changed

Lines changed: 51 additions & 0 deletions

File tree

command_run.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import (
99
"unicode"
1010
)
1111

12+
type helpShownKey struct{}
13+
1214
func (cmd *Command) parseArgsFromStdin() ([]string, error) {
1315
type state int
1416
const (
@@ -176,6 +178,7 @@ func (cmd *Command) run(ctx context.Context, osArgs []string) (_ context.Context
176178

177179
cmd.isInError = true
178180
if cmd.checkHelp() {
181+
ctx = context.WithValue(ctx, helpShownKey{}, true)
179182
if cmd.parent == nil {
180183
_ = ShowRootCommandHelp(cmd)
181184
} else {
@@ -210,6 +213,7 @@ func (cmd *Command) run(ctx context.Context, osArgs []string) (_ context.Context
210213
}
211214

212215
if cmd.checkHelp() {
216+
ctx = context.WithValue(ctx, helpShownKey{}, true)
213217
return ctx, helpCommandAction(ctx, cmd)
214218
} else {
215219
tracef("no help is wanted (cmd=%[1]q)", cmd.Name)
@@ -234,6 +238,9 @@ func (cmd *Command) run(ctx context.Context, osArgs []string) (_ context.Context
234238

235239
if cmd.After != nil && !cmd.Root().shellCompletion {
236240
defer func() {
241+
if ctx.Value(helpShownKey{}) != nil {
242+
return
243+
}
237244
if err := cmd.After(ctx, cmd); err != nil {
238245
err = cmd.handleExitCoder(ctx, err)
239246

command_test.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1810,6 +1810,50 @@ func TestCommand_AfterFunc(t *testing.T) {
18101810
assert.Equal(t, 0, counts.SubCommand, "Subcommand not executed when expected")
18111811
}
18121812

1813+
func TestCommand_AfterNotCalledOnSubcommandHelp(t *testing.T) {
1814+
var afterCalled bool
1815+
cmd := &Command{
1816+
After: func(_ context.Context, _ *Command) error {
1817+
afterCalled = true
1818+
return nil
1819+
},
1820+
Commands: []*Command{
1821+
{
1822+
Name: "sub",
1823+
Action: func(context.Context, *Command) error {
1824+
return nil
1825+
},
1826+
},
1827+
},
1828+
}
1829+
1830+
err := cmd.Run(buildTestContext(t), []string{"app", "sub", "--help"})
1831+
require.NoError(t, err)
1832+
assert.False(t, afterCalled, "After should not be called when --help is passed to subcommand")
1833+
}
1834+
1835+
func TestCommand_AfterStillCalledOnNormalSubcommand(t *testing.T) {
1836+
var afterCalled bool
1837+
cmd := &Command{
1838+
After: func(_ context.Context, _ *Command) error {
1839+
afterCalled = true
1840+
return nil
1841+
},
1842+
Commands: []*Command{
1843+
{
1844+
Name: "sub",
1845+
Action: func(context.Context, *Command) error {
1846+
return nil
1847+
},
1848+
},
1849+
},
1850+
}
1851+
1852+
err := cmd.Run(buildTestContext(t), []string{"app", "sub"})
1853+
require.NoError(t, err)
1854+
assert.True(t, afterCalled, "After should be called on normal subcommand execution")
1855+
}
1856+
18131857
func TestCommandNoHelpFlag(t *testing.T) {
18141858
oldFlag := HelpFlag
18151859
defer func() {

0 commit comments

Comments
 (0)