}
gotoolchain = minToolchain
- if (mode == "auto" || mode == "path") && !goInstallVersion(minVers) {
+ if mode == "auto" || mode == "path" {
// Read go.mod to find new minimum and suggested toolchain.
file, goVers, toolchain := modGoToolchain()
gover.Startup.AutoFile = file
}
if gover.Compare(goVers, minVers) > 0 {
gotoolchain = "go" + goVers
+ minVers = goVers
// Starting with Go 1.21, the first released version has a .0 patch version suffix.
// Don't try to download a language version (sans patch component), such as go1.22.
// Instead, use the first toolchain of that language version, such as 1.22.0.
}
}
}
+ maybeSwitchForGoInstallVersion(minVers)
}
// If we are invoked as a target toolchain, confirm that
return file, gover.GoModLookup(data, "go"), gover.GoModLookup(data, "toolchain")
}
-// 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(minVers string) bool {
+// maybeSwitchForGoInstallVersion reports whether the command line is go install m@v or go run m@v.
+// If so, switch to the go version required to build m@v if it's higher than minVers.
+func maybeSwitchForGoInstallVersion(minVers string) {
// 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.
if len(os.Args) < 3 {
- return false
+ return
}
var cmdFlags *flag.FlagSet
switch os.Args[1] {
default:
// Command doesn't support a pkg@version as the main module.
- return false
+ return
case "install":
cmdFlags = &work.CmdInstall.Flag
case "run":
args = args[1:]
if a == "--" {
if len(args) == 0 {
- return false
+ return
}
pkgArg = args[0]
break
val = "true"
}
if err := modcacherwVal.Set(val); err != nil {
- return false
+ return
}
modcacherwSeen = true
continue
// because it is preceded by run flags and followed by arguments to the
// program being run. Since we don't know whether this flag takes
// an argument, we can't reliably identify the end of the run flags.
- // Just give up and let the user clarify using the "=" form..
- return false
+ // Just give up and let the user clarify using the "=" form.
+ return
}
// We would like to let 'go install -newflag pkg@version' work even
}
if !strings.Contains(pkgArg, "@") || build.IsLocalImport(pkgArg) || filepath.IsAbs(pkgArg) {
- return false
+ return
}
path, version, _ := strings.Cut(pkgArg, "@")
if path == "" || version == "" || gover.IsToolchain(path) {
- return false
+ return
}
if !modcacherwSeen && base.InGOFLAGS("-modcacherw") {
base.SetFromGOFLAGS(fs)
}
- // It would be correct to simply return true here, bypassing use
- // of the current go.mod or go.work, and let "go run" or "go install"
- // do the rest, including a toolchain switch.
+ // It would be correct to do nothing here, and let "go run" or "go install"
+ // do the toolchain switch.
// Our goal instead is, since we have gone to the trouble of handling
// unknown flags to some degree, to run the switch now, so that
// these commands can switch to a newer toolchain directed by the
SwitchOrFatal(ctx, err)
}
}
-
- return true // pkg@version found
}
go version
stdout go1.501
+go mod edit -go=1.21
+
# 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
! 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
+# go install m@v and go run m@v should use the go directive from m@v,
+# or the go directive in go.mod, whichever is higher.
env TESTGO_VERSION=go1.2.3
-go mod edit -go=1.999 -toolchain=go1.998
+go mod edit -go=1.1.1 -toolchain=go1.1.1
! go install rsc.io/fortune/nonexist@v0.0.1
stderr '^go: rsc.io/fortune@v0.0.1 requires go >= 1.21rc999; switching to go1.22.9$'
+! stderr 'upgrading toolchain'
stderr '^go: rsc.io/fortune/nonexist@v0.0.1: module rsc.io/fortune@v0.0.1 found, but does not contain package rsc.io/fortune/nonexist'
! go run rsc.io/fortune/nonexist@v0.0.1
stderr '^go: rsc.io/fortune@v0.0.1 requires go >= 1.21rc999; switching to go1.22.9$'
+! stderr 'upgrading toolchain'
+stderr '^go: rsc.io/fortune/nonexist@v0.0.1: module rsc.io/fortune@v0.0.1 found, but does not contain package rsc.io/fortune/nonexist'
+
+go mod edit -go=1.23rc1 -toolchain=go1.1.1
+
+! go install rsc.io/fortune/nonexist@v0.0.1
+stderr '^go: upgrading toolchain to go1.23rc1 \(required by go line in go.mod; upgrade allowed by GOTOOLCHAIN=auto\)'
+! stderr 'switching to'
stderr '^go: rsc.io/fortune/nonexist@v0.0.1: module rsc.io/fortune@v0.0.1 found, but does not contain package rsc.io/fortune/nonexist'
+! go run rsc.io/fortune/nonexist@v0.0.1
+stderr '^go: upgrading toolchain to go1.23rc1 \(required by go line in go.mod; upgrade allowed by GOTOOLCHAIN=auto\)'
+! stderr 'switching to'
+stderr '^go: rsc.io/fortune/nonexist@v0.0.1: module rsc.io/fortune@v0.0.1 found, but does not contain package rsc.io/fortune/nonexist'
+
+go mod edit -go=1.23rc1 -toolchain=go1.998
+
+! go install rsc.io/fortune/nonexist@v0.0.1
+stderr '^go: upgrading toolchain to go1.998 \(required by toolchain line in go.mod; upgrade allowed by GOTOOLCHAIN=auto\)'
+! stderr 'switching to'
+stderr '^go: rsc.io/fortune/nonexist@v0.0.1: module rsc.io/fortune@v0.0.1 found, but does not contain package rsc.io/fortune/nonexist'
+
+! go run rsc.io/fortune/nonexist@v0.0.1
+stderr '^go: upgrading toolchain to go1.998 \(required by toolchain line in go.mod; upgrade allowed by GOTOOLCHAIN=auto\)'
+! stderr 'switching to'
+stderr '^go: rsc.io/fortune/nonexist@v0.0.1: module rsc.io/fortune@v0.0.1 found, but does not contain package rsc.io/fortune/nonexist'
+
+go mod edit -go=1.1.1 -toolchain=go1.1.1
+
# go install should handle unknown flags to find m@v
! go install -unknownflag rsc.io/fortune/nonexist@v0.0.1
stderr '^go: rsc.io/fortune@v0.0.1 requires go >= 1.21rc999; switching to go1.22.9$'
stderr '^go: rsc.io/fortune@v0.0.1 requires go >= 1.21rc999; switching to go1.22.9$'
stderr '^flag provided but not defined: -unknownflag'
+env GODEBUG=
+
# go run cannot handle unknown boolean flags
! go run -unknownflag rsc.io/fortune/nonexist@v0.0.1
! stderr switching