10 // Project contains name, license and paths to projects.
19 // NewProject returns Project with specified project name.
20 // If projectName is blank string, it returns nil.
21 func NewProject(projectName string) *Project {
22 if projectName == "" {
29 // 1. Find already created protect.
30 p.absPath = findPackage(projectName)
32 // 2. If there are no created project with this path, and user is in GOPATH,
33 // then use GOPATH/src/projectName.
39 for _, srcPath := range srcPaths {
40 goPath := filepath.Dir(srcPath)
41 if filepathHasPrefix(wd, goPath) {
42 p.absPath = filepath.Join(srcPath, projectName)
48 // 3. If user is not in GOPATH, then use (first GOPATH)/src/projectName.
50 p.absPath = filepath.Join(srcPaths[0], projectName)
56 // findPackage returns full path to existing go package in GOPATHs.
57 // findPackage returns "", if it can't find path.
58 // If packageName is "", findPackage returns "".
59 func findPackage(packageName string) string {
60 if packageName == "" {
64 for _, srcPath := range srcPaths {
65 packagePath := filepath.Join(srcPath, packageName)
66 if exists(packagePath) {
74 // NewProjectFromPath returns Project with specified absolute path to
76 // If absPath is blank string or if absPath is not actually absolute,
78 func NewProjectFromPath(absPath string) *Project {
79 if absPath == "" || !filepath.IsAbs(absPath) {
85 p.absPath = strings.TrimSuffix(p.absPath, findCmdDir(p.absPath))
86 p.name = filepath.ToSlash(trimSrcPath(p.absPath, p.SrcPath()))
90 // trimSrcPath trims at the beginning of absPath the srcPath.
91 func trimSrcPath(absPath, srcPath string) string {
92 relPath, err := filepath.Rel(srcPath, absPath)
94 er("Cobra supports project only within $GOPATH: " + err.Error())
99 // License returns the License object of project.
100 func (p *Project) License() License {
101 if p.license.Text == "" && p.license.Name != "None" {
102 p.license = getLicense()
108 // Name returns the name of project, e.g. "github.com/spf13/cobra"
109 func (p Project) Name() string {
113 // CmdPath returns absolute path to directory, where all commands are located.
115 // CmdPath returns blank string, only if p.AbsPath() is a blank string.
116 func (p *Project) CmdPath() string {
121 p.cmdPath = filepath.Join(p.absPath, findCmdDir(p.absPath))
126 // findCmdDir checks if base of absPath is cmd dir and returns it or
127 // looks for existing cmd dir in absPath.
128 // If the cmd dir doesn't exist, empty, or cannot be found,
130 func findCmdDir(absPath string) string {
131 if !exists(absPath) || isEmpty(absPath) {
135 if isCmdDir(absPath) {
136 return filepath.Base(absPath)
139 files, _ := filepath.Glob(filepath.Join(absPath, "c*"))
140 for _, file := range files {
142 return filepath.Base(file)
149 // isCmdDir checks if base of name is one of cmdDir.
150 func isCmdDir(name string) bool {
151 name = filepath.Base(name)
152 for _, cmdDir := range cmdDirs {
160 // AbsPath returns absolute path of project.
161 func (p Project) AbsPath() string {
165 // SrcPath returns absolute path to $GOPATH/src where project is located.
166 func (p *Project) SrcPath() string {
171 p.srcPath = srcPaths[0]
175 for _, srcPath := range srcPaths {
176 if filepathHasPrefix(p.absPath, srcPath) {
185 func filepathHasPrefix(path string, prefix string) bool {
186 if len(path) <= len(prefix) {
189 if runtime.GOOS == "windows" {
190 // Paths in windows are case-insensitive.
191 return strings.EqualFold(path[0:len(prefix)], prefix)
193 return path[0:len(prefix)] == prefix