From a6e61a3a8d49eaa720906f7023fef7d11e56af6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mislav=20Marohni=C4=87?= Date: Thu, 31 Oct 2019 13:21:22 +0100 Subject: [PATCH 1/3] Silence Cobra usage on errors When an error occurs anywhere in a command, Cobra used to print the error itself and command usage help. We already print error in `main()`, and we don't want to use command usage string on anything other than flag-parsing errors. This also fixes the double output of each error. --- command/root.go | 16 ++++++++++++---- main.go | 4 +++- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/command/root.go b/command/root.go index c0b676c86..51c602511 100644 --- a/command/root.go +++ b/command/root.go @@ -1,6 +1,7 @@ package command import ( + "errors" "fmt" "os" @@ -16,17 +17,24 @@ func init() { RootCmd.PersistentFlags().StringP("current-branch", "B", "", "current git branch") // TODO: // RootCmd.PersistentFlags().BoolP("verbose", "V", false, "enable verbose output") + + RootCmd.SetFlagErrorFunc(func(cmd *cobra.Command, err error) error { + cmd.Println(err) + cmd.Println(cmd.UsageString()) + return SilentErr + }) } +var SilentErr = errors.New("SilentErr") + // RootCmd is the entry point of command-line execution var RootCmd = &cobra.Command{ Use: "gh", Short: "GitHub CLI", Long: `Do things with GitHub from your terminal`, - Args: cobra.MinimumNArgs(1), - Run: func(cmd *cobra.Command, args []string) { - fmt.Println("root") - }, + + SilenceErrors: true, + SilenceUsage: true, } // overriden in tests diff --git a/main.go b/main.go index f954ae933..2ef3e1e2c 100644 --- a/main.go +++ b/main.go @@ -9,7 +9,9 @@ import ( func main() { if err := command.RootCmd.Execute(); err != nil { - fmt.Println(err) + if err != command.SilentErr { + fmt.Println(err) + } os.Exit(1) } } From faa96be9eadd3fe5d9f4b23637322946ddbb2fea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mislav=20Marohni=C4=87?= Date: Thu, 31 Oct 2019 15:46:38 +0100 Subject: [PATCH 2/3] Ensure that errors are printed to stderr --- main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.go b/main.go index 2ef3e1e2c..ae20c309d 100644 --- a/main.go +++ b/main.go @@ -10,7 +10,7 @@ import ( func main() { if err := command.RootCmd.Execute(); err != nil { if err != command.SilentErr { - fmt.Println(err) + fmt.Fprintln(os.Stderr, err) } os.Exit(1) } From e87775845d3e19548448acc6f26692ffce11998c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mislav=20Marohni=C4=87?= Date: Thu, 31 Oct 2019 22:44:43 +0100 Subject: [PATCH 3/3] Also print cmd usage string on "unknown command" --- command/root.go | 10 +++++----- main.go | 9 ++++++--- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/command/root.go b/command/root.go index 51c602511..a309960e3 100644 --- a/command/root.go +++ b/command/root.go @@ -1,7 +1,6 @@ package command import ( - "errors" "fmt" "os" @@ -19,13 +18,14 @@ func init() { // RootCmd.PersistentFlags().BoolP("verbose", "V", false, "enable verbose output") RootCmd.SetFlagErrorFunc(func(cmd *cobra.Command, err error) error { - cmd.Println(err) - cmd.Println(cmd.UsageString()) - return SilentErr + return FlagError{err} }) } -var SilentErr = errors.New("SilentErr") +// FlagError is the kind of error raised in flag processing +type FlagError struct { + error +} // RootCmd is the entry point of command-line execution var RootCmd = &cobra.Command{ diff --git a/main.go b/main.go index ae20c309d..e7f94a5d0 100644 --- a/main.go +++ b/main.go @@ -3,14 +3,17 @@ package main import ( "fmt" "os" + "strings" "github.com/github/gh-cli/command" ) func main() { - if err := command.RootCmd.Execute(); err != nil { - if err != command.SilentErr { - fmt.Fprintln(os.Stderr, err) + if cmd, err := command.RootCmd.ExecuteC(); err != nil { + fmt.Fprintln(os.Stderr, err) + _, isFlagError := err.(command.FlagError) + if isFlagError || strings.HasPrefix(err.Error(), "unknown command ") { + fmt.Fprintln(os.Stderr, cmd.UsageString()) } os.Exit(1) }