]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/go: don't try to add replaced versions that won't be selected
authorBryan C. Mills <bcmills@google.com>
Thu, 24 Jun 2021 03:29:10 +0000 (23:29 -0400)
committerBryan C. Mills <bcmills@google.com>
Thu, 24 Jun 2021 18:12:53 +0000 (18:12 +0000)
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 <bcmills@google.com>
Run-TryBot: Bryan C. Mills <bcmills@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Jay Conrod <jayconrod@google.com>
src/cmd/go/internal/modload/import.go
src/cmd/go/testdata/script/mod_tidy_replace_old.txt [new file with mode: 0644]

index 60bd26fb22f019ee21ae29c95f1cf9ea8d3a2e8b..d2bbe5cbe0b1eae58ac5a041792d0b4d0e8a3c85 100644 (file)
@@ -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 (file)
index 0000000..cfd3792
--- /dev/null
@@ -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"
+)