From 600a2a4ffb9a273a3a1635b60120ffc768741aa9 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Wed, 23 Jun 2021 23:29:10 -0400 Subject: [PATCH] cmd/go: don't try to add replaced versions that won't be selected In Go 1.12, we added a heuristic to 'go mod tidy' to resolve packages by adding replaced-but-not-required modules before falling back to searching for modules from the network. Unfortunately, that heuristic fails when the replaced version is already lower than the selected version: adding such a module to the build list doesn't change the selected version of that module, and so it doesn't make progress toward resolving the missing package. Fixes #46659 Change-Id: I75e2387d5290e769f6b0fa1231dcc4605db68597 Reviewed-on: https://go-review.googlesource.com/c/go/+/330432 Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills TryBot-Result: Go Bot Reviewed-by: Jay Conrod --- src/cmd/go/internal/modload/import.go | 9 +++++ .../testdata/script/mod_tidy_replace_old.txt | 34 +++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 src/cmd/go/testdata/script/mod_tidy_replace_old.txt diff --git a/src/cmd/go/internal/modload/import.go b/src/cmd/go/internal/modload/import.go index 60bd26fb22..d2bbe5cbe0 100644 --- a/src/cmd/go/internal/modload/import.go +++ b/src/cmd/go/internal/modload/import.go @@ -428,6 +428,15 @@ func queryImport(ctx context.Context, path string, rs *Requirements) (module.Ver mv = module.ZeroPseudoVersion("v0") } } + mg, err := rs.Graph(ctx) + if err != nil { + return module.Version{}, err + } + if cmpVersion(mg.Selected(mp), mv) >= 0 { + // We can't resolve the import by adding mp@mv to the module graph, + // because the selected version of mp is already at least mv. + continue + } mods = append(mods, module.Version{Path: mp, Version: mv}) } diff --git a/src/cmd/go/testdata/script/mod_tidy_replace_old.txt b/src/cmd/go/testdata/script/mod_tidy_replace_old.txt new file mode 100644 index 0000000000..cfd3792600 --- /dev/null +++ b/src/cmd/go/testdata/script/mod_tidy_replace_old.txt @@ -0,0 +1,34 @@ +# Regression test for https://golang.org/issue/46659. +# +# If a 'replace' directive specifies an older-than-selected version of a module, +# 'go mod tidy' shouldn't try to add that version to the build list to resolve a +# missing package: it won't be selected, and would cause the module loader to +# loop indefinitely trying to resolve the package. + +cp go.mod go.mod.orig + +! go mod tidy +! stderr panic +stderr '^golang\.org/issue46659 imports\n\texample\.com/missingpkg/deprecated: package example\.com/missingpkg/deprecated provided by example\.com/missingpkg at latest version v1\.0\.0 but not at required version v1\.0\.1-beta$' + +go mod tidy -e + +cmp go.mod go.mod.orig + +-- go.mod -- +module golang.org/issue46659 + +go 1.17 + +replace example.com/missingpkg v1.0.1-alpha => example.com/missingpkg v1.0.0 + +require example.com/usemissingpre v1.0.0 + +require example.com/missingpkg v1.0.1-beta // indirect +-- m.go -- +package m + +import ( + _ "example.com/missingpkg/deprecated" + _ "example.com/usemissingpre" +)