]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/go: change toolchain based on $GOTOOLCHAIN
authorRuss Cox <rsc@golang.org>
Fri, 10 Mar 2023 19:02:32 +0000 (14:02 -0500)
committerRuss Cox <rsc@golang.org>
Tue, 18 Apr 2023 13:19:02 +0000 (13:19 +0000)
For proposal #57001, add code to reinvoke a different Go toolchain
based on $GOTOOLCHAIN. The toolchain is searched for in $PATH
first and otherwise downloaded. The download is a standard module
download, so the toolchain is validated using the checksum database
before being executed or even stored in the file system.

Followup CLs will refine the exact toolchain selection and implement
other parts of the proposal. This is only the download+reinvoke code.

For #57001.

Change-Id: I44363cbd916dac01342b1bfce6a487fe7166be4a
Reviewed-on: https://go-review.googlesource.com/c/go/+/475955
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Michael Matloob <matloob@golang.org>
52 files changed:
src/cmd/go/gotoolchain.go [new file with mode: 0644]
src/cmd/go/gotoolchain_js.go [new file with mode: 0644]
src/cmd/go/internal/modcmd/download.go
src/cmd/go/internal/modfetch/fetch.go
src/cmd/go/main.go
src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.aix-ppc64.txt [new file with mode: 0644]
src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.android-386.txt [new file with mode: 0644]
src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.android-amd64.txt [new file with mode: 0644]
src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.android-arm.txt [new file with mode: 0644]
src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.android-arm64.txt [new file with mode: 0644]
src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.darwin-amd64.txt [new file with mode: 0644]
src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.darwin-arm64.txt [new file with mode: 0644]
src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.dragonfly-amd64.txt [new file with mode: 0644]
src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.freebsd-386.txt [new file with mode: 0644]
src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.freebsd-amd64.txt [new file with mode: 0644]
src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.freebsd-arm.txt [new file with mode: 0644]
src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.freebsd-arm64.txt [new file with mode: 0644]
src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.freebsd-riscv64.txt [new file with mode: 0644]
src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.illumos-amd64.txt [new file with mode: 0644]
src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.ios-amd64.txt [new file with mode: 0644]
src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.ios-arm64.txt [new file with mode: 0644]
src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.js-wasm.txt [new file with mode: 0644]
src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.linux-386.txt [new file with mode: 0644]
src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.linux-amd64.txt [new file with mode: 0644]
src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.linux-arm.txt [new file with mode: 0644]
src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.linux-arm64.txt [new file with mode: 0644]
src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.linux-loong64.txt [new file with mode: 0644]
src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.linux-mips64x.txt [new file with mode: 0644]
src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.linux-mipsx.txt [new file with mode: 0644]
src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.linux-ppc64.txt [new file with mode: 0644]
src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.linux-ppc64le.txt [new file with mode: 0644]
src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.linux-riscv64.txt [new file with mode: 0644]
src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.linux-s390x.txt [new file with mode: 0644]
src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.netbsd-386.txt [new file with mode: 0644]
src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.netbsd-amd64.txt [new file with mode: 0644]
src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.netbsd-arm.txt [new file with mode: 0644]
src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.netbsd-arm64.txt [new file with mode: 0644]
src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.openbsd-386.txt [new file with mode: 0644]
src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.openbsd-amd64.txt [new file with mode: 0644]
src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.openbsd-arm.txt [new file with mode: 0644]
src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.openbsd-arm64.txt [new file with mode: 0644]
src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.openbsd-mips64.txt [new file with mode: 0644]
src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.plan9-386.txt [new file with mode: 0644]
src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.plan9-amd64.txt [new file with mode: 0644]
src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.plan9-arm.txt [new file with mode: 0644]
src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.solaris-amd64.txt [new file with mode: 0644]
src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.windows-386.txt [new file with mode: 0644]
src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.windows-amd64.txt [new file with mode: 0644]
src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.windows-arm.txt [new file with mode: 0644]
src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.windows-arm64.txt [new file with mode: 0644]
src/cmd/go/testdata/script/gotoolchain.txt [new file with mode: 0644]
src/internal/cfg/cfg.go

diff --git a/src/cmd/go/gotoolchain.go b/src/cmd/go/gotoolchain.go
new file mode 100644 (file)
index 0000000..a051224
--- /dev/null
@@ -0,0 +1,214 @@
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build !js
+
+package main
+
+import (
+       "cmd/go/internal/base"
+       "cmd/go/internal/cfg"
+       "cmd/go/internal/modcmd"
+       "cmd/go/internal/modload"
+       "context"
+       "fmt"
+       "internal/godebug"
+       "io/fs"
+       "log"
+       "os"
+       "os/exec"
+       "path/filepath"
+       "runtime"
+       "strings"
+       "syscall"
+)
+
+const (
+       // We download golang.org/toolchain version v0.0.1-<gotoolchain>.<goos>-<goarch>.
+       // If the 0.0.1 indicates anything at all, its the version of the toolchain packaging:
+       // if for some reason we needed to change the way toolchains are packaged into
+       // module zip files in a future version of Go, we could switch to v0.0.2 and then
+       // older versions expecting the old format could use v0.0.1 and newer versions
+       // would use v0.0.2. Of course, then we'd also have to publish two of each
+       // module zip file. It's not likely we'll ever need to change this.
+       gotoolchainModule  = "golang.org/toolchain"
+       gotoolchainVersion = "v0.0.1"
+
+       // gotoolchainSwitchEnv is a special environment variable
+       // set to 1 during the toolchain switch by the parent process
+       // and cleared in the child process. When set, that indicates
+       // to the child not to do its own toolchain switch logic,
+       // to avoid an infinite recursion if for some reason a toolchain
+       // did not believe it could handle its own version and then
+       // reinvoked itself.
+       gotoolchainSwitchEnv = "GOTOOLCHAIN_INTERNAL_SWITCH"
+)
+
+// switchGoToolchain invokes a different Go toolchain if directed by
+// the GOTOOLCHAIN environment variable or the user's configuration
+// or go.mod file.
+func switchGoToolchain() {
+       log.SetPrefix("go: ")
+       defer log.SetPrefix("")
+
+       sw := os.Getenv(gotoolchainSwitchEnv)
+       os.Unsetenv(gotoolchainSwitchEnv)
+
+       if !modload.WillBeEnabled() || sw == "1" {
+               return
+       }
+
+       gotoolchain := cfg.Getenv("GOTOOLCHAIN")
+       if gotoolchain == "" {
+               if strings.HasPrefix(runtime.Version(), "go") {
+                       gotoolchain = "local" // TODO: set to "auto" once auto is implemented below
+               } else {
+                       gotoolchain = "local"
+               }
+       }
+       env := gotoolchain
+       if gotoolchain == "auto" || gotoolchain == "path" {
+               // TODO: Locate and read go.mod or go.work.
+               base.Fatalf("GOTOOLCHAIN=auto not yet implemented")
+       }
+
+       if gotoolchain == "local" || gotoolchain == runtime.Version() {
+               // Let the current binary handle the command.
+               return
+       }
+
+       // Minimal sanity check of GOTOOLCHAIN setting before search.
+       // We want to allow things like go1.20.3 but also gccgo-go1.20.3.
+       // We want to disallow mistakes / bad ideas like GOTOOLCHAIN=bash,
+       // since we will find that in the path lookup.
+       if !strings.HasPrefix(gotoolchain, "go1") && !strings.Contains(gotoolchain, "-go1") {
+               base.Fatalf("invalid GOTOOLCHAIN %q", gotoolchain)
+       }
+
+       // Look in PATH for the toolchain before we download one.
+       // This allows custom toolchains as well as reuse of toolchains
+       // already installed using go install golang.org/dl/go1.2.3@latest.
+       if exe, err := exec.LookPath(gotoolchain); err == nil {
+               execGoToolchain(gotoolchain, "", exe)
+       }
+
+       // GOTOOLCHAIN=auto looks in PATH and then falls back to download.
+       // GOTOOLCHAIN=path only looks in PATH.
+       if env == "path" {
+               base.Fatalf("cannot find %q in PATH", gotoolchain)
+       }
+
+       // Set up modules without an explicit go.mod, to download distribution.
+       modload.ForceUseModules = true
+       modload.RootMode = modload.NoRoot
+       modload.Init()
+
+       // Download and unpack toolchain module into module cache.
+       // Note that multiple go commands might be doing this at the same time,
+       // and that's OK: the module cache handles that case correctly.
+       m := &modcmd.ModuleJSON{
+               Path:    gotoolchainModule,
+               Version: gotoolchainVersion + "-" + gotoolchain + "." + runtime.GOOS + "-" + runtime.GOARCH,
+       }
+       modcmd.DownloadModule(context.Background(), m)
+       if m.Error != "" {
+               if strings.Contains(m.Error, ".info: 404") {
+                       base.Fatalf("download %s for %s/%s: toolchain not available", gotoolchain, runtime.GOOS, runtime.GOARCH)
+               }
+               base.Fatalf("download %s: %v", gotoolchain, m.Error)
+       }
+
+       // On first use after download, set the execute bits on the commands
+       // so that we can run them. Note that multiple go commands might be
+       // doing this at the same time, but if so no harm done.
+       dir := m.Dir
+       if runtime.GOOS != "windows" {
+               info, err := os.Stat(filepath.Join(dir, "bin/go"))
+               if err != nil {
+                       base.Fatalf("download %s: %v", gotoolchain, err)
+               }
+               if info.Mode()&0111 == 0 {
+                       // allowExec sets the exec permission bits on all files found in dir.
+                       allowExec := func(dir string) {
+                               err := filepath.WalkDir(dir, func(path string, d fs.DirEntry, err error) error {
+                                       if err != nil {
+                                               return err
+                                       }
+                                       if !d.IsDir() {
+                                               info, err := os.Stat(path)
+                                               if err != nil {
+                                                       return err
+                                               }
+                                               if err := os.Chmod(path, info.Mode()&0777|0111); err != nil {
+                                                       return err
+                                               }
+                                       }
+                                       return nil
+                               })
+                               if err != nil {
+                                       base.Fatalf("download %s: %v", gotoolchain, err)
+                               }
+                       }
+
+                       // Set the bits in pkg/tool before bin/go.
+                       // If we are racing with another go command and do bin/go first,
+                       // then the check of bin/go above might succeed, the other go command
+                       // would skip its own mode-setting, and then the go command might
+                       // try to run a tool before we get to setting the bits on pkg/tool.
+                       // Setting pkg/tool before bin/go avoids that ordering problem.
+                       // The only other tool the go command invokes is gofmt,
+                       // so we set that one explicitly before handling bin (which will include bin/go).
+                       allowExec(filepath.Join(dir, "pkg/tool"))
+                       allowExec(filepath.Join(dir, "bin/gofmt"))
+                       allowExec(filepath.Join(dir, "bin"))
+               }
+       }
+
+       // Reinvoke the go command.
+       execGoToolchain(gotoolchain, dir, filepath.Join(dir, "bin/go"))
+}
+
+// execGoToolchain execs the Go toolchain with the given name (gotoolchain),
+// GOROOT directory, and go command executable.
+// The GOROOT directory is empty if we are invoking a command named
+// gotoolchain found in $PATH.
+func execGoToolchain(gotoolchain, dir, exe string) {
+       os.Setenv(gotoolchainSwitchEnv, "1")
+       if dir == "" {
+               os.Unsetenv("GOROOT")
+       } else {
+               os.Setenv("GOROOT", dir)
+       }
+
+       // On Windows, there is no syscall.Exec, so the best we can do
+       // is run a subprocess and exit with the same status.
+       // Doing the same on Unix would be a problem because it wouldn't
+       // propagate signals and such, but there are no signals on Windows.
+       // We also use the exec case when GODEBUG=gotoolchainexec=0,
+       // to allow testing this code even when not on Windows.
+       if godebug.New("gotoolchainexec").Value() == "0" || runtime.GOOS == "windows" {
+               cmd := exec.Command(exe, os.Args[1:]...)
+               if runtime.GOOS == "windows" && strings.Contains(exe, "go1.999test") {
+                       // See testdata/script/gotoolchain.txt.
+                       cmd = exec.Command("cmd", "/c", "echo pretend we ran "+exe)
+               }
+               cmd.Stdin = os.Stdin
+               cmd.Stdout = os.Stdout
+               cmd.Stderr = os.Stderr
+               fmt.Fprintln(os.Stderr, cmd.Args)
+               err := cmd.Run()
+               if err != nil {
+                       if e, ok := err.(*exec.ExitError); ok && e.ProcessState != nil {
+                               if e.ProcessState.Exited() {
+                                       os.Exit(e.ProcessState.ExitCode())
+                               }
+                               base.Fatalf("exec %s: %s", gotoolchain, e.ProcessState)
+                       }
+                       base.Fatalf("exec %s: %s", exe, err)
+               }
+               os.Exit(0)
+       }
+       err := syscall.Exec(exe, os.Args, os.Environ())
+       base.Fatalf("exec %s: %v", gotoolchain, err)
+}
diff --git a/src/cmd/go/gotoolchain_js.go b/src/cmd/go/gotoolchain_js.go
new file mode 100644 (file)
index 0000000..0042ef3
--- /dev/null
@@ -0,0 +1,11 @@
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build js
+
+package main
+
+// nop for systems that don't even define syscall.Exec, like js/wasm.
+func switchGoToolchain() {
+}
index f0b62e8b4bb825a5c21a29dc94d2c1ab76d6691f..302ab2fb6b063f7cffb9b0b84876709998c6c267 100644 (file)
@@ -88,7 +88,8 @@ func init() {
        base.AddModCommonFlags(&cmdDownload.Flag)
 }
 
-type moduleJSON struct {
+// A ModuleJSON describes the result of go mod download.
+type ModuleJSON struct {
        Path     string `json:",omitempty"`
        Version  string `json:",omitempty"`
        Query    string `json:",omitempty"`
@@ -167,43 +168,11 @@ func runDownload(ctx context.Context, cmd *base.Command, args []string) {
                base.Exit()
        }
 
-       downloadModule := func(m *moduleJSON) {
-               _, file, err := modfetch.InfoFile(m.Path, m.Version)
-               if err != nil {
-                       m.Error = err.Error()
-                       return
-               }
-               m.Info = file
-               m.GoMod, err = modfetch.GoModFile(m.Path, m.Version)
-               if err != nil {
-                       m.Error = err.Error()
-                       return
-               }
-               m.GoModSum, err = modfetch.GoModSum(m.Path, m.Version)
-               if err != nil {
-                       m.Error = err.Error()
-                       return
-               }
-               mod := module.Version{Path: m.Path, Version: m.Version}
-               m.Zip, err = modfetch.DownloadZip(ctx, mod)
-               if err != nil {
-                       m.Error = err.Error()
-                       return
-               }
-               m.Sum = modfetch.Sum(mod)
-               m.Dir, err = modfetch.Download(ctx, mod)
-               if err != nil {
-                       m.Error = err.Error()
-                       return
-               }
-       }
-
-       var mods []*moduleJSON
-
        if *downloadReuse != "" && modload.HasModRoot() {
                base.Fatalf("go mod download -reuse cannot be used inside a module")
        }
 
+       var mods []*ModuleJSON
        type token struct{}
        sem := make(chan token, runtime.GOMAXPROCS(0))
        infos, infosErr := modload.ListModules(ctx, args, 0, *downloadReuse)
@@ -232,7 +201,7 @@ func runDownload(ctx context.Context, cmd *base.Command, args []string) {
                        // Nothing to download.
                        continue
                }
-               m := &moduleJSON{
+               m := &ModuleJSON{
                        Path:    info.Path,
                        Version: info.Version,
                        Query:   info.Query,
@@ -249,7 +218,7 @@ func runDownload(ctx context.Context, cmd *base.Command, args []string) {
                }
                sem <- token{}
                go func() {
-                       downloadModule(m)
+                       DownloadModule(ctx, m)
                        <-sem
                }()
        }
@@ -309,3 +278,37 @@ func runDownload(ctx context.Context, cmd *base.Command, args []string) {
                base.Errorf("go: %v", infosErr)
        }
 }
+
+// DownloadModule runs 'go mod download' for m.Path@m.Version,
+// leaving the results (including any error) in m itself.
+func DownloadModule(ctx context.Context, m *ModuleJSON) {
+       var err error
+       _, file, err := modfetch.InfoFile(m.Path, m.Version)
+       if err != nil {
+               m.Error = err.Error()
+               return
+       }
+       m.Info = file
+       m.GoMod, err = modfetch.GoModFile(m.Path, m.Version)
+       if err != nil {
+               m.Error = err.Error()
+               return
+       }
+       m.GoModSum, err = modfetch.GoModSum(m.Path, m.Version)
+       if err != nil {
+               m.Error = err.Error()
+               return
+       }
+       mod := module.Version{Path: m.Path, Version: m.Version}
+       m.Zip, err = modfetch.DownloadZip(ctx, mod)
+       if err != nil {
+               m.Error = err.Error()
+               return
+       }
+       m.Sum = modfetch.Sum(mod)
+       m.Dir, err = modfetch.Download(ctx, mod)
+       if err != nil {
+               m.Error = err.Error()
+               return
+       }
+}
index c9502ca4326fc48b5fe55e6587ad09c1dd362779..35b8ab9eba1fc50c6507dc0ce531801bf0f2d8c4 100644 (file)
@@ -173,7 +173,18 @@ func DownloadZip(ctx context.Context, mod module.Version) (zipfile string, err e
 
                // The zip or ziphash file does not exist. Acquire the lock and create them.
                if cfg.CmdName != "mod download" {
-                       fmt.Fprintf(os.Stderr, "go: downloading %s %s\n", mod.Path, mod.Version)
+                       vers := mod.Version
+                       if mod.Path == "golang.org/toolchain" {
+                               // Shorten v0.0.1-go1.13.1.darwin-amd64 to go1.13.1.darwin-amd64
+                               _, vers, _ = strings.Cut(vers, "-")
+                               if i := strings.LastIndex(vers, "."); i >= 0 {
+                                       goos, goarch, _ := strings.Cut(vers[i+1:], "-")
+                                       vers = vers[:i] + " (" + goos + "/" + goarch + ")"
+                               }
+                               fmt.Fprintf(os.Stderr, "go: downloading %s\n", vers)
+                       } else {
+                               fmt.Fprintf(os.Stderr, "go: downloading %s %s\n", mod.Path, vers)
+                       }
                }
                unlock, err := lockVersion(mod)
                if err != nil {
index 6d3d5d405930d850978dc27b852f6d8a69eb798d..e441b4ea014d80493706919da533b730b19b0da8 100644 (file)
@@ -87,11 +87,14 @@ func init() {
        }
 }
 
+var _ = go11tag
+
 func main() {
-       _ = go11tag
+       log.SetFlags(0)
+       switchGoToolchain()
+
        flag.Usage = base.Usage
        flag.Parse()
-       log.SetFlags(0)
 
        args := flag.Args()
        if len(args) < 1 {
diff --git a/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.aix-ppc64.txt b/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.aix-ppc64.txt
new file mode 100644 (file)
index 0000000..e70c4d7
--- /dev/null
@@ -0,0 +1,14 @@
+golang.org/toolchain@v0.0.1-go1.999testmod.aix-ppc64
+
+-- .mod --
+module golang.org/toolchain
+-- .info --
+{"Version":"v0.0.1-go1.999testmod.aix-ppc64"}
+-- go.mod --
+module golang.org/toolchain
+-- bin/go --
+#!/bin/sh
+echo go1.999testmod here!
+-- bin/gofmt --
+echo i am unused
+-- pkg/tool/fake --
diff --git a/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.android-386.txt b/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.android-386.txt
new file mode 100644 (file)
index 0000000..981334e
--- /dev/null
@@ -0,0 +1,14 @@
+golang.org/toolchain@v0.0.1-go1.999testmod.android-386
+
+-- .mod --
+module golang.org/toolchain
+-- .info --
+{"Version":"v0.0.1-go1.999testmod.android-386"}
+-- go.mod --
+module golang.org/toolchain
+-- bin/go --
+#!/bin/sh
+echo go1.999testmod here!
+-- bin/gofmt --
+echo i am unused
+-- pkg/tool/fake --
diff --git a/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.android-amd64.txt b/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.android-amd64.txt
new file mode 100644 (file)
index 0000000..a01fce8
--- /dev/null
@@ -0,0 +1,14 @@
+golang.org/toolchain@v0.0.1-go1.999testmod.android-amd64
+
+-- .mod --
+module golang.org/toolchain
+-- .info --
+{"Version":"v0.0.1-go1.999testmod.android-amd64"}
+-- go.mod --
+module golang.org/toolchain
+-- bin/go --
+#!/bin/sh
+echo go1.999testmod here!
+-- bin/gofmt --
+echo i am unused
+-- pkg/tool/fake --
diff --git a/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.android-arm.txt b/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.android-arm.txt
new file mode 100644 (file)
index 0000000..0de1cec
--- /dev/null
@@ -0,0 +1,14 @@
+golang.org/toolchain@v0.0.1-go1.999testmod.android-arm
+
+-- .mod --
+module golang.org/toolchain
+-- .info --
+{"Version":"v0.0.1-go1.999testmod.android-arm"}
+-- go.mod --
+module golang.org/toolchain
+-- bin/go --
+#!/bin/sh
+echo go1.999testmod here!
+-- bin/gofmt --
+echo i am unused
+-- pkg/tool/fake --
diff --git a/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.android-arm64.txt b/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.android-arm64.txt
new file mode 100644 (file)
index 0000000..1ebeadc
--- /dev/null
@@ -0,0 +1,14 @@
+golang.org/toolchain@v0.0.1-go1.999testmod.android-arm64
+
+-- .mod --
+module golang.org/toolchain
+-- .info --
+{"Version":"v0.0.1-go1.999testmod.android-arm64"}
+-- go.mod --
+module golang.org/toolchain
+-- bin/go --
+#!/bin/sh
+echo go1.999testmod here!
+-- bin/gofmt --
+echo i am unused
+-- pkg/tool/fake --
diff --git a/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.darwin-amd64.txt b/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.darwin-amd64.txt
new file mode 100644 (file)
index 0000000..5091853
--- /dev/null
@@ -0,0 +1,14 @@
+golang.org/toolchain@v0.0.1-go1.999testmod.darwin-amd64
+
+-- .mod --
+module golang.org/toolchain
+-- .info --
+{"Version":"v0.0.1-go1.999testmod.darwin-amd64"}
+-- go.mod --
+module golang.org/toolchain
+-- bin/go --
+#!/bin/sh
+echo go1.999testmod here!
+-- bin/gofmt --
+echo i am unused
+-- pkg/tool/fake --
diff --git a/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.darwin-arm64.txt b/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.darwin-arm64.txt
new file mode 100644 (file)
index 0000000..6b2b132
--- /dev/null
@@ -0,0 +1,14 @@
+golang.org/toolchain@v0.0.1-go1.999testmod.darwin-arm64
+
+-- .mod --
+module golang.org/toolchain
+-- .info --
+{"Version":"v0.0.1-go1.999testmod.darwin-arm64"}
+-- go.mod --
+module golang.org/toolchain
+-- bin/go --
+#!/bin/sh
+echo go1.999testmod here!
+-- bin/gofmt --
+echo i am unused
+-- pkg/tool/fake --
diff --git a/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.dragonfly-amd64.txt b/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.dragonfly-amd64.txt
new file mode 100644 (file)
index 0000000..814180a
--- /dev/null
@@ -0,0 +1,14 @@
+golang.org/toolchain@v0.0.1-go1.999testmod.dragonfly-amd64
+
+-- .mod --
+module golang.org/toolchain
+-- .info --
+{"Version":"v0.0.1-go1.999testmod.dragonfly-amd64"}
+-- go.mod --
+module golang.org/toolchain
+-- bin/go --
+#!/bin/sh
+echo go1.999testmod here!
+-- bin/gofmt --
+echo i am unused
+-- pkg/tool/fake --
diff --git a/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.freebsd-386.txt b/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.freebsd-386.txt
new file mode 100644 (file)
index 0000000..12e0df4
--- /dev/null
@@ -0,0 +1,14 @@
+golang.org/toolchain@v0.0.1-go1.999testmod.freebsd-386
+
+-- .mod --
+module golang.org/toolchain
+-- .info --
+{"Version":"v0.0.1-go1.999testmod.freebsd-386"}
+-- go.mod --
+module golang.org/toolchain
+-- bin/go --
+#!/bin/sh
+echo go1.999testmod here!
+-- bin/gofmt --
+echo i am unused
+-- pkg/tool/fake --
diff --git a/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.freebsd-amd64.txt b/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.freebsd-amd64.txt
new file mode 100644 (file)
index 0000000..bf470a5
--- /dev/null
@@ -0,0 +1,14 @@
+golang.org/toolchain@v0.0.1-go1.999testmod.freebsd-amd64
+
+-- .mod --
+module golang.org/toolchain
+-- .info --
+{"Version":"v0.0.1-go1.999testmod.freebsd-amd64"}
+-- go.mod --
+module golang.org/toolchain
+-- bin/go --
+#!/bin/sh
+echo go1.999testmod here!
+-- bin/gofmt --
+echo i am unused
+-- pkg/tool/fake --
diff --git a/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.freebsd-arm.txt b/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.freebsd-arm.txt
new file mode 100644 (file)
index 0000000..dc32e0e
--- /dev/null
@@ -0,0 +1,14 @@
+golang.org/toolchain@v0.0.1-go1.999testmod.freebsd-arm
+
+-- .mod --
+module golang.org/toolchain
+-- .info --
+{"Version":"v0.0.1-go1.999testmod.freebsd-arm"}
+-- go.mod --
+module golang.org/toolchain
+-- bin/go --
+#!/bin/sh
+echo go1.999testmod here!
+-- bin/gofmt --
+echo i am unused
+-- pkg/tool/fake --
diff --git a/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.freebsd-arm64.txt b/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.freebsd-arm64.txt
new file mode 100644 (file)
index 0000000..4335ba6
--- /dev/null
@@ -0,0 +1,14 @@
+golang.org/toolchain@v0.0.1-go1.999testmod.freebsd-arm64
+
+-- .mod --
+module golang.org/toolchain
+-- .info --
+{"Version":"v0.0.1-go1.999testmod.freebsd-arm64"}
+-- go.mod --
+module golang.org/toolchain
+-- bin/go --
+#!/bin/sh
+echo go1.999testmod here!
+-- bin/gofmt --
+echo i am unused
+-- pkg/tool/fake --
diff --git a/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.freebsd-riscv64.txt b/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.freebsd-riscv64.txt
new file mode 100644 (file)
index 0000000..6161fe2
--- /dev/null
@@ -0,0 +1,14 @@
+golang.org/toolchain@v0.0.1-go1.999testmod.freebsd-riscv64
+
+-- .mod --
+module golang.org/toolchain
+-- .info --
+{"Version":"v0.0.1-go1.999testmod.freebsd-riscv64"}
+-- go.mod --
+module golang.org/toolchain
+-- bin/go --
+#!/bin/sh
+echo go1.999testmod here!
+-- bin/gofmt --
+echo i am unused
+-- pkg/tool/fake --
diff --git a/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.illumos-amd64.txt b/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.illumos-amd64.txt
new file mode 100644 (file)
index 0000000..b677457
--- /dev/null
@@ -0,0 +1,14 @@
+golang.org/toolchain@v0.0.1-go1.999testmod.illumos-amd64
+
+-- .mod --
+module golang.org/toolchain
+-- .info --
+{"Version":"v0.0.1-go1.999testmod.illumos-amd64"}
+-- go.mod --
+module golang.org/toolchain
+-- bin/go --
+#!/bin/sh
+echo go1.999testmod here!
+-- bin/gofmt --
+echo i am unused
+-- pkg/tool/fake --
diff --git a/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.ios-amd64.txt b/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.ios-amd64.txt
new file mode 100644 (file)
index 0000000..e8363bc
--- /dev/null
@@ -0,0 +1,14 @@
+golang.org/toolchain@v0.0.1-go1.999testmod.ios-amd64
+
+-- .mod --
+module golang.org/toolchain
+-- .info --
+{"Version":"v0.0.1-go1.999testmod.ios-amd64"}
+-- go.mod --
+module golang.org/toolchain
+-- bin/go --
+#!/bin/sh
+echo go1.999testmod here!
+-- bin/gofmt --
+echo i am unused
+-- pkg/tool/fake --
diff --git a/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.ios-arm64.txt b/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.ios-arm64.txt
new file mode 100644 (file)
index 0000000..9585966
--- /dev/null
@@ -0,0 +1,14 @@
+golang.org/toolchain@v0.0.1-go1.999testmod.ios-arm64
+
+-- .mod --
+module golang.org/toolchain
+-- .info --
+{"Version":"v0.0.1-go1.999testmod.ios-arm64"}
+-- go.mod --
+module golang.org/toolchain
+-- bin/go --
+#!/bin/sh
+echo go1.999testmod here!
+-- bin/gofmt --
+echo i am unused
+-- pkg/tool/fake --
diff --git a/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.js-wasm.txt b/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.js-wasm.txt
new file mode 100644 (file)
index 0000000..37fa6c0
--- /dev/null
@@ -0,0 +1,14 @@
+golang.org/toolchain@v0.0.1-go1.999testmod.js-wasm
+
+-- .mod --
+module golang.org/toolchain
+-- .info --
+{"Version":"v0.0.1-go1.999testmod.js-wasm"}
+-- go.mod --
+module golang.org/toolchain
+-- bin/go --
+#!/bin/sh
+echo go1.999testmod here!
+-- bin/gofmt --
+echo i am unused
+-- pkg/tool/fake --
diff --git a/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.linux-386.txt b/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.linux-386.txt
new file mode 100644 (file)
index 0000000..ee96638
--- /dev/null
@@ -0,0 +1,14 @@
+golang.org/toolchain@v0.0.1-go1.999testmod.linux-386
+
+-- .mod --
+module golang.org/toolchain
+-- .info --
+{"Version":"v0.0.1-go1.999testmod.linux-386"}
+-- go.mod --
+module golang.org/toolchain
+-- bin/go --
+#!/bin/sh
+echo go1.999testmod here!
+-- bin/gofmt --
+echo i am unused
+-- pkg/tool/fake --
diff --git a/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.linux-amd64.txt b/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.linux-amd64.txt
new file mode 100644 (file)
index 0000000..6277341
--- /dev/null
@@ -0,0 +1,14 @@
+golang.org/toolchain@v0.0.1-go1.999testmod.linux-amd64
+
+-- .mod --
+module golang.org/toolchain
+-- .info --
+{"Version":"v0.0.1-go1.999testmod.linux-amd64"}
+-- go.mod --
+module golang.org/toolchain
+-- bin/go --
+#!/bin/sh
+echo go1.999testmod here!
+-- bin/gofmt --
+echo i am unused
+-- pkg/tool/fake --
diff --git a/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.linux-arm.txt b/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.linux-arm.txt
new file mode 100644 (file)
index 0000000..678711b
--- /dev/null
@@ -0,0 +1,14 @@
+golang.org/toolchain@v0.0.1-go1.999testmod.linux-arm
+
+-- .mod --
+module golang.org/toolchain
+-- .info --
+{"Version":"v0.0.1-go1.999testmod.linux-arm"}
+-- go.mod --
+module golang.org/toolchain
+-- bin/go --
+#!/bin/sh
+echo go1.999testmod here!
+-- bin/gofmt --
+echo i am unused
+-- pkg/tool/fake --
diff --git a/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.linux-arm64.txt b/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.linux-arm64.txt
new file mode 100644 (file)
index 0000000..bb305ab
--- /dev/null
@@ -0,0 +1,14 @@
+golang.org/toolchain@v0.0.1-go1.999testmod.linux-arm64
+
+-- .mod --
+module golang.org/toolchain
+-- .info --
+{"Version":"v0.0.1-go1.999testmod.linux-arm64"}
+-- go.mod --
+module golang.org/toolchain
+-- bin/go --
+#!/bin/sh
+echo go1.999testmod here!
+-- bin/gofmt --
+echo i am unused
+-- pkg/tool/fake --
diff --git a/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.linux-loong64.txt b/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.linux-loong64.txt
new file mode 100644 (file)
index 0000000..52a23d4
--- /dev/null
@@ -0,0 +1,14 @@
+golang.org/toolchain@v0.0.1-go1.999testmod.linux-loong64
+
+-- .mod --
+module golang.org/toolchain
+-- .info --
+{"Version":"v0.0.1-go1.999testmod.linux-loong64"}
+-- go.mod --
+module golang.org/toolchain
+-- bin/go --
+#!/bin/sh
+echo go1.999testmod here!
+-- bin/gofmt --
+echo i am unused
+-- pkg/tool/fake --
diff --git a/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.linux-mips64x.txt b/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.linux-mips64x.txt
new file mode 100644 (file)
index 0000000..79fff13
--- /dev/null
@@ -0,0 +1,14 @@
+golang.org/toolchain@v0.0.1-go1.999testmod.linux-mips64x
+
+-- .mod --
+module golang.org/toolchain
+-- .info --
+{"Version":"v0.0.1-go1.999testmod.linux-mips64x"}
+-- go.mod --
+module golang.org/toolchain
+-- bin/go --
+#!/bin/sh
+echo go1.999testmod here!
+-- bin/gofmt --
+echo i am unused
+-- pkg/tool/fake --
diff --git a/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.linux-mipsx.txt b/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.linux-mipsx.txt
new file mode 100644 (file)
index 0000000..a725626
--- /dev/null
@@ -0,0 +1,14 @@
+golang.org/toolchain@v0.0.1-go1.999testmod.linux-mipsx
+
+-- .mod --
+module golang.org/toolchain
+-- .info --
+{"Version":"v0.0.1-go1.999testmod.linux-mipsx"}
+-- go.mod --
+module golang.org/toolchain
+-- bin/go --
+#!/bin/sh
+echo go1.999testmod here!
+-- bin/gofmt --
+echo i am unused
+-- pkg/tool/fake --
diff --git a/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.linux-ppc64.txt b/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.linux-ppc64.txt
new file mode 100644 (file)
index 0000000..f25ae8e
--- /dev/null
@@ -0,0 +1,14 @@
+golang.org/toolchain@v0.0.1-go1.999testmod.linux-ppc64
+
+-- .mod --
+module golang.org/toolchain
+-- .info --
+{"Version":"v0.0.1-go1.999testmod.linux-ppc64"}
+-- go.mod --
+module golang.org/toolchain
+-- bin/go --
+#!/bin/sh
+echo go1.999testmod here!
+-- bin/gofmt --
+echo i am unused
+-- pkg/tool/fake --
diff --git a/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.linux-ppc64le.txt b/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.linux-ppc64le.txt
new file mode 100644 (file)
index 0000000..e22b8ee
--- /dev/null
@@ -0,0 +1,14 @@
+golang.org/toolchain@v0.0.1-go1.999testmod.linux-ppc64le
+
+-- .mod --
+module golang.org/toolchain
+-- .info --
+{"Version":"v0.0.1-go1.999testmod.linux-ppc64le"}
+-- go.mod --
+module golang.org/toolchain
+-- bin/go --
+#!/bin/sh
+echo go1.999testmod here!
+-- bin/gofmt --
+echo i am unused
+-- pkg/tool/fake --
diff --git a/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.linux-riscv64.txt b/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.linux-riscv64.txt
new file mode 100644 (file)
index 0000000..2e15fe3
--- /dev/null
@@ -0,0 +1,14 @@
+golang.org/toolchain@v0.0.1-go1.999testmod.linux-riscv64
+
+-- .mod --
+module golang.org/toolchain
+-- .info --
+{"Version":"v0.0.1-go1.999testmod.linux-riscv64"}
+-- go.mod --
+module golang.org/toolchain
+-- bin/go --
+#!/bin/sh
+echo go1.999testmod here!
+-- bin/gofmt --
+echo i am unused
+-- pkg/tool/fake --
diff --git a/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.linux-s390x.txt b/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.linux-s390x.txt
new file mode 100644 (file)
index 0000000..1022ee4
--- /dev/null
@@ -0,0 +1,14 @@
+golang.org/toolchain@v0.0.1-go1.999testmod.linux-s390x
+
+-- .mod --
+module golang.org/toolchain
+-- .info --
+{"Version":"v0.0.1-go1.999testmod.linux-s390x"}
+-- go.mod --
+module golang.org/toolchain
+-- bin/go --
+#!/bin/sh
+echo go1.999testmod here!
+-- bin/gofmt --
+echo i am unused
+-- pkg/tool/fake --
diff --git a/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.netbsd-386.txt b/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.netbsd-386.txt
new file mode 100644 (file)
index 0000000..8b7b156
--- /dev/null
@@ -0,0 +1,14 @@
+golang.org/toolchain@v0.0.1-go1.999testmod.netbsd-386
+
+-- .mod --
+module golang.org/toolchain
+-- .info --
+{"Version":"v0.0.1-go1.999testmod.netbsd-386"}
+-- go.mod --
+module golang.org/toolchain
+-- bin/go --
+#!/bin/sh
+echo go1.999testmod here!
+-- bin/gofmt --
+echo i am unused
+-- pkg/tool/fake --
diff --git a/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.netbsd-amd64.txt b/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.netbsd-amd64.txt
new file mode 100644 (file)
index 0000000..ebdb407
--- /dev/null
@@ -0,0 +1,14 @@
+golang.org/toolchain@v0.0.1-go1.999testmod.netbsd-amd64
+
+-- .mod --
+module golang.org/toolchain
+-- .info --
+{"Version":"v0.0.1-go1.999testmod.netbsd-amd64"}
+-- go.mod --
+module golang.org/toolchain
+-- bin/go --
+#!/bin/sh
+echo go1.999testmod here!
+-- bin/gofmt --
+echo i am unused
+-- pkg/tool/fake --
diff --git a/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.netbsd-arm.txt b/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.netbsd-arm.txt
new file mode 100644 (file)
index 0000000..fcacf08
--- /dev/null
@@ -0,0 +1,14 @@
+golang.org/toolchain@v0.0.1-go1.999testmod.netbsd-arm
+
+-- .mod --
+module golang.org/toolchain
+-- .info --
+{"Version":"v0.0.1-go1.999testmod.netbsd-arm"}
+-- go.mod --
+module golang.org/toolchain
+-- bin/go --
+#!/bin/sh
+echo go1.999testmod here!
+-- bin/gofmt --
+echo i am unused
+-- pkg/tool/fake --
diff --git a/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.netbsd-arm64.txt b/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.netbsd-arm64.txt
new file mode 100644 (file)
index 0000000..c2bd257
--- /dev/null
@@ -0,0 +1,14 @@
+golang.org/toolchain@v0.0.1-go1.999testmod.netbsd-arm64
+
+-- .mod --
+module golang.org/toolchain
+-- .info --
+{"Version":"v0.0.1-go1.999testmod.netbsd-arm64"}
+-- go.mod --
+module golang.org/toolchain
+-- bin/go --
+#!/bin/sh
+echo go1.999testmod here!
+-- bin/gofmt --
+echo i am unused
+-- pkg/tool/fake --
diff --git a/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.openbsd-386.txt b/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.openbsd-386.txt
new file mode 100644 (file)
index 0000000..965a054
--- /dev/null
@@ -0,0 +1,14 @@
+golang.org/toolchain@v0.0.1-go1.999testmod.openbsd-386
+
+-- .mod --
+module golang.org/toolchain
+-- .info --
+{"Version":"v0.0.1-go1.999testmod.openbsd-386"}
+-- go.mod --
+module golang.org/toolchain
+-- bin/go --
+#!/bin/sh
+echo go1.999testmod here!
+-- bin/gofmt --
+echo i am unused
+-- pkg/tool/fake --
diff --git a/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.openbsd-amd64.txt b/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.openbsd-amd64.txt
new file mode 100644 (file)
index 0000000..1acb7a3
--- /dev/null
@@ -0,0 +1,14 @@
+golang.org/toolchain@v0.0.1-go1.999testmod.openbsd-amd64
+
+-- .mod --
+module golang.org/toolchain
+-- .info --
+{"Version":"v0.0.1-go1.999testmod.openbsd-amd64"}
+-- go.mod --
+module golang.org/toolchain
+-- bin/go --
+#!/bin/sh
+echo go1.999testmod here!
+-- bin/gofmt --
+echo i am unused
+-- pkg/tool/fake --
diff --git a/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.openbsd-arm.txt b/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.openbsd-arm.txt
new file mode 100644 (file)
index 0000000..0e47d9c
--- /dev/null
@@ -0,0 +1,14 @@
+golang.org/toolchain@v0.0.1-go1.999testmod.openbsd-arm
+
+-- .mod --
+module golang.org/toolchain
+-- .info --
+{"Version":"v0.0.1-go1.999testmod.openbsd-arm"}
+-- go.mod --
+module golang.org/toolchain
+-- bin/go --
+#!/bin/sh
+echo go1.999testmod here!
+-- bin/gofmt --
+echo i am unused
+-- pkg/tool/fake --
diff --git a/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.openbsd-arm64.txt b/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.openbsd-arm64.txt
new file mode 100644 (file)
index 0000000..8c99161
--- /dev/null
@@ -0,0 +1,14 @@
+golang.org/toolchain@v0.0.1-go1.999testmod.openbsd-arm64
+
+-- .mod --
+module golang.org/toolchain
+-- .info --
+{"Version":"v0.0.1-go1.999testmod.openbsd-arm64"}
+-- go.mod --
+module golang.org/toolchain
+-- bin/go --
+#!/bin/sh
+echo go1.999testmod here!
+-- bin/gofmt --
+echo i am unused
+-- pkg/tool/fake --
diff --git a/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.openbsd-mips64.txt b/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.openbsd-mips64.txt
new file mode 100644 (file)
index 0000000..6c7cdfb
--- /dev/null
@@ -0,0 +1,14 @@
+golang.org/toolchain@v0.0.1-go1.999testmod.openbsd-mips64
+
+-- .mod --
+module golang.org/toolchain
+-- .info --
+{"Version":"v0.0.1-go1.999testmod.openbsd-mips64"}
+-- go.mod --
+module golang.org/toolchain
+-- bin/go --
+#!/bin/sh
+echo go1.999testmod here!
+-- bin/gofmt --
+echo i am unused
+-- pkg/tool/fake --
diff --git a/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.plan9-386.txt b/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.plan9-386.txt
new file mode 100644 (file)
index 0000000..26f7209
--- /dev/null
@@ -0,0 +1,14 @@
+golang.org/toolchain@v0.0.1-go1.999testmod.plan9-386
+
+-- .mod --
+module golang.org/toolchain
+-- .info --
+{"Version":"v0.0.1-go1.999testmod.plan9-386"}
+-- go.mod --
+module golang.org/toolchain
+-- bin/go --
+#!/bin/rc
+echo go1.999testmod here!
+-- bin/gofmt --
+echo i am unused
+-- pkg/tool/fake --
diff --git a/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.plan9-amd64.txt b/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.plan9-amd64.txt
new file mode 100644 (file)
index 0000000..7cf1dde
--- /dev/null
@@ -0,0 +1,14 @@
+golang.org/toolchain@v0.0.1-go1.999testmod.plan9-amd64
+
+-- .mod --
+module golang.org/toolchain
+-- .info --
+{"Version":"v0.0.1-go1.999testmod.plan9-amd64"}
+-- go.mod --
+module golang.org/toolchain
+-- bin/go --
+#!/bin/rc
+echo go1.999testmod here!
+-- bin/gofmt --
+echo i am unused
+-- pkg/tool/fake --
diff --git a/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.plan9-arm.txt b/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.plan9-arm.txt
new file mode 100644 (file)
index 0000000..3c3b6a7
--- /dev/null
@@ -0,0 +1,14 @@
+golang.org/toolchain@v0.0.1-go1.999testmod.plan9-arm
+
+-- .mod --
+module golang.org/toolchain
+-- .info --
+{"Version":"v0.0.1-go1.999testmod.plan9-arm"}
+-- go.mod --
+module golang.org/toolchain
+-- bin/go --
+#!/bin/rc
+echo go1.999testmod here!
+-- bin/gofmt --
+echo i am unused
+-- pkg/tool/fake --
diff --git a/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.solaris-amd64.txt b/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.solaris-amd64.txt
new file mode 100644 (file)
index 0000000..a750aaf
--- /dev/null
@@ -0,0 +1,14 @@
+golang.org/toolchain@v0.0.1-go1.999testmod.solaris-amd64
+
+-- .mod --
+module golang.org/toolchain
+-- .info --
+{"Version":"v0.0.1-go1.999testmod.solaris-amd64"}
+-- go.mod --
+module golang.org/toolchain
+-- bin/go --
+#!/bin/sh
+echo go1.999testmod here!
+-- bin/gofmt --
+echo i am unused
+-- pkg/tool/fake --
diff --git a/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.windows-386.txt b/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.windows-386.txt
new file mode 100644 (file)
index 0000000..ca0f7aa
--- /dev/null
@@ -0,0 +1,10 @@
+golang.org/toolchain@v0.0.1-go1.999testmod.windows-386
+
+-- .mod --
+module golang.org/toolchain
+-- .info --
+{"Version":"v0.0.1-go1.999testmod.windows-386"}
+-- go.mod --
+module golang.org/toolchain
+-- bin/go.bat --
+@echo go1.999testmod here!
diff --git a/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.windows-amd64.txt b/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.windows-amd64.txt
new file mode 100644 (file)
index 0000000..44e16c7
--- /dev/null
@@ -0,0 +1,10 @@
+golang.org/toolchain@v0.0.1-go1.999testmod.windows-amd64
+
+-- .mod --
+module golang.org/toolchain
+-- .info --
+{"Version":"v0.0.1-go1.999testmod.windows-amd64"}
+-- go.mod --
+module golang.org/toolchain
+-- bin/go.bat --
+@echo go1.999testmod here!
diff --git a/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.windows-arm.txt b/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.windows-arm.txt
new file mode 100644 (file)
index 0000000..ee4e016
--- /dev/null
@@ -0,0 +1,10 @@
+golang.org/toolchain@v0.0.1-go1.999testmod.windows-arm
+
+-- .mod --
+module golang.org/toolchain
+-- .info --
+{"Version":"v0.0.1-go1.999testmod.windows-arm"}
+-- go.mod --
+module golang.org/toolchain
+-- bin/go.bat --
+@echo go1.999testmod here!
diff --git a/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.windows-arm64.txt b/src/cmd/go/testdata/mod/golang.org_toolchain_v0.0.1-go1.999testmod.windows-arm64.txt
new file mode 100644 (file)
index 0000000..be3ff80
--- /dev/null
@@ -0,0 +1,10 @@
+golang.org/toolchain@v0.0.1-go1.999testmod.windows-arm64
+
+-- .mod --
+module golang.org/toolchain
+-- .info --
+{"Version":"v0.0.1-go1.999testmod.windows-arm64"}
+-- go.mod --
+module golang.org/toolchain
+-- bin/go.bat --
+@echo go1.999testmod here!
diff --git a/src/cmd/go/testdata/script/gotoolchain.txt b/src/cmd/go/testdata/script/gotoolchain.txt
new file mode 100644 (file)
index 0000000..0b7b29d
--- /dev/null
@@ -0,0 +1,51 @@
+[!GOOS:windows] chmod 0755 $WORK/bin/go1.999testpath
+[!GOOS:plan9] env PATH=$WORK/bin${:}$PATH
+[GOOS:plan9] env path=$WORK/bin${:}$path
+[GOOS:plan9] replace /bin/sh /bin/rc $WORK/bin/go1.999testpath
+
+# Plain go version
+go version
+! stdout 999
+
+# GOTOOLCHAIN from PATH
+env GOTOOLCHAIN=go1.999testpath
+go version
+[!GOOS:windows] stdout 'go1.999testpath here!'
+[GOOS:windows] stdout 'pretend we ran .*go1.999testpath'
+
+# GOTOOLCHAIN from PATH, with forced subprocess
+env GOTOOLCHAIN=go1.999testpath
+env GODEBUG=gotoolchainexec=0
+go version
+[!GOOS:windows] stdout 'go1.999testpath here!'
+[GOOS:windows] stdout 'pretend we ran .*go1.999testpath'
+env GODEBUG=
+
+# GOTOOLCHAIN from network
+env GOTOOLCHAIN=go1.999testmod
+go version
+stderr 'go: downloading go1.999testmod \(.*/.*\)'
+[!GOOS:windows] stdout 'go1.999testmod here!'
+[GOOS:windows] stdout 'pretend we ran .*go1.999testmod.*\\bin\\go'
+
+# GOTOOLCHAIN from network, does not exist
+env GOTOOLCHAIN=go1.9999x
+! go version
+stderr 'go: download go1.9999x for .*: toolchain not available'
+
+-- $WORK/bin/go1.999testpath --
+#!/bin/sh
+echo go1.999testpath here!
+-- $WORK/bin/go1.999testpath.bat --
+This should say:
+       @echo go1.999testpath here!
+but exec.Command does not directly support batch files.
+execGoToolchain in cmd/go/toolchain.go picks off versions
+named go1.999test and instead of running them just runs
+cmd /c "echo pretend we ran <file>".
+
+Since the real toolchain will have an exe file and cmd is an
+exe file, this seems like a good enough test.
+Changing execGoToolchain to use cmd /c to run the batch file
+hangs for unknown reasons.
+
index 78664d7a96ddab14d3baa2cb5b1422c9edcdf535..f4adea2a25ff8efde4a3fca0a7c50e71c1aa5f4b 100644 (file)
@@ -59,6 +59,7 @@ const KnownEnv = `
        GOROOT
        GOSUMDB
        GOTMPDIR
+       GOTOOLCHAIN
        GOTOOLDIR
        GOVCS
        GOWASM