Commit 3fb1e0bd authored by Russ Cox's avatar Russ Cox

cmd/go: fix go get -t -u path/... containing vendor directories

A lot of things had to line up to make this break,
but the caching of download results interacted badly
with vendor directories, "go get -t -u", and wildcard
expansion.

Fixes #18219.

Change-Id: I2676498d2f714eaeb69f399e9ed527640c12e60d
Reviewed-on: https://go-review.googlesource.com/34201
Run-TryBot: Russ Cox <rsc@golang.org>
Reviewed-by: 's avatarIan Lance Taylor <iant@golang.org>
parent ec80737b
...@@ -205,6 +205,10 @@ var downloadRootCache = map[string]bool{} ...@@ -205,6 +205,10 @@ var downloadRootCache = map[string]bool{}
// download runs the download half of the get command // download runs the download half of the get command
// for the package named by the argument. // for the package named by the argument.
func download(arg string, parent *Package, stk *importStack, mode int) { func download(arg string, parent *Package, stk *importStack, mode int) {
if mode&useVendor != 0 {
// Caller is responsible for expanding vendor paths.
panic("internal error: download mode has useVendor set")
}
load := func(path string, mode int) *Package { load := func(path string, mode int) *Package {
if parent == nil { if parent == nil {
return loadPackage(path, stk) return loadPackage(path, stk)
...@@ -315,32 +319,42 @@ func download(arg string, parent *Package, stk *importStack, mode int) { ...@@ -315,32 +319,42 @@ func download(arg string, parent *Package, stk *importStack, mode int) {
} }
// Process dependencies, now that we know what they are. // Process dependencies, now that we know what they are.
for _, path := range p.Imports { imports := p.Imports
if mode&getTestDeps != 0 {
// Process test dependencies when -t is specified.
// (But don't get test dependencies for test dependencies:
// we always pass mode 0 to the recursive calls below.)
imports = stringList(imports, p.TestImports, p.XTestImports)
}
for i, path := range imports {
if path == "C" { if path == "C" {
continue continue
} }
// Don't get test dependencies recursively. // Fail fast on import naming full vendor path.
// Imports is already vendor-expanded. // Otherwise expand path as needed for test imports.
download(path, p, stk, 0) // Note that p.Imports can have additional entries beyond p.build.Imports.
} orig := path
if mode&getTestDeps != 0 { if i < len(p.build.Imports) {
// Process test dependencies when -t is specified. orig = p.build.Imports[i]
// (Don't get test dependencies for test dependencies.)
// We pass useVendor here because p.load does not
// vendor-expand TestImports and XTestImports.
// The call to loadImport inside download needs to do that.
for _, path := range p.TestImports {
if path == "C" {
continue
}
download(path, p, stk, useVendor)
} }
for _, path := range p.XTestImports { if j, ok := findVendor(orig); ok {
if path == "C" { stk.push(path)
continue err := &PackageError{
ImportStack: stk.copy(),
Err: "must be imported as " + path[j+len("vendor/"):],
} }
download(path, p, stk, useVendor) stk.pop()
errorf("%s", err)
continue
}
// If this is a test import, apply vendor lookup now.
// We cannot pass useVendor to download, because
// download does caching based on the value of path,
// so it must be the fully qualified path already.
if i >= len(p.Imports) {
path = vendoredImportPath(p, path)
} }
download(path, p, stk, 0)
} }
if isWildcard { if isWildcard {
......
...@@ -178,7 +178,9 @@ func (p *Package) copyBuild(pp *build.Package) { ...@@ -178,7 +178,9 @@ func (p *Package) copyBuild(pp *build.Package) {
p.CgoCXXFLAGS = pp.CgoCXXFLAGS p.CgoCXXFLAGS = pp.CgoCXXFLAGS
p.CgoLDFLAGS = pp.CgoLDFLAGS p.CgoLDFLAGS = pp.CgoLDFLAGS
p.CgoPkgConfig = pp.CgoPkgConfig p.CgoPkgConfig = pp.CgoPkgConfig
p.Imports = pp.Imports // We modify p.Imports in place, so make copy now.
p.Imports = make([]string, len(pp.Imports))
copy(p.Imports, pp.Imports)
p.TestGoFiles = pp.TestGoFiles p.TestGoFiles = pp.TestGoFiles
p.TestImports = pp.TestImports p.TestImports = pp.TestImports
p.XTestGoFiles = pp.XTestGoFiles p.XTestGoFiles = pp.XTestGoFiles
......
...@@ -188,6 +188,42 @@ func TestVendorGetUpdate(t *testing.T) { ...@@ -188,6 +188,42 @@ func TestVendorGetUpdate(t *testing.T) {
tg.run("get", "-u", "github.com/rsc/go-get-issue-11864") tg.run("get", "-u", "github.com/rsc/go-get-issue-11864")
} }
func TestVendorGetU(t *testing.T) {
testenv.MustHaveExternalNetwork(t)
tg := testgo(t)
defer tg.cleanup()
tg.makeTempdir()
tg.setenv("GOPATH", tg.path("."))
tg.run("get", "-u", "github.com/rsc/go-get-issue-11864")
}
func TestVendorGetTU(t *testing.T) {
testenv.MustHaveExternalNetwork(t)
tg := testgo(t)
defer tg.cleanup()
tg.makeTempdir()
tg.setenv("GOPATH", tg.path("."))
tg.run("get", "-t", "-u", "github.com/rsc/go-get-issue-11864/...")
}
func TestVendorGetBadVendor(t *testing.T) {
testenv.MustHaveExternalNetwork(t)
for _, suffix := range []string{"bad/imp", "bad/imp2", "bad/imp3", "..."} {
t.Run(suffix, func(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
tg.makeTempdir()
tg.setenv("GOPATH", tg.path("."))
tg.runFail("get", "-t", "-u", "github.com/rsc/go-get-issue-18219/"+suffix)
tg.grepStderr("must be imported as", "did not find error about vendor import")
tg.mustNotExist(tg.path("src/github.com/rsc/vendor"))
})
}
}
func TestGetSubmodules(t *testing.T) { func TestGetSubmodules(t *testing.T) {
testenv.MustHaveExternalNetwork(t) testenv.MustHaveExternalNetwork(t)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment