1
0
mirror of https://github.com/golang/go synced 2024-11-17 03:04:44 -07:00

cmd/go: fix hang in workspaces

golang.org/cl/365234 incorrectly had pruningForGoVersion always return
workspace pruning instead of just returning workspace pruning at the top
level, which broke the proper determination of pruning for dependency
packages. Fix that code, and also fix a hang that resulted because the
module loading code keeps loading dependencies until it reaches a pruned
module or an unpruned module it already saw, so it could get stuck in a
cycle. 

Change-Id: I8911f7d83aaee5870c43ef0355abbd439f15d4f7
Reviewed-on: https://go-review.googlesource.com/c/go/+/366775
Trust: Michael Matloob <matloob@golang.org>
Run-TryBot: Michael Matloob <matloob@golang.org>
Reviewed-by: Bryan Mills <bcmills@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
This commit is contained in:
Michael Matloob 2021-11-23 17:36:21 -05:00
parent 6b609110fd
commit 85a8e1786a
3 changed files with 76 additions and 4 deletions

View File

@ -694,7 +694,11 @@ func LoadModFile(ctx context.Context) *Requirements {
MainModules = makeMainModules([]module.Version{mainModule}, []string{""}, []*modfile.File{nil}, []*modFileIndex{nil}, "", nil)
goVersion := LatestGoVersion()
rawGoVersion.Store(mainModule, goVersion)
requirements = newRequirements(pruningForGoVersion(goVersion), nil, nil)
pruning := pruningForGoVersion(goVersion)
if inWorkspaceMode() {
pruning = workspace
}
requirements = newRequirements(pruning, nil, nil)
return requirements
}

View File

@ -124,9 +124,6 @@ const (
)
func pruningForGoVersion(goVersion string) modPruning {
if inWorkspaceMode() {
return workspace
}
if semver.Compare("v"+goVersion, ExplicitIndirectVersionV) < 0 {
// The go.mod file does not duplicate relevant information about transitive
// dependencies, so they cannot be pruned out.

View File

@ -0,0 +1,71 @@
# This test makes checks against a regression of a bug in the Go command
# where the module loader hung forever because all main module dependencies
# kept workspace pruning instead of adopting the pruning in their go.mod
# files, and the loader kept adding dependencies on the queue until they
# were either pruned or unpruned, never breaking a module dependency cycle.
#
# This is the module graph in the test:
#
# /-------------------------\
# | |
# V |
# example.com/a -> example.com/b v1.0.0 -> example.com/c v1.1.0
go list -m -f '{{.Version}}' example.com/c
-- go.work --
go 1.16
use (
./a
)
-- a/go.mod --
module example.com/a
go 1.18
require example.com/b v1.0.0
replace example.com/b v1.0.0 => ../b
replace example.com/c v1.0.0 => ../c
-- a/foo.go --
package main
import "example.com/b"
func main() {
b.B()
}
-- b/go.mod --
module example.com/b
go 1.18
require example.com/c v1.0.0
-- b/b.go --
package b
func B() {
}
-- b/cmd/main.go --
package main
import "example.com/c"
func main() {
c.C()
}
-- c/go.mod --
module example.com/c
go 1.18
require example.com/b v1.0.0
-- c/c.go --
package c
import "example.com/b"
func C() {
b.B()
}