Skip to content

Commit 830cb81

Browse files
authored
Support package resolution and filepaths (#187)
* Support package resolution and filepaths This change introduces the logic to resolve packages using gotool and build packages from filepaths. It assumes that the packages being scanned are located within the GOPATH. If the GOPATH environment variable is not set the GOPATH is derived as $HOME/go. Relates to #184 * Fix build error * Address unhandled error * Fix formatting error * Handle multiple paths on GOPATH
1 parent b643ac2 commit 830cb81

File tree

2 files changed

+86
-2
lines changed

2 files changed

+86
-2
lines changed

analyzer.go

+4
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,10 @@ func (gas *Analyzer) Process(packagePaths ...string) error {
108108
if err != nil {
109109
return err
110110
}
111+
if _, err := os.Stat(abspath); os.IsNotExist(err) {
112+
gas.logger.Printf("Skipping: %s. Path doesn't exist.", abspath)
113+
continue
114+
}
111115
gas.logger.Println("Searching directory:", abspath)
112116

113117
basePackage, err := build.Default.ImportDir(packagePath, build.ImportComment)

cmd/gas/main.go

+82-2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,10 @@ import (
1919
"fmt"
2020
"log"
2121
"os"
22+
"os/user"
23+
"path/filepath"
2224
"regexp"
25+
"runtime"
2326
"sort"
2427
"strings"
2528

@@ -171,6 +174,82 @@ func saveOutput(filename, format string, issues []*gas.Issue, metrics *gas.Metri
171174
return nil
172175
}
173176

177+
func getenv(key, userDefault string) string {
178+
if val := os.Getenv(key); val != "" {
179+
return val
180+
}
181+
return userDefault
182+
}
183+
184+
func gopath() []string {
185+
defaultGoPath := runtime.GOROOT()
186+
if u, err := user.Current(); err == nil {
187+
defaultGoPath = filepath.Join(u.HomeDir, "go")
188+
}
189+
path := getenv("GOPATH", defaultGoPath)
190+
paths := strings.Split(path, string(os.PathListSeparator))
191+
for idx, path := range paths {
192+
if abs, err := filepath.Abs(path); err == nil {
193+
paths[idx] = abs
194+
}
195+
}
196+
return paths
197+
}
198+
199+
func cleanPath(path string, gopaths []string) (string, error) {
200+
201+
cleanFailed := fmt.Errorf("%s is not within the $GOPATH and cannot be processed", path)
202+
nonRecursivePath := strings.TrimSuffix(path, "/...")
203+
// do not attempt to clean directs that are resolvable on gopath
204+
if _, err := os.Stat(nonRecursivePath); err != nil && os.IsNotExist(err) {
205+
log.Printf("directory %s doesn't exist, checking if is a package on $GOPATH", path)
206+
for _, basedir := range gopaths {
207+
dir := filepath.Join(basedir, "src", nonRecursivePath)
208+
if st, err := os.Stat(dir); err == nil && st.IsDir() {
209+
log.Printf("located %s in %s", path, dir)
210+
return path, nil
211+
}
212+
}
213+
return "", cleanFailed
214+
}
215+
216+
// ensure we resolve package directory correctly based on $GOPATH
217+
abspath, err := filepath.Abs(path)
218+
if err != nil {
219+
abspath = path
220+
}
221+
for _, base := range gopaths {
222+
projectRoot := filepath.FromSlash(fmt.Sprintf("%s/src/", base))
223+
if strings.HasPrefix(abspath, projectRoot) {
224+
return strings.TrimPrefix(abspath, projectRoot), nil
225+
}
226+
}
227+
return "", cleanFailed
228+
}
229+
230+
func cleanPaths(paths []string) []string {
231+
gopaths := gopath()
232+
var clean []string
233+
for _, path := range paths {
234+
cleaned, err := cleanPath(path, gopaths)
235+
if err != nil {
236+
log.Fatal(err)
237+
}
238+
clean = append(clean, cleaned)
239+
}
240+
return clean
241+
}
242+
243+
func resolvePackage(pkg string, searchPaths []string) string {
244+
for _, basedir := range searchPaths {
245+
dir := filepath.Join(basedir, "src", pkg)
246+
if st, err := os.Stat(dir); err == nil && st.IsDir() {
247+
return dir
248+
}
249+
}
250+
return pkg
251+
}
252+
174253
func main() {
175254

176255
// Setup usage description
@@ -218,13 +297,14 @@ func main() {
218297

219298
var packages []string
220299
// Iterate over packages on the import paths
221-
for _, pkg := range gotool.ImportPaths(flag.Args()) {
300+
gopaths := gopath()
301+
for _, pkg := range gotool.ImportPaths(cleanPaths(flag.Args())) {
222302

223303
// Skip vendor directory
224304
if vendor.MatchString(pkg) {
225305
continue
226306
}
227-
packages = append(packages, pkg)
307+
packages = append(packages, resolvePackage(pkg, gopaths))
228308
}
229309

230310
if err := analyzer.Process(packages...); err != nil {

0 commit comments

Comments
 (0)