cmd/go/internal/modload: do not prune the module root when walking directories

When walking filesystem paths to locate packages, we normally prune
out subdirectories with names beginning with ".", "_", or equal to
"testdata". However, we should not prune out such a directory if it is
at or above the module root, since its name is not part of the package
path.

Fixes #28481
Updates #27852

Change-Id: Ice82b1f908afaab50f5592f6c38ca6a0fe911edf
Reviewed-on: https://go-review.googlesource.com/c/go/+/196297
Run-TryBot: Bryan C. Mills <bcmills@google.com>
Reviewed-by: Daniel Martí <mvdan@mvdan.cc>
Reviewed-by: Jay Conrod <jayconrod@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
Bryan C. Mills 2019-09-18 16:59:17 -04:00
parent e13dd94c56
commit a11644a265
2 changed files with 58 additions and 9 deletions

View File

@ -48,17 +48,21 @@ func matchPackages(pattern string, tags map[string]bool, useStd bool, modules []
return nil
}
want := true
elem := ""
// Don't use GOROOT/src but do walk down into it.
if path == root && importPathRoot == "" {
if path == root {
if importPathRoot == "" {
return nil
}
want := true
// Avoid .foo, _foo, and testdata directory trees.
_, elem := filepath.Split(path)
} else {
// Avoid .foo, _foo, and testdata subdirectory trees.
_, elem = filepath.Split(path)
if strings.HasPrefix(elem, ".") || strings.HasPrefix(elem, "_") || elem == "testdata" {
want = false
}
}
name := importPathRoot + filepath.ToSlash(path[len(root):])
if importPathRoot == "" {

View File

@ -0,0 +1,45 @@
# Regression test for golang.org/issue/28481:
# 'mod tidy' removed dependencies if the module root was
# within a directory named 'testdata' or '_foo'.
env GO111MODULE=on
# A module should be allowed in a directory named testdata.
cd $WORK/testdata
go mod init testdata.tld/foo
# Building a package within that module should resolve its dependencies.
go build
grep 'rsc.io/quote' go.mod
# Tidying the module should preserve those dependencies.
go mod tidy
grep 'rsc.io/quote' go.mod
[short] stop
# Vendoring the module's dependencies should work too.
go mod vendor
exists vendor/rsc.io/quote
# The same should work in directories with names starting with underscores.
cd $WORK/_ignored
go mod init testdata.tld/foo
go build
grep 'rsc.io/quote' go.mod
go mod tidy
grep 'rsc.io/quote' go.mod
go mod vendor
exists vendor/rsc.io/quote
-- $WORK/testdata/main.go --
package foo
import _ "rsc.io/quote"
-- $WORK/_ignored/main.go --
package foo
import _ "rsc.io/quote"