]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/go: handle queries properly in go install m@v
authorRuss Cox <rsc@golang.org>
Wed, 24 May 2023 11:10:17 +0000 (07:10 -0400)
committerGopher Robot <gobot@golang.org>
Thu, 25 May 2023 17:34:01 +0000 (17:34 +0000)
The original code only handled go install m@v1.0.0
but not queries like go install m@v1 or m@master.
Handle those by invoking more of the module machinery.

For #57001.

Change-Id: I7d54fc3dd65072e5906a17ff95b407b0f7feac69
Reviewed-on: https://go-review.googlesource.com/c/go/+/497879
Run-TryBot: Russ Cox <rsc@golang.org>
Reviewed-by: Bryan Mills <bcmills@google.com>
Auto-Submit: Russ Cox <rsc@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>

src/cmd/go/gotoolchain.go
src/cmd/go/internal/modload/init.go
src/cmd/go/testdata/mod/rsc.io_fortune_v0.0.1.txt
src/cmd/go/testdata/script/gotoolchain.txt

index 26d80db246c6dc454d78c9f892dbe36483a56461..03e2e95edd18ea11b5cb55f236892ecdb114a90d 100644 (file)
@@ -15,18 +15,15 @@ import (
        "log"
        "os"
        "os/exec"
-       "path"
        "path/filepath"
        "runtime"
        "strings"
-       "sync"
        "syscall"
 
        "cmd/go/internal/base"
        "cmd/go/internal/cfg"
        "cmd/go/internal/gover"
        "cmd/go/internal/modcmd"
-       "cmd/go/internal/modfetch"
        "cmd/go/internal/modload"
        "cmd/go/internal/run"
 
@@ -374,46 +371,25 @@ func goInstallVersion() (m module.Version, goVers string, ok bool) {
                return module.Version{}, "", false
        }
 
-       // We need to resolve the pkg to a module, to find its go.mod.
-       // Normally we use the module loading code to grab the full
-       // module file tree for pkg and all its path prefixes, checking each
-       // for a file tree that contains source code for pkg.
-       // We can't do that here, because the modules may use newer versions
-       // of Go that affect which files are contained in the modules and therefore
-       // affect their checksums: there is no guarantee an older version of Go
-       // can extract a newer Go module from a VCS repo and choose the right files
-       // (this allows evolution such as https://go.dev/issue/42965).
-       // Instead, we check for a module at all path prefixes (including path itself)
-       // and take the max of the Go versions along the path.
-       var paths []string
-       for len(m.Path) > 1 {
-               paths = append(paths, m.Path)
-               m.Path = path.Dir(m.Path)
-       }
-       goVersions := make([]string, len(paths))
-       var wg sync.WaitGroup
-       for i, path := range paths {
-               i := i
-               path := path
-               wg.Add(1)
-               go func() {
-                       defer wg.Done()
-                       // TODO(rsc): m.Version could in general be something like latest or patch or upgrade.
-                       // Use modload.Query. See review comment on https://go.dev/cl/497079.
-                       data, err := modfetch.GoMod(context.Background(), path, m.Version)
-                       if err != nil {
-                               return
-                       }
-                       goVersions[i] = gover.GoModLookup(data, "go")
-               }()
+       // Set up modules without an explicit go.mod, to download go.mod.
+       modload.ForceUseModules = true
+       modload.RootMode = modload.NoRoot
+       modload.Init()
+       defer modload.Reset()
+
+       // See internal/load.PackagesAndErrorsOutsideModule
+       ctx := context.Background()
+       allowed := modload.CheckAllowed
+       if modload.IsRevisionQuery(m.Path, m.Version) {
+               // Don't check for retractions if a specific revision is requested.
+               allowed = nil
        }
-       wg.Wait()
-       goVers = ""
-       for i, v := range goVersions {
-               if gover.Compare(goVers, v) < 0 {
-                       m.Path = paths[i]
-                       goVers = v
-               }
+       noneSelected := func(path string) (version string) { return "none" }
+       _, err := modload.QueryPackages(ctx, m.Path, m.Version, noneSelected, allowed)
+       tooNew, ok := err.(*gover.TooNewError)
+       if !ok {
+               return module.Version{}, "", false
        }
-       return m, goVers, true
+       m.Path, m.Version, _ = strings.Cut(tooNew.What, "@")
+       return m, tooNew.GoVersion, true
 }
index 58747e7129f05c7240c23d730b47786bd2a1482f..86be7da243df6147d12d0979a008e6fdcc8e5388 100644 (file)
@@ -323,6 +323,20 @@ func WorkFilePath() string {
        return workFilePath
 }
 
+// Reset clears all the initialized, cached state about the use of modules,
+// so that we can start over.
+func Reset() {
+       initialized = false
+       ForceUseModules = false
+       RootMode = 0
+       modRoots = nil
+       cfg.ModulesEnabled = false
+       MainModules = nil
+       requirements = nil
+       workFilePath = ""
+       modfetch.Reset()
+}
+
 // Init determines whether module mode is enabled, locates the root of the
 // current module (if any), sets environment variables for Git subprocesses, and
 // configures the cfg, codehost, load, modfetch, and search packages for use
index 7aae658d41618ae58b77824a0b0db14ebcd84a6b..644695cba11b6c9034a40466311392522e9cd493 100644 (file)
@@ -5,6 +5,10 @@ written by hand
 module rsc.io/fortune
 go 1.21rc999
 
+-- go.mod --
+module rsc.io/fortune
+go 1.21rc999
+
 -- .info --
 {"Version":"v0.0.1"}
 -- fortune.go --
index 97e6d5fd1bf23b72f8658aeaee2bf001b945b0f8..406bbd7568ca6c38dd92e377ddd4c498541dc2a7 100644 (file)
@@ -212,6 +212,10 @@ cp go1999 go.mod
 ! go install rsc.io/fortune/nonexist@v0.0.1
 stderr '^go: cannot find "go1.21rc999" in PATH$'
 
+# go install m@v should handle queries
+! go install rsc.io/fortune/nonexist@v0.0
+stderr '^go: cannot find "go1.21rc999" in PATH$'
+
 # go run m@v should use go version in m@v's go.mod
 env GOTOOLCHAIN=path
 env TESTGO_VERSION=go1.19
@@ -227,6 +231,15 @@ stderr '^go: cannot find "go1.21rc999" in PATH$'
 ! go run -x rsc.io/fortune/nonexist@v0.0.1 args here
 stderr '^go: cannot find "go1.21rc999" in PATH$'
 
+# go run m@v should handle queries
+! go run rsc.io/fortune/nonexist@v0
+stderr '^go: cannot find "go1.21rc999" in PATH$'
+
+# go install m@v should work if not upgrading
+go install rsc.io/fortune/nonexist@v1
+stderr '^go: downloading rsc.io/fortune v1.0.0$'
+stdout '^go1.999testpath here!'
+
 -- empty --
 
 -- go1999 --