Skip to content

Commit 40d34bc

Browse files
author
Alessio Treglia
authored
Fix stderr printing functions (#894)
* Fix stderr printing functions Follow-up of #822 * Errors go to stderr as per POSIX * use PrintErrf() instead of extra call to Sprintf() * Error messages should always be printed to os.Stderr. * add test case for Print* redirection Thanks: @bukowa for the patch.
1 parent 0bc8bfb commit 40d34bc

File tree

3 files changed

+50
-8
lines changed

3 files changed

+50
-8
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ var rootCmd = &cobra.Command{
177177

178178
func Execute() {
179179
if err := rootCmd.Execute(); err != nil {
180-
fmt.Println(err)
180+
fmt.Fprintln(os.Stderr, err)
181181
os.Exit(1)
182182
}
183183
}

command.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,7 @@ func (c *Command) UsageFunc() (f func(*Command) error) {
367367
c.mergePersistentFlags()
368368
err := tmpl(c.OutOrStderr(), c.UsageTemplate(), c)
369369
if err != nil {
370-
c.Println(err)
370+
c.PrintErrln(err)
371371
}
372372
return err
373373
}
@@ -395,7 +395,7 @@ func (c *Command) HelpFunc() func(*Command, []string) {
395395
// See https://github.com/spf13/cobra/issues/1002
396396
err := tmpl(c.OutOrStdout(), c.HelpTemplate(), c)
397397
if err != nil {
398-
c.Println(err)
398+
c.PrintErrln(err)
399399
}
400400
}
401401
}
@@ -938,8 +938,8 @@ func (c *Command) ExecuteC() (cmd *Command, err error) {
938938
c = cmd
939939
}
940940
if !c.SilenceErrors {
941-
c.Println("Error:", err.Error())
942-
c.Printf("Run '%v --help' for usage.\n", c.CommandPath())
941+
c.PrintErrln("Error:", err.Error())
942+
c.PrintErrf("Run '%v --help' for usage.\n", c.CommandPath())
943943
}
944944
return c, err
945945
}
@@ -967,7 +967,7 @@ func (c *Command) ExecuteC() (cmd *Command, err error) {
967967
// If root command has SilentErrors flagged,
968968
// all subcommands should respect it
969969
if !cmd.SilenceErrors && !c.SilenceErrors {
970-
c.Println("Error:", err.Error())
970+
c.PrintErrln("Error:", err.Error())
971971
}
972972

973973
// If root command has SilentUsage flagged,
@@ -1209,12 +1209,12 @@ func (c *Command) PrintErr(i ...interface{}) {
12091209

12101210
// PrintErrln is a convenience method to Println to the defined Err output, fallback to Stderr if not set.
12111211
func (c *Command) PrintErrln(i ...interface{}) {
1212-
c.Print(fmt.Sprintln(i...))
1212+
c.PrintErr(fmt.Sprintln(i...))
12131213
}
12141214

12151215
// PrintErrf is a convenience method to Printf to the defined Err output, fallback to Stderr if not set.
12161216
func (c *Command) PrintErrf(format string, i ...interface{}) {
1217-
c.Print(fmt.Sprintf(format, i...))
1217+
c.PrintErr(fmt.Sprintf(format, i...))
12181218
}
12191219

12201220
// CommandPath returns the full path to this command.

command_test.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"bytes"
55
"context"
66
"fmt"
7+
"io/ioutil"
78
"os"
89
"reflect"
910
"strings"
@@ -1636,6 +1637,47 @@ func TestUsageStringRedirected(t *testing.T) {
16361637
}
16371638
}
16381639

1640+
func TestCommandPrintRedirection(t *testing.T) {
1641+
errBuff, outBuff := bytes.NewBuffer(nil), bytes.NewBuffer(nil)
1642+
root := &Command{
1643+
Run: func(cmd *Command, args []string) {
1644+
1645+
cmd.PrintErr("PrintErr")
1646+
cmd.PrintErrln("PrintErr", "line")
1647+
cmd.PrintErrf("PrintEr%s", "r")
1648+
1649+
cmd.Print("Print")
1650+
cmd.Println("Print", "line")
1651+
cmd.Printf("Prin%s", "t")
1652+
},
1653+
}
1654+
1655+
root.SetErr(errBuff)
1656+
root.SetOut(outBuff)
1657+
1658+
if err := root.Execute(); err != nil {
1659+
t.Error(err)
1660+
}
1661+
1662+
gotErrBytes, err := ioutil.ReadAll(errBuff)
1663+
if err != nil {
1664+
t.Error(err)
1665+
}
1666+
1667+
gotOutBytes, err := ioutil.ReadAll(outBuff)
1668+
if err != nil {
1669+
t.Error(err)
1670+
}
1671+
1672+
if wantErr := []byte("PrintErrPrintErr line\nPrintErr"); !bytes.Equal(gotErrBytes, wantErr) {
1673+
t.Errorf("got: '%s' want: '%s'", gotErrBytes, wantErr)
1674+
}
1675+
1676+
if wantOut := []byte("PrintPrint line\nPrint"); !bytes.Equal(gotOutBytes, wantOut) {
1677+
t.Errorf("got: '%s' want: '%s'", gotOutBytes, wantOut)
1678+
}
1679+
}
1680+
16391681
func TestFlagErrorFunc(t *testing.T) {
16401682
c := &Command{Use: "c", Run: emptyRun}
16411683

0 commit comments

Comments
 (0)