Added a function to get a correct build context when $GOROOT is not set
diff --git a/cmd/guess_deps.go b/cmd/guess_deps.go
index 97bf7db..f637c7c 100644
--- a/cmd/guess_deps.go
+++ b/cmd/guess_deps.go
@@ -2,7 +2,6 @@
import (
"github.com/Masterminds/cookoo"
- "go/build"
"os"
"strings"
)
@@ -12,9 +11,13 @@
// Params
// - dirname (string): Directory to use as the base. Default: "."
func GuessDeps(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) {
+ buildContext, err := GetBuildContext()
+ if err != nil {
+ return nil, err
+ }
base := p.Get("dirname", ".").(string)
deps := make(map[string]bool)
- err := findDeps(deps, base, "")
+ err = findDeps(buildContext, deps, base, "")
deps = compactDeps(deps)
delete(deps, base)
if err != nil {
@@ -24,7 +27,7 @@
config := new(Config)
// Get the name of the top level package
- config.Name = guessPackageName(base)
+ config.Name = guessPackageName(buildContext, base)
config.Imports = make([]*Dependency, len(deps))
i := 0
for pa := range deps {
@@ -45,13 +48,13 @@
// As of Go 1.5 the go command knows about the vendor directory but the go/build
// package does not. It only knows about the GOPATH and GOROOT. In order to look
// for packages in the vendor/ directory we need to fake it for now.
-func findDeps(soFar map[string]bool, name, vpath string) error {
+func findDeps(b *BuildCtxt, soFar map[string]bool, name, vpath string) error {
cwd, err := os.Getwd()
if err != nil {
return err
}
- pkg, err := build.Import(name, cwd, 0)
+ pkg, err := b.Import(name, cwd, 0)
if err != nil {
return err
}
@@ -79,8 +82,8 @@
// Try looking for a dependency as a vendor. If it's not there then
// fall back to a way where it will be found in the GOPATH or GOROOT.
- if err := findDeps(soFar, vpath+"/vendor/"+imp, vpath); err != nil {
- if err := findDeps(soFar, imp, vpath); err != nil {
+ if err := findDeps(b, soFar, vpath+"/vendor/"+imp, vpath); err != nil {
+ if err := findDeps(b, soFar, imp, vpath); err != nil {
return err
}
}
@@ -106,13 +109,13 @@
// Attempt to guess at the package name at the top level. When unable to detect
// a name goes to default of "main".
-func guessPackageName(base string) string {
+func guessPackageName(b *BuildCtxt, base string) string {
cwd, err := os.Getwd()
if err != nil {
return "main"
}
- pkg, err := build.Import(base, cwd, 0)
+ pkg, err := b.Import(base, cwd, 0)
if err != nil {
return "main"
}
diff --git a/cmd/tree.go b/cmd/tree.go
index 885f34a..98435fd 100644
--- a/cmd/tree.go
+++ b/cmd/tree.go
@@ -3,7 +3,6 @@
import (
"errors"
"fmt"
- "go/build"
"os"
"path/filepath"
"sort"
@@ -16,9 +15,13 @@
// Tree prints a tree representing dependencies.
func Tree(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) {
+ buildContext, err := GetBuildContext()
+ if err != nil {
+ return nil, err
+ }
showcore := p.Get("showcore", false).(bool)
basedir := p.Get("dir", ".").(string)
- myName := guessPackageName(basedir)
+ myName := guessPackageName(buildContext, basedir)
if basedir == "." {
var err error
@@ -30,7 +33,7 @@
}
fmt.Println(myName)
- displayTree(basedir, myName, 1, showcore)
+ displayTree(buildContext, basedir, myName, 1, showcore)
return nil, nil
}
@@ -41,19 +44,22 @@
// Returns:
//
func ListDeps(c cookoo.Context, p *cookoo.Params) (interface{}, cookoo.Interrupt) {
+ buildContext, err := GetBuildContext()
+ if err != nil {
+ return nil, err
+ }
basedir := p.Get("dir", ".").(string)
- myName := guessPackageName(basedir)
+ myName := guessPackageName(buildContext, basedir)
- var err error
basedir, err = filepath.Abs(basedir)
if err != nil {
return nil, err
}
direct := map[string]bool{}
- d := walkDeps(basedir, myName)
+ d := walkDeps(buildContext, basedir, myName)
for _, i := range d {
- listDeps(direct, i, basedir)
+ listDeps(buildContext, direct, i, basedir)
}
sortable := make([]string, len(direct))
@@ -76,8 +82,8 @@
return nil, nil
}
-func listDeps(info map[string]bool, name, path string) {
- found := findPkg(name, path)
+func listDeps(b *BuildCtxt, info map[string]bool, name, path string) {
+ found := findPkg(b, name, path)
switch found.PType {
case ptypeUnknown:
info[name] = false
@@ -86,16 +92,16 @@
break
default:
info[name] = true
- for _, i := range walkDeps(found.Path, found.Name) {
- listDeps(info, i, found.Path)
+ for _, i := range walkDeps(b, found.Path, found.Name) {
+ listDeps(b, info, i, found.Path)
}
}
}
-func displayTree(basedir, myName string, level int, core bool) {
- deps := walkDeps(basedir, myName)
+func displayTree(b *BuildCtxt, basedir, myName string, level int, core bool) {
+ deps := walkDeps(b, basedir, myName)
for _, name := range deps {
- found := findPkg(name, basedir)
+ found := findPkg(b, name, basedir)
if found.PType == ptypeUnknown {
msg := "glide get " + found.Name
fmt.Printf("\t%s\t(%s)\n", found.Name, msg)
@@ -106,7 +112,7 @@
}
fmt.Print(strings.Repeat("\t", level))
fmt.Printf("%s (%s)\n", found.Name, found.Path)
- displayTree(found.Path, found.Name, level+1, core)
+ displayTree(b, found.Path, found.Name, level+1, core)
}
}
@@ -125,7 +131,7 @@
PType ptype
}
-func findPkg(name, cwd string) *pinfo {
+func findPkg(b *BuildCtxt, name, cwd string) *pinfo {
var fi os.FileInfo
var err error
var p string
@@ -144,7 +150,7 @@
}
}
// Check $GOPATH
- for _, r := range strings.Split(os.Getenv("GOPATH"), ":") {
+ for _, r := range strings.Split(b.GOPATH, ":") {
p = filepath.Join(r, "src", name)
if fi, err = os.Stat(p); err == nil && (fi.IsDir() || isLink(fi)) {
info.Path = p
@@ -154,7 +160,7 @@
}
// Check $GOROOT
- for _, r := range strings.Split(os.Getenv("GOROOT"), ":") {
+ for _, r := range strings.Split(b.GOROOT, ":") {
p = filepath.Join(r, "src", name)
if fi, err = os.Stat(p); err == nil && (fi.IsDir() || isLink(fi)) {
info.Path = p
@@ -169,7 +175,7 @@
return fi.Mode()&os.ModeSymlink == os.ModeSymlink
}
-func walkDeps(base, myName string) []string {
+func walkDeps(b *BuildCtxt, base, myName string) []string {
externalDeps := []string{}
filepath.Walk(base, func(path string, fi os.FileInfo, err error) error {
if excludeSubtree(path, fi) {
@@ -178,7 +184,8 @@
}
return nil
}
- pkg, err := build.ImportDir(path, 0)
+
+ pkg, err := b.ImportDir(path, 0)
if err != nil {
return err
}
diff --git a/cmd/util.go b/cmd/util.go
index b445f2d..20960fc 100644
--- a/cmd/util.go
+++ b/cmd/util.go
@@ -2,11 +2,13 @@
import (
"fmt"
+ "go/build"
"io"
"os"
"os/exec"
"path"
"path/filepath"
+ "strings"
"github.com/Masterminds/cookoo"
)
@@ -122,6 +124,27 @@
return ps
}
+// Convenience wrapper for not having to import go/build anywhere else
+type BuildCtxt struct {
+ build.Context
+}
+
+// GetBuildContext returns a build context from go/build. When the $GOROOT
+// variable is not set in the users environment it sets the context's root
+// path to the path returned by 'go env GOROOT'.
+func GetBuildContext() (*BuildCtxt, error) {
+ buildContext := &BuildCtxt{build.Default}
+ if goRoot := os.Getenv("GOROOT"); len(goRoot) == 0 {
+ out, err := exec.Command("go", "env", "GOROOT").Output()
+ if goRoot = strings.TrimSpace(string(out)); len(goRoot) == 0 || err != nil {
+ return nil, fmt.Errorf("Please set the $GOROOT environment " +
+ "variable to use this command\n")
+ }
+ buildContext.GOROOT = goRoot
+ }
+ return buildContext, nil
+}
+
func fileExist(name string) (bool, error) {
_, err := os.Stat(name)
if err == nil {