Skip to content

Commit

Permalink
cmd/go: fix two-step toolchain upgrade through go install, GOTOOLCHAIN
Browse files Browse the repository at this point in the history
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 golang#69051.

Change-Id: I16f060f473574d8b8f84c55fae2fd0cdabc8aa19
Reviewed-on: https://go-review.googlesource.com/c/go/+/637496
Reviewed-by: Michael Matloob <[email protected]>
LUCI-TryBot-Result: Go LUCI <[email protected]>
  • Loading branch information
rsc committed Dec 19, 2024
1 parent 4f0561f commit cb72406
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 3 deletions.
10 changes: 7 additions & 3 deletions src/cmd/go/internal/toolchain/select.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand Down
11 changes: 11 additions & 0 deletions src/cmd/go/testdata/script/gotoolchain_local.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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/[email protected]
! 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
Expand Down

0 comments on commit cb72406

Please sign in to comment.