From fbf844b46d147c442a6016aa9c6bef51c309257b Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Thu, 13 May 2021 09:48:40 -0400 Subject: [release-branch.go1.15] cmd/go: error out of 'go mod tidy' if the go version is newer than supported MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This backports the test from CL 319669, but — because of extensive changes to the module loader during the Go 1.16 and 1.17 cycles — the implementation is entirely different. (This implementation is based on the addGoStmt function already present in init.go.) Fixes #46143 Updates #46142 Change-Id: Ib7a0a159e53cbe476be6aa9a050add10cc750dec Reviewed-on: https://go-review.googlesource.com/c/go/+/319710 Trust: Bryan C. Mills Run-TryBot: Bryan C. Mills Reviewed-by: Jay Conrod TryBot-Result: Go Bot --- src/cmd/go/internal/modcmd/tidy.go | 1 + src/cmd/go/internal/modload/load.go | 27 +++++++++++++++++++++ src/cmd/go/testdata/script/mod_tidy_too_new.txt | 31 +++++++++++++++++++++++++ 3 files changed, 59 insertions(+) create mode 100644 src/cmd/go/testdata/script/mod_tidy_too_new.txt diff --git a/src/cmd/go/internal/modcmd/tidy.go b/src/cmd/go/internal/modcmd/tidy.go index 5ff847485cb..71e1eda44af 100644 --- a/src/cmd/go/internal/modcmd/tidy.go +++ b/src/cmd/go/internal/modcmd/tidy.go @@ -43,6 +43,7 @@ func runTidy(cmd *base.Command, args []string) { } modload.SilenceMissingStdImports = true + modload.CheckTidyVersion() modload.LoadALL() modload.TidyBuildList() modTidyGoSum() // updates memory copy; WriteGoMod on next line flushes it out diff --git a/src/cmd/go/internal/modload/load.go b/src/cmd/go/internal/modload/load.go index e5ea1a6c238..0dea6ee636b 100644 --- a/src/cmd/go/internal/modload/load.go +++ b/src/cmd/go/internal/modload/load.go @@ -24,7 +24,9 @@ import ( "sort" "strings" + "golang.org/x/mod/modfile" "golang.org/x/mod/module" + "golang.org/x/mod/semver" ) // buildList is the list of modules to use for building packages. @@ -478,6 +480,31 @@ func SetBuildList(list []module.Version) { buildList = append([]module.Version{}, list...) } +// CheckTidyVersion reports an error to stderr if the Go version indicated by +// the go.mod file is not supported by this version of the 'go' command. +// +// If allowError is false, such an error terminates the program. +func CheckTidyVersion() { + InitMod() + mf := ModFile() + if mf.Go == nil || mf.Go.Version == "" { + return + } + goVersionV := "v" + mf.Go.Version + + tags := build.Default.ReleaseTags + maxGo := tags[len(tags)-1] + if !strings.HasPrefix(maxGo, "go") || !modfile.GoVersionRE.MatchString(maxGo[2:]) { + base.Fatalf("go: unrecognized go version %q", maxGo) + } + max := maxGo[2:] + + if semver.Compare(goVersionV, "v"+max) > 0 { + have := goVersionV[1:] + base.Fatalf("go mod tidy: go.mod file indicates go %s, but maximum supported version is %s\n", have, max) + } +} + // TidyBuildList trims the build list to the minimal requirements needed to // retain the same versions of all packages from the preceding Load* or // ImportPaths* call. diff --git a/src/cmd/go/testdata/script/mod_tidy_too_new.txt b/src/cmd/go/testdata/script/mod_tidy_too_new.txt new file mode 100644 index 00000000000..8a73c28cbb8 --- /dev/null +++ b/src/cmd/go/testdata/script/mod_tidy_too_new.txt @@ -0,0 +1,31 @@ +# https://golang.org/issue/46142: 'go mod tidy' should error out if the version +# in the go.mod file is newer than the most recent supported version. + +cp go.mod go.mod.orig + + +# If the go.mod file specifies an unsupported Go version, 'go mod tidy' should +# refuse to edit it: we don't know what a tidy go.mod file for that version +# would look like. + +! go mod tidy +stderr 'go mod tidy: go.mod file indicates go 2000.0, but maximum supported version is '$goversion'$' +cmp go.mod go.mod.orig + + +-- go.mod -- +module example.net/from/the/future + +go 2000.0 + +replace example.net/m v0.0.0 => ./m +-- x.go -- +package x + +import "example.net/m" +-- m/go.mod -- +module example.net/m + +go 1.17 +-- m/m.go -- +package m -- cgit v1.2.3-54-g00ecf