cmd/go/internal/vgo: ignore appengine imports
As an unfortunate special case, just ignore import of appengine or appengine/*
when scanning a source tree to find modules that need to be imported.
A more aggressive option would be to ignore all paths that don't start
with an element with a dot (that is, don't start with a plausible domain name),
but I don't want to require that all modules have a dot at the start of the name.
The real problem here is that appengine was introduced so long ago that it
predates "go get" and did not use URL-like paths, and some code exists that
is still using those old imports. I am unaware of any other special cases like
that. If they arise, we can add them too, or we can revisit whether there is a
more general fix. For now this should suffice.
Fixes golang/go#25881.
Change-Id: I38cdbc1cd83a2f55d87f598bd0cbf1f6bcade88a
Reviewed-on: https://go-review.googlesource.com/118757
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ross Light <light@google.com>
diff --git a/vendor/cmd/go/internal/vgo/get.go b/vendor/cmd/go/internal/vgo/get.go
index 9fd8497..b61f7bc 100644
--- a/vendor/cmd/go/internal/vgo/get.go
+++ b/vendor/cmd/go/internal/vgo/get.go
@@ -131,7 +131,7 @@
if err != nil {
return err // TODO
}
- imports, testImports, err := imports.ScanDir(dir, v.Tags)
+ imports, testImports, err := scanDir(dir, v.Tags)
for _, path := range imports {
xxx
}
diff --git a/vendor/cmd/go/internal/vgo/load.go b/vendor/cmd/go/internal/vgo/load.go
index 5be03b4..fee3ff0 100644
--- a/vendor/cmd/go/internal/vgo/load.go
+++ b/vendor/cmd/go/internal/vgo/load.go
@@ -220,7 +220,7 @@
ld.pkgdir[realPath] = dir
- imports, testImports, err := imports.ScanDir(dir, ld.tags)
+ imports, testImports, err := scanDir(dir, ld.tags)
if err != nil {
base.Errorf("vgo: %s [%s]: %v", ld.stackText(), dir, err)
return
@@ -580,3 +580,31 @@
}
return module.Version{Path: m.Path, Version: "none"}, nil
}
+
+// scanDir is like imports.ScanDir but elides known magic imports from the list,
+// so that vgo does not go looking for packages that don't really exist.
+//
+// The only known magic imports are appengine and appengine/*.
+// These are so old that they predate "go get" and did not use URL-like paths.
+// Most code today now uses google.golang.org/appengine instead,
+// but not all code has been so updated. When we mostly ignore build tags
+// during "vgo vendor", we look into "// +build appengine" files and
+// may see these legacy imports. We drop them so that the module
+// search does not look for modules to try to satisfy them.
+func scanDir(path string, tags map[string]bool) (imports_, testImports []string, err error) {
+ imports_, testImports, err = imports.ScanDir(path, tags)
+
+ filter := func(x []string) []string {
+ w := 0
+ for _, pkg := range x {
+ if pkg != "appengine" && !strings.HasPrefix(pkg, "appengine/") &&
+ pkg != "appengine_internal" && !strings.HasPrefix(pkg, "appengine_internal/") {
+ x[w] = pkg
+ w++
+ }
+ }
+ return x
+ }
+
+ return filter(imports_), filter(testImports), err
+}
diff --git a/vendor/cmd/go/internal/vgo/search.go b/vendor/cmd/go/internal/vgo/search.go
index c3f7ab1..fb2bac4 100644
--- a/vendor/cmd/go/internal/vgo/search.go
+++ b/vendor/cmd/go/internal/vgo/search.go
@@ -145,7 +145,7 @@
if !have[name] {
have[name] = true
if match(name) {
- if _, _, err := imports.ScanDir(path, imports.Tags()); err != imports.ErrNoGo {
+ if _, _, err := scanDir(path, imports.Tags()); err != imports.ErrNoGo {
pkgs = append(pkgs, name)
}
}
diff --git a/vendor/cmd/go/testdata/vendormod/appengine.go b/vendor/cmd/go/testdata/vendormod/appengine.go
new file mode 100644
index 0000000..da4d04c
--- /dev/null
+++ b/vendor/cmd/go/testdata/vendormod/appengine.go
@@ -0,0 +1,6 @@
+// +build appengine
+
+package m
+
+import _ "appengine"
+import _ "appengine/datastore"
diff --git a/vendor/cmd/go/vgo_test.go b/vendor/cmd/go/vgo_test.go
index 34a8c71..54ad36f 100644
--- a/vendor/cmd/go/vgo_test.go
+++ b/vendor/cmd/go/vgo_test.go
@@ -217,7 +217,7 @@
tg.grepStderr("unknown module x/y.z: not a domain name", "expected domain error")
tg.runFail("-vgo", "build")
- tg.grepStderr("unknown module appengine: not a domain name", "expected domain error")
+ tg.grepStderrNot("unknown module appengine: not a domain name", "expected nothing about appengine")
tg.grepStderr("tcp.*nonexistent.rsc.io", "expected error for nonexistent.rsc.io")
}