OSDN Git Service

new repo
[bytom/vapor.git] / vendor / github.com / spf13 / cobra / cobra / cmd / project.go
1 package cmd
2
3 import (
4         "os"
5         "path/filepath"
6         "runtime"
7         "strings"
8 )
9
10 // Project contains name, license and paths to projects.
11 type Project struct {
12         absPath string
13         cmdPath string
14         srcPath string
15         license License
16         name    string
17 }
18
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 == "" {
23                 return nil
24         }
25
26         p := new(Project)
27         p.name = projectName
28
29         // 1. Find already created protect.
30         p.absPath = findPackage(projectName)
31
32         // 2. If there are no created project with this path, and user is in GOPATH,
33         // then use GOPATH/src/projectName.
34         if p.absPath == "" {
35                 wd, err := os.Getwd()
36                 if err != nil {
37                         er(err)
38                 }
39                 for _, srcPath := range srcPaths {
40                         goPath := filepath.Dir(srcPath)
41                         if filepathHasPrefix(wd, goPath) {
42                                 p.absPath = filepath.Join(srcPath, projectName)
43                                 break
44                         }
45                 }
46         }
47
48         // 3. If user is not in GOPATH, then use (first GOPATH)/src/projectName.
49         if p.absPath == "" {
50                 p.absPath = filepath.Join(srcPaths[0], projectName)
51         }
52
53         return p
54 }
55
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 == "" {
61                 return ""
62         }
63
64         for _, srcPath := range srcPaths {
65                 packagePath := filepath.Join(srcPath, packageName)
66                 if exists(packagePath) {
67                         return packagePath
68                 }
69         }
70
71         return ""
72 }
73
74 // NewProjectFromPath returns Project with specified absolute path to
75 // package.
76 // If absPath is blank string or if absPath is not actually absolute,
77 // it returns nil.
78 func NewProjectFromPath(absPath string) *Project {
79         if absPath == "" || !filepath.IsAbs(absPath) {
80                 return nil
81         }
82
83         p := new(Project)
84         p.absPath = absPath
85         p.absPath = strings.TrimSuffix(p.absPath, findCmdDir(p.absPath))
86         p.name = filepath.ToSlash(trimSrcPath(p.absPath, p.SrcPath()))
87         return p
88 }
89
90 // trimSrcPath trims at the beginning of absPath the srcPath.
91 func trimSrcPath(absPath, srcPath string) string {
92         relPath, err := filepath.Rel(srcPath, absPath)
93         if err != nil {
94                 er("Cobra supports project only within $GOPATH: " + err.Error())
95         }
96         return relPath
97 }
98
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()
103         }
104
105         return p.license
106 }
107
108 // Name returns the name of project, e.g. "github.com/spf13/cobra"
109 func (p Project) Name() string {
110         return p.name
111 }
112
113 // CmdPath returns absolute path to directory, where all commands are located.
114 //
115 // CmdPath returns blank string, only if p.AbsPath() is a blank string.
116 func (p *Project) CmdPath() string {
117         if p.absPath == "" {
118                 return ""
119         }
120         if p.cmdPath == "" {
121                 p.cmdPath = filepath.Join(p.absPath, findCmdDir(p.absPath))
122         }
123         return p.cmdPath
124 }
125
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,
129 // it returns "cmd".
130 func findCmdDir(absPath string) string {
131         if !exists(absPath) || isEmpty(absPath) {
132                 return "cmd"
133         }
134
135         if isCmdDir(absPath) {
136                 return filepath.Base(absPath)
137         }
138
139         files, _ := filepath.Glob(filepath.Join(absPath, "c*"))
140         for _, file := range files {
141                 if isCmdDir(file) {
142                         return filepath.Base(file)
143                 }
144         }
145
146         return "cmd"
147 }
148
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 {
153                 if name == cmdDir {
154                         return true
155                 }
156         }
157         return false
158 }
159
160 // AbsPath returns absolute path of project.
161 func (p Project) AbsPath() string {
162         return p.absPath
163 }
164
165 // SrcPath returns absolute path to $GOPATH/src where project is located.
166 func (p *Project) SrcPath() string {
167         if p.srcPath != "" {
168                 return p.srcPath
169         }
170         if p.absPath == "" {
171                 p.srcPath = srcPaths[0]
172                 return p.srcPath
173         }
174
175         for _, srcPath := range srcPaths {
176                 if filepathHasPrefix(p.absPath, srcPath) {
177                         p.srcPath = srcPath
178                         break
179                 }
180         }
181
182         return p.srcPath
183 }
184
185 func filepathHasPrefix(path string, prefix string) bool {
186         if len(path) <= len(prefix) {
187                 return false
188         }
189         if runtime.GOOS == "windows" {
190                 // Paths in windows are case-insensitive.
191                 return strings.EqualFold(path[0:len(prefix)], prefix)
192         }
193         return path[0:len(prefix)] == prefix
194
195 }