Skip to content

Commit 77c2150

Browse files
authored
Merge pull request #2329 from c-tonneslan/fix/inherit-parent-writer-to-subcommand
inherit Reader/Writer/ErrWriter from parent on subcommand setup
2 parents eb79f05 + 34744b4 commit 77c2150

2 files changed

Lines changed: 47 additions & 6 deletions

File tree

command_setup.go

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,18 +46,33 @@ func (cmd *Command) setupDefaults(osArgs []string) {
4646
}
4747

4848
if cmd.Reader == nil {
49-
tracef("setting default Reader as os.Stdin (cmd=%[1]q)", cmd.Name)
50-
cmd.Reader = os.Stdin
49+
if cmd.parent != nil && cmd.parent.Reader != nil {
50+
tracef("inheriting Reader from parent (cmd=%[1]q)", cmd.Name)
51+
cmd.Reader = cmd.parent.Reader
52+
} else {
53+
tracef("setting default Reader as os.Stdin (cmd=%[1]q)", cmd.Name)
54+
cmd.Reader = os.Stdin
55+
}
5156
}
5257

5358
if cmd.Writer == nil {
54-
tracef("setting default Writer as os.Stdout (cmd=%[1]q)", cmd.Name)
55-
cmd.Writer = os.Stdout
59+
if cmd.parent != nil && cmd.parent.Writer != nil {
60+
tracef("inheriting Writer from parent (cmd=%[1]q)", cmd.Name)
61+
cmd.Writer = cmd.parent.Writer
62+
} else {
63+
tracef("setting default Writer as os.Stdout (cmd=%[1]q)", cmd.Name)
64+
cmd.Writer = os.Stdout
65+
}
5666
}
5767

5868
if cmd.ErrWriter == nil {
59-
tracef("setting default ErrWriter as os.Stderr (cmd=%[1]q)", cmd.Name)
60-
cmd.ErrWriter = os.Stderr
69+
if cmd.parent != nil && cmd.parent.ErrWriter != nil {
70+
tracef("inheriting ErrWriter from parent (cmd=%[1]q)", cmd.Name)
71+
cmd.ErrWriter = cmd.parent.ErrWriter
72+
} else {
73+
tracef("setting default ErrWriter as os.Stderr (cmd=%[1]q)", cmd.Name)
74+
cmd.ErrWriter = os.Stderr
75+
}
6176
}
6277

6378
if cmd.AllowExtFlags {

command_test.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2833,6 +2833,32 @@ func TestSetupInitializesOnlyNilWriters(t *testing.T) {
28332833
assert.Equal(t, cmd.Writer, os.Stdout, "expected a.Writer to be os.Stdout")
28342834
}
28352835

2836+
// Regression for #2325. A Writer set on the root command should reach
2837+
// the subcommand's Action via c.Writer, not get silently replaced by
2838+
// os.Stdout the first time the subcommand runs setupDefaults.
2839+
func TestSubcommandInheritsRootWriters(t *testing.T) {
2840+
var out, errOut bytes.Buffer
2841+
root := &Command{
2842+
Name: "demo",
2843+
Writer: &out,
2844+
ErrWriter: &errOut,
2845+
Commands: []*Command{
2846+
{
2847+
Name: "sub",
2848+
Action: func(_ context.Context, c *Command) error {
2849+
_, _ = fmt.Fprintln(c.Writer, "from sub")
2850+
_, _ = fmt.Fprintln(c.ErrWriter, "errors from sub")
2851+
return nil
2852+
},
2853+
},
2854+
},
2855+
}
2856+
2857+
assert.NoError(t, root.Run(buildTestContext(t), []string{"demo", "sub"}))
2858+
assert.Equal(t, "from sub\n", out.String())
2859+
assert.Equal(t, "errors from sub\n", errOut.String())
2860+
}
2861+
28362862
func TestFlagAction(t *testing.T) {
28372863
now := time.Now().UTC().Truncate(time.Minute)
28382864
testCases := []struct {

0 commit comments

Comments
 (0)