Repository: spf13/cobra
Pull request #912 (2019-07-19 04:08:42)

Used goimports to fix import order
Keeps the list sorted and prevents future merge conflicts.

CLAassistant: [![CLA assistant check](https://cla-assistant.io/pull/badge/not_signed)](https://cla-assistant.io/spf13/cobra?pullRequest=912) <br/>Thank you for your submission, we really appreciate it. Like many open source projects, we ask that you sign our [Contributor License Agreement](https://cla-assistant.io/spf13/cobra?pullRequest=912) before we can accept your contribution.<br/><sub>You have signed the CLA already but the status is still pending? Let us [recheck](https://cla-assistant.io/check/spf13/cobra?pullRequest=912) it.</sub>
umarcor: This PR is already part of #876 (see [first commit](https://github.com/spf13/cobra/pull/876/commits/e9ea59bd041c0997db53effa0f16bd78bb7d3516)). However, I think it's ok to merge it independently, since #876 deprecates golang 1.10 and 1.11.

Patch:
diff --git a/.gitignore b/.gitignore
index 3b053c5..b2b848e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -32,7 +32,8 @@ Session.vim
 tags
 
 *.exe
-
+cobra
 cobra.test
 
-.idea/*
+.idea/
+*.iml
diff --git a/.travis.yml b/.travis.yml
index 38b85f4..fca1e69 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -18,13 +18,10 @@ matrix:
       go: 1.12.x
       script: diff -u <(echo -n) <(gofmt -d -s .)
 
-before_install:
-  - mkdir -p bin
-  - curl -Lso bin/shellcheck https://github.com/caarlos0/shellcheck-docker/releases/download/v0.6.0/shellcheck
-  - chmod +x bin/shellcheck
-  - go get -u github.com/kyoh86/richgo
+before_install: go get -u github.com/kyoh86/richgo
+
 script:
-  - PATH=$PATH:$PWD/bin richgo test -v ./...
+  - richgo test -v ./...
   - go build
   - if [ -z $NOVET ]; then
       diff -u <(echo -n) <(go vet . 2>&1 | grep -vE 'ExampleCommand|bash_completions.*Fprint');
diff --git a/README.md b/README.md
index 1c4d6bc..649e2e2 100644
--- a/README.md
+++ b/README.md
@@ -218,6 +218,8 @@ import (
   "github.com/spf13/viper"
 )
 
+var cfgFile string
+
 func init() {
   cobra.OnInitialize(initConfig)
   rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.cobra.yaml)")
diff --git a/cobra.go b/cobra.go
index 6505c07..d01becc 100644
--- a/cobra.go
+++ b/cobra.go
@@ -52,7 +52,7 @@ var EnableCommandSorting = true
 // if the CLI is started from explorer.exe.
 // To disable the mousetrap, just set this variable to blank string ("").
 // Works only on Microsoft Windows.
-var MousetrapHelpText string = `This is a command line tool.
+var MousetrapHelpText = `This is a command line tool.
 
 You need to open cmd.exe and run it from there.
 `
@@ -61,7 +61,7 @@ You need to open cmd.exe and run it from there.
 // if the CLI is started from explorer.exe. Set to 0 to wait for the return key to be pressed.
 // To disable the mousetrap, just set MousetrapHelpText to blank string ("").
 // Works only on Microsoft Windows.
-var MousetrapDisplayDuration time.Duration = 5 * time.Second
+var MousetrapDisplayDuration = 5 * time.Second
 
 // AddTemplateFunc adds a template function that's available to Usage and Help
 // template generation.
diff --git a/cobra/README.md b/cobra/README.md
index 6054f95..c360fda 100644
--- a/cobra/README.md
+++ b/cobra/README.md
@@ -16,11 +16,23 @@ for you. It is a very powerful application that will populate your program with
 the right structure so you can immediately enjoy all the benefits of Cobra. It
 will also automatically apply the license you specify to your application.
 
-Cobra init is pretty smart. You can provide it a full path, or simply a path
-similar to what is expected in the import.
+Cobra init is pretty smart. You can either run it in your current application directory
+or you can specify a relative path to an existing project. If the directory does not exist, it will be created for you.
+
+Updates to the Cobra generator have now decoupled it from the GOPATH.
+As such `--pkg-name` is required.
+
+**Note:** init will no longer fail on non-empty directories.
+
+```
+mkdir -p newApp && cd newApp
+cobra init --pkg-name github.com/spf13/newApp
+```
+
+or
 
 ```
-cobra init github.com/spf13/newApp
+cobra init --pkg-name github.com/spf13/newApp path/to/newApp
 ```
 
 ### cobra add
diff --git a/cobra/cmd/init.go b/cobra/cmd/init.go
index 63397d1..dcf5ada 100644
--- a/cobra/cmd/init.go
+++ b/cobra/cmd/init.go
@@ -15,10 +15,11 @@ package cmd
 
 import (
 	"fmt"
-	"github.com/spf13/cobra"
-	"github.com/spf13/viper"
 	"os"
 	"path"
+
+	"github.com/spf13/cobra"
+	"github.com/spf13/viper"
 )
 
 var (
diff --git a/cobra/cmd/project.go b/cobra/cmd/project.go
index dd2f7ea..a53893c 100644
--- a/cobra/cmd/project.go
+++ b/cobra/cmd/project.go
@@ -2,9 +2,10 @@ package cmd
 
 import (
 	"fmt"
-	"github.com/spf13/cobra/cobra/tpl"
 	"os"
 	"text/template"
+
+	"github.com/spf13/cobra/cobra/tpl"
 )
 
 // Project contains name, license and paths to projects.
@@ -25,7 +26,6 @@ type Command struct {
 }
 
 func (p *Project) Create() error {
-
 	// check if AbsolutePath exists
 	if _, err := os.Stat(p.AbsolutePath); os.IsNotExist(err) {
 		// create directory
diff --git a/cobra/cmd/root.go b/cobra/cmd/root.go
index 624c717..97f404b 100644
--- a/cobra/cmd/root.go
+++ b/cobra/cmd/root.go
@@ -36,8 +36,8 @@ to quickly create a Cobra application.`,
 )
 
 // Execute executes the root command.
-func Execute() {
-	rootCmd.Execute()
+func Execute() error {
+	return rootCmd.Execute()
 }
 
 func init() {
diff --git a/cobra/main.go b/cobra/main.go
index c3a9d9c..eeaf982 100644
--- a/cobra/main.go
+++ b/cobra/main.go
@@ -13,8 +13,14 @@
 
 package main
 
-import "github.com/spf13/cobra/cobra/cmd"
+import (
+	"os"
+
+	"github.com/spf13/cobra/cobra/cmd"
+)
 
 func main() {
-	cmd.Execute()
+	if err := cmd.Execute(); err != nil {
+		os.Exit(1)
+	}
 }
diff --git a/command.go b/command.go
index c7e8983..42e500d 100644
--- a/command.go
+++ b/command.go
@@ -17,6 +17,7 @@ package cobra
 
 import (
 	"bytes"
+	"errors"
 	"fmt"
 	"io"
 	"os"
@@ -27,6 +28,8 @@ import (
 	flag "github.com/spf13/pflag"
 )
 
+var ErrSubCommandRequired = errors.New("subcommand is required")
+
 // FParseErrWhitelist configures Flag parse errors to be ignored
 type FParseErrWhitelist flag.ParseErrorsWhitelist
 
@@ -228,7 +231,7 @@ func (c *Command) SetErr(newErr io.Writer) {
 	c.errWriter = newErr
 }
 
-// SetOut sets the source for input data
+// SetIn sets the source for input data
 // If newIn is nil, os.Stdin is used.
 func (c *Command) SetIn(newIn io.Reader) {
 	c.inReader = newIn
@@ -297,7 +300,7 @@ func (c *Command) ErrOrStderr() io.Writer {
 	return c.getErr(os.Stderr)
 }
 
-// ErrOrStderr returns output to stderr
+// InOrStdin returns output to stderr
 func (c *Command) InOrStdin() io.Reader {
 	return c.getIn(os.Stdin)
 }
@@ -369,7 +372,7 @@ func (c *Command) HelpFunc() func(*Command, []string) {
 	}
 	return func(c *Command, a []string) {
 		c.mergePersistentFlags()
-		err := tmpl(c.OutOrStdout(), c.HelpTemplate(), c)
+		err := tmpl(c.OutOrStderr(), c.HelpTemplate(), c)
 		if err != nil {
 			c.Println(err)
 		}
@@ -786,7 +789,7 @@ func (c *Command) execute(a []string) (err error) {
 	}
 
 	if !c.Runnable() {
-		return flag.ErrHelp
+		return ErrSubCommandRequired
 	}
 
 	c.preRun()
@@ -920,6 +923,14 @@ func (c *Command) ExecuteC() (cmd *Command, err error) {
 			return cmd, nil
 		}
 
+		// If command wasn't runnable, show full help, but do return the error.
+		// This will result in apps by default returning a non-success exit code, but also gives them the option to
+		// handle specially.
+		if err == ErrSubCommandRequired {
+			cmd.HelpFunc()(cmd, args)
+			return cmd, err
+		}
+
 		// If root command has SilentErrors flagged,
 		// all subcommands should respect it
 		if !cmd.SilenceErrors && !c.SilenceErrors {


Test patch:
diff --git a/command_test.go b/command_test.go
index 2fa2003..b26bd4a 100644
--- a/command_test.go
+++ b/command_test.go
@@ -836,8 +836,8 @@ func TestHelpExecutedOnNonRunnableChild(t *testing.T) {
 	rootCmd.AddCommand(childCmd)
 
 	output, err := executeCommand(rootCmd, "child")
-	if err != nil {
-		t.Errorf("Unexpected error: %v", err)
+	if err != ErrSubCommandRequired {
+		t.Errorf("Expected error")
 	}
 
 	checkStringContains(t, output, childCmd.Long)