cmd/go: add go1.24 requirement when running go get with tools

Based on CL 762260 by Olivier Mengué

When adding a tool (go get -tool), add in go.mod a requirement
for a toolchain >= go1.24.0.

When removing tools, add go 1.24.0 requirement if a tool directive will
remain after changes.

When upgrading/downgrading the go version or toolchain version (either
explicitely or via adding a dependency), check if a tool directive will
remain and enforce go1.24.0 requirement:
- if an older go version is explicitely requested, fail
- else upgrade go to 1.24.0 and remove older toolchain directive

Fixes #74739

Change-Id: I7001529ecd15d87bbaad0c4b6aef7b676a6a6964
Reviewed-on: https://go-review.googlesource.com/c/go/+/763140
Reviewed-by: Olivier Mengué <olivier.mengue@gmail.com>
LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Sean Liao <sean@liao.dev>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Auto-Submit: Michael Matloob <matloob@golang.org>
Reviewed-by: Michael Matloob <matloob@google.com>
This commit is contained in:
Olivier Mengué 2026-03-26 09:08:22 +01:00 committed by Gopher Robot
parent 60eb90e6b0
commit a221442229
3 changed files with 66 additions and 1 deletions

View file

@ -57,6 +57,10 @@ const (
// ExplicitModulesTxtImportVersion is the Go version at which vendored packages need to be present
// in modules.txt to be imported.
ExplicitModulesTxtImportVersion = "1.23"
// GoModToolVersion is the Go version required for the tool
// directive in go.mod.
GoModToolVersion = "1.24"
)
// FromGoMod returns the go version from the go.mod file.

View file

@ -1944,10 +1944,31 @@ func UpdateGoModFromReqs(ld *Loader, ctx context.Context, opts WriteOpts) (befor
forceGoStmt(modFile, mainModule, goVersion)
}
}
// Add Go 1.24 requirement if we're running go get and there are tool directives.
tools := map[string]bool{}
for _, t := range modFile.Tool {
tools[t.Path] = true
}
for _, t := range opts.DropTools {
delete(tools, t)
}
for _, t := range opts.AddTools {
tools[t] = true
}
if len(tools) > 0 && gover.Compare(goVersion, gover.GoModToolVersion) < 0 && cfg.CmdName == "get" {
if opts.ExplicitToolchain {
return nil, nil, nil, errors.New(gover.GoModToolVersion + " is required for tool directives in go.mod: go get go@" + gover.GoModToolVersion + ".0")
}
// TODO: If we start enforcing that the go version is > 1.24 on modules
// that have tool directives, add a requirement instead of calling forceGoStmt.
goVersion = gover.GoModToolVersion
forceGoStmt(modFile, mainModule, gover.GoModToolVersion)
}
if toolchain == "" {
toolchain = "go" + goVersion
}
toolVers := gover.FromToolchain(toolchain)
if opts.DropToolchain || toolchain == "go"+goVersion || (gover.Compare(toolVers, gover.GoStrictVersion) < 0 && !opts.ExplicitToolchain) {
// go get toolchain@none or toolchain matches go line or isn't valid; drop it.

View file

@ -0,0 +1,40 @@
# Adding a tool upgrades the toolchain to 1.24.0 because older go
# versions fail to parse the tool directive. Issue #74739.
cp go.mod.go1.23.0 go.mod
go get -tool ./mytool
stderr 'go: upgraded go 1.23.0 => 1.24'
cmp go.mod go.mod.go1.24
go mod tidy
cmp go.mod go.mod.go1.24
# No toolchain change if go >= 1.24.0
cp go.mod.go1.24 go.mod
cmp go.mod go.mod.go1.24
go get -tool ./mytool
cmp go.mod go.mod.go1.24
go mod tidy
cmp go.mod go.mod.go1.24
# TODO(#78550): If #78550 is approved, go build should reject
# the go.mod file if go < 1.24 but there is a tool directive.
# For now, we will let it through.
cp go.mod.go1.23.0 go.mod
go list ./mytool
go build -n ./mytool
-- go.mod.go1.23.0 --
module m
go 1.23.0
tool m/mytool
-- go.mod.go1.24 --
module m
go 1.24
tool m/mytool
-- mytool/mytool.go --
package mytool
func main() {}