From d20925b9326e2e50610b0a21ba0c009f99482a70 Mon Sep 17 00:00:00 2001
From: Albert Nigmatzianov <albertnigma@gmail.com>
Date: Fri, 5 May 2017 10:06:10 +0200
Subject: [PATCH] cmd: Small correctives

---
 cobra/cmd/add.go     | 17 +++++++++--------
 cobra/cmd/helpers.go |  4 ++--
 cobra/cmd/init.go    | 22 ++++++++++++++--------
 cobra/cmd/project.go | 33 ++++++++++++++++++++-------------
 command_test.go      |  6 ++----
 5 files changed, 47 insertions(+), 35 deletions(-)

diff --git a/cobra/cmd/add.go b/cobra/cmd/add.go
index 988568ea..9e30671c 100644
--- a/cobra/cmd/add.go
+++ b/cobra/cmd/add.go
@@ -51,14 +51,19 @@ Example: cobra add server -> resulting in a new cmd/server.go`,
 			er(err)
 		}
 		project := NewProjectFromPath(wd)
+
 		cmdName := validateCmdName(args[0])
-		createCmdFile(project, cmdName)
+		cmdPath := filepath.Join(project.CmdPath(), cmdName+".go")
+		createCmdFile(project.License(), cmdPath, cmdName)
+
+		fmt.Fprintln(cmd.OutOrStdout(), cmdName, "created at", cmdPath)
 	},
 }
 
 // validateCmdName returns source without any dashes and underscore.
 // If there will be dash or underscore, next letter will be uppered.
 // It supports only ASCII (1-byte character) strings.
+// https://github.com/spf13/cobra/issues/269
 func validateCmdName(source string) string {
 	i := 0
 	l := len(source)
@@ -102,7 +107,7 @@ func validateCmdName(source string) string {
 	return output
 }
 
-func createCmdFile(project *Project, cmdName string) {
+func createCmdFile(license License, path, cmdName string) {
 	template := `{{comment .copyright}}
 {{comment .license}}
 
@@ -146,21 +151,17 @@ func init() {
 
 	data := make(map[string]interface{})
 	data["copyright"] = copyrightLine()
-	data["license"] = project.License().Header
+	data["license"] = license.Header
 	data["viper"] = viper.GetBool("useViper")
 	data["parentName"] = parentName
 	data["cmdName"] = cmdName
 
-	filePath := filepath.Join(project.CmdPath(), cmdName+".go")
-
 	cmdScript, err := executeTemplate(template, data)
 	if err != nil {
 		er(err)
 	}
-	err = writeStringToFile(filePath, cmdScript)
+	err = writeStringToFile(path, cmdScript)
 	if err != nil {
 		er(err)
 	}
-
-	fmt.Println(cmdName, "created at", filePath)
 }
diff --git a/cobra/cmd/helpers.go b/cobra/cmd/helpers.go
index d5ee9062..fc9dd85d 100644
--- a/cobra/cmd/helpers.go
+++ b/cobra/cmd/helpers.go
@@ -26,7 +26,7 @@ import (
 var projectPath string
 
 var cmdDirs = [...]string{"cmd", "cmds", "command", "commands"}
-var goPaths, srcPaths []string
+var srcPaths []string
 
 func init() {
 	// Initialize goPaths and srcPaths
@@ -35,7 +35,7 @@ func init() {
 		er("$GOPATH is not set")
 	}
 
-	goPaths = filepath.SplitList(envGoPath)
+	goPaths := filepath.SplitList(envGoPath)
 	srcPaths = make([]string, 0, len(goPaths))
 	for _, goPath := range goPaths {
 		srcPaths = append(srcPaths, filepath.Join(goPath, "src"))
diff --git a/cobra/cmd/init.go b/cobra/cmd/init.go
index 9a6f93d2..7812d9cb 100644
--- a/cobra/cmd/init.go
+++ b/cobra/cmd/init.go
@@ -48,16 +48,27 @@ Init will not use an existing directory with contents.`,
 			}
 			project = NewProjectFromPath(wd)
 		} else if len(args) == 1 {
-			project = NewProject(args[0])
+			arg := args[0]
+			if filepath.IsAbs(arg) {
+				project = NewProjectFromPath(arg)
+			} else {
+				project = NewProject(arg)
+			}
 		} else {
 			er("please enter the name")
 		}
 
-		initializePath(project)
+		initializeProject(project)
+
+		fmt.Fprintln(cmd.OutOrStdout(), `Your Cobra application is ready at
+`+project.AbsPath()+`.
+
+Give it a try by going there and running `+"`go run main.go`."+`
+Add commands to it by running `+"`cobra add [cmdname]`.")
 	},
 }
 
-func initializePath(project *Project) {
+func initializeProject(project *Project) {
 	if !exists(project.AbsPath()) { // If path doesn't yet exist, create it
 		err := os.MkdirAll(project.AbsPath(), os.ModePerm)
 		if err != nil {
@@ -216,9 +227,4 @@ func initConfig() {
 		er(err)
 	}
 
-	fmt.Println(`Your Cobra application is ready at
-` + project.AbsPath() + `.
-
-Give it a try by going there and running ` + "`go run main.go`." + `
-Add commands to it by running ` + "`cobra add [cmdname]`.")
 }
diff --git a/cobra/cmd/project.go b/cobra/cmd/project.go
index 2c885664..facd80a5 100644
--- a/cobra/cmd/project.go
+++ b/cobra/cmd/project.go
@@ -29,21 +29,22 @@ func NewProject(projectName string) *Project {
 	p.absPath = findPackage(projectName)
 
 	// 2. If there are no created project with this path, and user is in GOPATH,
-	// then use GOPATH/src+projectName.
+	// then use GOPATH/src/projectName.
 	if p.absPath == "" {
 		wd, err := os.Getwd()
 		if err != nil {
 			er(err)
 		}
-		for _, goPath := range goPaths {
+		for _, srcPath := range srcPaths {
+			goPath := filepath.Dir(srcPath)
 			if filepath.HasPrefix(wd, goPath) {
-				p.absPath = filepath.Join(goPath, "src", projectName)
+				p.absPath = filepath.Join(srcPath, projectName)
 				break
 			}
 		}
 	}
 
-	// 3. If user is not in GOPATH, then use (first GOPATH)+projectName.
+	// 3. If user is not in GOPATH, then use (first GOPATH)/src/projectName.
 	if p.absPath == "" {
 		p.absPath = filepath.Join(srcPaths[0], projectName)
 	}
@@ -130,25 +131,31 @@ func findCmdDir(absPath string) string {
 		return "cmd"
 	}
 
-	base := filepath.Base(absPath)
-	for _, cmdDir := range cmdDirs {
-		if base == cmdDir {
-			return cmdDir
-		}
+	if isCmdDir(absPath) {
+		return filepath.Base(absPath)
 	}
 
 	files, _ := filepath.Glob(filepath.Join(absPath, "c*"))
 	for _, file := range files {
-		for _, cmdDir := range cmdDirs {
-			if file == cmdDir {
-				return cmdDir
-			}
+		if isCmdDir(file) {
+			return file
 		}
 	}
 
 	return "cmd"
 }
 
+// isCmdDir checks if base of name is one of cmdDir.
+func isCmdDir(name string) bool {
+	name = filepath.Base(name)
+	for _, cmdDir := range cmdDirs {
+		if name == cmdDir {
+			return true
+		}
+	}
+	return false
+}
+
 // AbsPath returns absolute path of project.
 func (p Project) AbsPath() string {
 	return p.absPath
diff --git a/command_test.go b/command_test.go
index d8c5021e..91d1fb10 100644
--- a/command_test.go
+++ b/command_test.go
@@ -227,8 +227,7 @@ func TestFlagErrorFunc(t *testing.T) {
 
 // TestSortedFlags checks,
 // if cmd.LocalFlags() is unsorted when cmd.Flags().SortFlags set to false.
-//
-// Source: https://github.com/spf13/cobra/issues/404
+// https://github.com/spf13/cobra/issues/404
 func TestSortedFlags(t *testing.T) {
 	cmd := &Command{}
 	cmd.Flags().SortFlags = false
@@ -264,8 +263,7 @@ func isStringInStringSlice(s string, ss []string) bool {
 // TestHelpFlagInHelp checks,
 // if '--help' flag is shown in help for child (executing `parent help child`),
 // that has no other flags.
-//
-// Source: https://github.com/spf13/cobra/issues/302
+// https://github.com/spf13/cobra/issues/302
 func TestHelpFlagInHelp(t *testing.T) {
 	output := new(bytes.Buffer)
 	parent := &Command{Use: "parent", Long: "long", Run: func(*Command, []string) { return }}