summaryrefslogtreecommitdiff
path: root/src/cmd/go/pkg.go
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2015-12-10 22:34:17 -0500
committerRuss Cox <rsc@golang.org>2015-12-16 20:22:18 +0000
commit0c428a56176353d52170f318e998f342b08dacd2 (patch)
tree0f0aad65368b97a5a1f07bc8637c9f99a331689e /src/cmd/go/pkg.go
parentae9529a261966d98d7eba59de009e4553a86c94e (diff)
downloadgo-git-0c428a56176353d52170f318e998f342b08dacd2.tar.gz
go/build: support vendor directories in Import
This fix, plus a one-line change to golang.org/x/tools/go/loader, is sufficient to let that loader package process source code using vendored packages. For example, GOPATH="" ssadump net/http # uses vendored http2 used to fail, not able to find net/http's import of the vendored copy of golang.org/x/net/http2/hpack. This CL plus the fix to loader (CL 17727) suffices to get ssadump working, as well as - I expect - most other source code processing built on golang.org/x/tools/go/loader. Fixes #12278. Change-Id: I83715e757419171159f67d49bb453636afdd91f0 Reviewed-on: https://go-review.googlesource.com/17726 Reviewed-by: Ian Lance Taylor <iant@golang.org>
Diffstat (limited to 'src/cmd/go/pkg.go')
-rw-r--r--src/cmd/go/pkg.go56
1 files changed, 20 insertions, 36 deletions
diff --git a/src/cmd/go/pkg.go b/src/cmd/go/pkg.go
index 6c3a09a2d2..2f8799a608 100644
--- a/src/cmd/go/pkg.go
+++ b/src/cmd/go/pkg.go
@@ -118,7 +118,7 @@ func (p *Package) vendored(imports []string) []string {
seen := make(map[string]bool)
var all []string
for _, path := range imports {
- path, _ = vendoredImportPath(p, path)
+ path = vendoredImportPath(p, path)
if !seen[path] {
seen[path] = true
all = append(all, path)
@@ -256,6 +256,7 @@ func reloadPackage(arg string, stk *importStack) *Package {
// The variable is obnoxiously long so that years from now when people find it in
// their profiles and wonder what it does, there is some chance that a web search
// might answer the question.
+// There is a copy of this variable in src/go/build/build.go. Delete that one when this one goes away.
var go15VendorExperiment = os.Getenv("GO15VENDOREXPERIMENT") != "0"
// dirToImportPath returns the pseudo-import path we use for a package
@@ -312,11 +313,14 @@ func loadImport(path, srcDir string, parent *Package, stk *importStack, importPo
importPath := path
origPath := path
isLocal := build.IsLocalImport(path)
- var vendorSearch []string
if isLocal {
importPath = dirToImportPath(filepath.Join(srcDir, path))
} else if mode&useVendor != 0 {
- path, vendorSearch = vendoredImportPath(parent, path)
+ // We do our own vendor resolution, because we want to
+ // find out the key to use in packageCache without the
+ // overhead of repeated calls to buildContext.Import.
+ // The code is also needed in a few other places anyway.
+ path = vendoredImportPath(parent, path)
importPath = path
}
@@ -343,29 +347,14 @@ func loadImport(path, srcDir string, parent *Package, stk *importStack, importPo
//
// TODO: After Go 1, decide when to pass build.AllowBinary here.
// See issue 3268 for mistakes to avoid.
- bp, err := buildContext.Import(path, srcDir, build.ImportComment)
-
- // If we got an error from go/build about package not found,
- // it contains the directories from $GOROOT and $GOPATH that
- // were searched. Add to that message the vendor directories
- // that were searched.
- if err != nil && len(vendorSearch) > 0 {
- // NOTE(rsc): The direct text manipulation here is fairly awful,
- // but it avoids defining new go/build API (an exported error type)
- // late in the Go 1.5 release cycle. If this turns out to be a more general
- // problem we could define a real error type when the decision can be
- // considered more carefully.
- text := err.Error()
- if strings.Contains(text, "cannot find package \"") && strings.Contains(text, "\" in any of:\n\t") {
- old := strings.SplitAfter(text, "\n")
- lines := []string{old[0]}
- for _, dir := range vendorSearch {
- lines = append(lines, "\t"+dir+" (vendor tree)\n")
- }
- lines = append(lines, old[1:]...)
- err = errors.New(strings.Join(lines, ""))
- }
- }
+ buildMode := build.ImportComment
+ if go15VendorExperiment && mode&useVendor != 0 && path == origPath {
+ // We've already searched the vendor directories and didn't find anything.
+ // Let Import search them again so that, if the package is not found anywhere,
+ // the error includes the vendor directories in the list of places considered.
+ buildMode |= build.AllowVendor
+ }
+ bp, err := buildContext.Import(path, srcDir, buildMode)
bp.ImportPath = importPath
if gobin != "" {
bp.BinDir = gobin
@@ -411,12 +400,9 @@ func isDir(path string) bool {
// If parent is x/y/z, then path might expand to x/y/z/vendor/path, x/y/vendor/path,
// x/vendor/path, vendor/path, or else stay path if none of those exist.
// vendoredImportPath returns the expanded path or, if no expansion is found, the original.
-// If no expansion is found, vendoredImportPath also returns a list of vendor directories
-// it searched along the way, to help prepare a useful error message should path turn
-// out not to exist.
-func vendoredImportPath(parent *Package, path string) (found string, searched []string) {
+func vendoredImportPath(parent *Package, path string) (found string) {
if parent == nil || parent.Root == "" || !go15VendorExperiment {
- return path, nil
+ return path
}
dir := filepath.Clean(parent.Dir)
root := filepath.Join(parent.Root, "src")
@@ -451,14 +437,12 @@ func vendoredImportPath(parent *Package, path string) (found string, searched []
// and found c:\gopath\src\vendor\path.
// We chopped \foo\bar (length 8) but the import path is "foo/bar" (length 7).
// Use "vendor/path" without any prefix.
- return vpath, nil
+ return vpath
}
- return parent.ImportPath[:len(parent.ImportPath)-chopped] + "/" + vpath, nil
+ return parent.ImportPath[:len(parent.ImportPath)-chopped] + "/" + vpath
}
- // Note the existence of a vendor directory in case path is not found anywhere.
- searched = append(searched, targ)
}
- return path, searched
+ return path
}
// reusePackage reuses package p to satisfy the import at the top