From: Russ Cox Date: Wed, 18 Dec 2024 20:42:48 +0000 (-0500) Subject: cmd/go: fix two-step toolchain upgrade through go install, GOTOOLCHAIN X-Git-Tag: go1.24rc2~6^2~64 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=cb72406c36;p=gostls13.git cmd/go: fix two-step toolchain upgrade through go install, GOTOOLCHAIN If we do one upgrade because of a go install target's go.mod file, we still might need a second upgrade to implement the GOTOOLCHAIN minimum. Instead of allowing a two-step switch (which we were cutting off anyway), skip the first step and go straight to the GOTOOLCHAIN min upgrade. Fixes #69051. Change-Id: I16f060f473574d8b8f84c55fae2fd0cdabc8aa19 Reviewed-on: https://go-review.googlesource.com/c/go/+/637496 Reviewed-by: Michael Matloob LUCI-TryBot-Result: Go LUCI --- diff --git a/src/cmd/go/internal/toolchain/select.go b/src/cmd/go/internal/toolchain/select.go index cbdd7a2418..aeab59519c 100644 --- a/src/cmd/go/internal/toolchain/select.go +++ b/src/cmd/go/internal/toolchain/select.go @@ -169,7 +169,7 @@ func Select() { } gotoolchain = minToolchain - if (mode == "auto" || mode == "path") && !goInstallVersion() { + if (mode == "auto" || mode == "path") && !goInstallVersion(minVers) { // Read go.mod to find new minimum and suggested toolchain. file, goVers, toolchain := modGoToolchain() gover.Startup.AutoFile = file @@ -549,7 +549,7 @@ func modGoToolchain() (file, goVers, toolchain string) { // goInstallVersion reports whether the command line is go install m@v or go run m@v. // If so, Select must not read the go.mod or go.work file in "auto" or "path" mode. -func goInstallVersion() bool { +func goInstallVersion(minVers string) bool { // Note: We assume there are no flags between 'go' and 'install' or 'run'. // During testing there are some debugging flags that are accepted // in that position, but in production go binaries there are not. @@ -708,7 +708,11 @@ func goInstallVersion() bool { if errors.Is(err, gover.ErrTooNew) { // Run early switch, same one go install or go run would eventually do, // if it understood all the command-line flags. - SwitchOrFatal(ctx, err) + var s Switcher + s.Error(err) + if s.TooNew != nil && gover.Compare(s.TooNew.GoVersion, minVers) > 0 { + SwitchOrFatal(ctx, err) + } } return true // pkg@version found diff --git a/src/cmd/go/testdata/script/gotoolchain_local.txt b/src/cmd/go/testdata/script/gotoolchain_local.txt index db7e082db9..8bece6ebd8 100644 --- a/src/cmd/go/testdata/script/gotoolchain_local.txt +++ b/src/cmd/go/testdata/script/gotoolchain_local.txt @@ -197,6 +197,17 @@ go mod edit -go=1.501 -toolchain=none go version stdout go1.501 +# avoid two-step switch, first from install target requirement, then from GOTOOLCHAIN min +# instead, just jump directly to GOTOOLCHAIN min +env TESTGO_VERSION=go1.2.3 +env GODEBUG=toolchaintrace=1 +env GOTOOLCHAIN=go1.23.0+auto +! go install rsc.io/fortune/nonexist@v0.0.1 +! stderr 'switching to go1.22.9' +stderr 'using go1.23.0' +env GODEBUG= +env GOTOOLCHAIN=auto + # go install m@v and go run m@v should ignore go.mod and use m@v env TESTGO_VERSION=go1.2.3 go mod edit -go=1.999 -toolchain=go1.998