forked from mirror/cobra
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.
This commit is contained in:
parent
0bc8bfbe59
commit
40d34bca1b
|
@ -177,7 +177,7 @@ var rootCmd = &cobra.Command{
|
||||||
|
|
||||||
func Execute() {
|
func Execute() {
|
||||||
if err := rootCmd.Execute(); err != nil {
|
if err := rootCmd.Execute(); err != nil {
|
||||||
fmt.Println(err)
|
fmt.Fprintln(os.Stderr, err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
14
command.go
14
command.go
|
@ -367,7 +367,7 @@ func (c *Command) UsageFunc() (f func(*Command) error) {
|
||||||
c.mergePersistentFlags()
|
c.mergePersistentFlags()
|
||||||
err := tmpl(c.OutOrStderr(), c.UsageTemplate(), c)
|
err := tmpl(c.OutOrStderr(), c.UsageTemplate(), c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Println(err)
|
c.PrintErrln(err)
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -395,7 +395,7 @@ func (c *Command) HelpFunc() func(*Command, []string) {
|
||||||
// See https://github.com/spf13/cobra/issues/1002
|
// See https://github.com/spf13/cobra/issues/1002
|
||||||
err := tmpl(c.OutOrStdout(), c.HelpTemplate(), c)
|
err := tmpl(c.OutOrStdout(), c.HelpTemplate(), c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Println(err)
|
c.PrintErrln(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -938,8 +938,8 @@ func (c *Command) ExecuteC() (cmd *Command, err error) {
|
||||||
c = cmd
|
c = cmd
|
||||||
}
|
}
|
||||||
if !c.SilenceErrors {
|
if !c.SilenceErrors {
|
||||||
c.Println("Error:", err.Error())
|
c.PrintErrln("Error:", err.Error())
|
||||||
c.Printf("Run '%v --help' for usage.\n", c.CommandPath())
|
c.PrintErrf("Run '%v --help' for usage.\n", c.CommandPath())
|
||||||
}
|
}
|
||||||
return c, err
|
return c, err
|
||||||
}
|
}
|
||||||
|
@ -967,7 +967,7 @@ func (c *Command) ExecuteC() (cmd *Command, err error) {
|
||||||
// If root command has SilentErrors flagged,
|
// If root command has SilentErrors flagged,
|
||||||
// all subcommands should respect it
|
// all subcommands should respect it
|
||||||
if !cmd.SilenceErrors && !c.SilenceErrors {
|
if !cmd.SilenceErrors && !c.SilenceErrors {
|
||||||
c.Println("Error:", err.Error())
|
c.PrintErrln("Error:", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
// If root command has SilentUsage flagged,
|
// If root command has SilentUsage flagged,
|
||||||
|
@ -1209,12 +1209,12 @@ func (c *Command) PrintErr(i ...interface{}) {
|
||||||
|
|
||||||
// PrintErrln is a convenience method to Println to the defined Err output, fallback to Stderr if not set.
|
// PrintErrln is a convenience method to Println to the defined Err output, fallback to Stderr if not set.
|
||||||
func (c *Command) PrintErrln(i ...interface{}) {
|
func (c *Command) PrintErrln(i ...interface{}) {
|
||||||
c.Print(fmt.Sprintln(i...))
|
c.PrintErr(fmt.Sprintln(i...))
|
||||||
}
|
}
|
||||||
|
|
||||||
// PrintErrf is a convenience method to Printf to the defined Err output, fallback to Stderr if not set.
|
// PrintErrf is a convenience method to Printf to the defined Err output, fallback to Stderr if not set.
|
||||||
func (c *Command) PrintErrf(format string, i ...interface{}) {
|
func (c *Command) PrintErrf(format string, i ...interface{}) {
|
||||||
c.Print(fmt.Sprintf(format, i...))
|
c.PrintErr(fmt.Sprintf(format, i...))
|
||||||
}
|
}
|
||||||
|
|
||||||
// CommandPath returns the full path to this command.
|
// CommandPath returns the full path to this command.
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -1636,6 +1637,47 @@ func TestUsageStringRedirected(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCommandPrintRedirection(t *testing.T) {
|
||||||
|
errBuff, outBuff := bytes.NewBuffer(nil), bytes.NewBuffer(nil)
|
||||||
|
root := &Command{
|
||||||
|
Run: func(cmd *Command, args []string) {
|
||||||
|
|
||||||
|
cmd.PrintErr("PrintErr")
|
||||||
|
cmd.PrintErrln("PrintErr", "line")
|
||||||
|
cmd.PrintErrf("PrintEr%s", "r")
|
||||||
|
|
||||||
|
cmd.Print("Print")
|
||||||
|
cmd.Println("Print", "line")
|
||||||
|
cmd.Printf("Prin%s", "t")
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
root.SetErr(errBuff)
|
||||||
|
root.SetOut(outBuff)
|
||||||
|
|
||||||
|
if err := root.Execute(); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
gotErrBytes, err := ioutil.ReadAll(errBuff)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
gotOutBytes, err := ioutil.ReadAll(outBuff)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if wantErr := []byte("PrintErrPrintErr line\nPrintErr"); !bytes.Equal(gotErrBytes, wantErr) {
|
||||||
|
t.Errorf("got: '%s' want: '%s'", gotErrBytes, wantErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
if wantOut := []byte("PrintPrint line\nPrint"); !bytes.Equal(gotOutBytes, wantOut) {
|
||||||
|
t.Errorf("got: '%s' want: '%s'", gotOutBytes, wantOut)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestFlagErrorFunc(t *testing.T) {
|
func TestFlagErrorFunc(t *testing.T) {
|
||||||
c := &Command{Use: "c", Run: emptyRun}
|
c := &Command{Use: "c", Run: emptyRun}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue