]> Cypherpunks.ru repositories - gostls13.git/commitdiff
cmd/go/internal/modcmd: factor out a type for flags whose arguments are Go versions
authorBryan C. Mills <bcmills@google.com>
Sat, 15 May 2021 03:14:22 +0000 (23:14 -0400)
committerBryan C. Mills <bcmills@google.com>
Mon, 24 May 2021 15:03:10 +0000 (15:03 +0000)
For #46141
Updates #45094

Change-Id: I6553600c69273762a81795ef021c66f4e0872b6b
Reviewed-on: https://go-review.googlesource.com/c/go/+/321069
Trust: Bryan C. Mills <bcmills@google.com>
Run-TryBot: Bryan C. Mills <bcmills@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Jay Conrod <jayconrod@google.com>
src/cmd/go/internal/modcmd/edit.go
src/cmd/go/internal/modcmd/tidy.go
src/cmd/go/internal/modload/init.go
src/cmd/go/internal/modload/load.go
src/cmd/go/internal/modload/modfile.go
src/cmd/go/testdata/script/mod_tidy_version.txt

index 79a93ca44b916edbd91bd169542caa5f0434bb89..e856e7c6304d338ab8ea8a49183958acb9fadc01 100644 (file)
@@ -196,7 +196,7 @@ func runEdit(ctx context.Context, cmd *base.Command, args []string) {
 
        if *editGo != "" {
                if !modfile.GoVersionRE.MatchString(*editGo) {
-                       base.Fatalf(`go mod: invalid -go option; expecting something like "-go 1.12"`)
+                       base.Fatalf(`go mod: invalid -go option; expecting something like "-go %s"`, modload.LatestGoVersion())
                }
        }
 
index c72ec30a57287eda2e0755772055463f55575b16..9af624028a39c3864ebd56ab8451dc1eece2f9ec 100644 (file)
@@ -12,8 +12,10 @@ import (
        "cmd/go/internal/imports"
        "cmd/go/internal/modload"
        "context"
+       "fmt"
 
        "golang.org/x/mod/modfile"
+       "golang.org/x/mod/semver"
 )
 
 var cmdTidy = &base.Command{
@@ -44,28 +46,48 @@ See https://golang.org/ref/mod#go-mod-tidy for more about 'go mod tidy'.
 }
 
 var (
-       tidyE  bool   // if true, report errors but proceed anyway.
-       tidyGo string // go version to write to the tidied go.mod file (toggles lazy loading)
+       tidyE  bool          // if true, report errors but proceed anyway.
+       tidyGo goVersionFlag // go version to write to the tidied go.mod file (toggles lazy loading)
 )
 
 func init() {
        cmdTidy.Flag.BoolVar(&cfg.BuildV, "v", false, "")
        cmdTidy.Flag.BoolVar(&tidyE, "e", false, "")
-       cmdTidy.Flag.StringVar(&tidyGo, "go", "", "")
+       cmdTidy.Flag.Var(&tidyGo, "go", "")
        base.AddModCommonFlags(&cmdTidy.Flag)
 }
 
+// A goVersionFlag is a flag.Value representing a supported Go version.
+//
+// (Note that the -go argument to 'go mod edit' is *not* a goVersionFlag.
+// It intentionally allows newer-than-supported versions as arguments.)
+type goVersionFlag struct {
+       v string
+}
+
+func (f *goVersionFlag) String() string   { return f.v }
+func (f *goVersionFlag) Get() interface{} { return f.v }
+
+func (f *goVersionFlag) Set(s string) error {
+       if s != "" {
+               latest := modload.LatestGoVersion()
+               if !modfile.GoVersionRE.MatchString(s) {
+                       return fmt.Errorf("expecting a Go version like %q", latest)
+               }
+               if semver.Compare("v"+s, "v"+latest) > 0 {
+                       return fmt.Errorf("maximum supported Go version is %s", latest)
+               }
+       }
+
+       f.v = s
+       return nil
+}
+
 func runTidy(ctx context.Context, cmd *base.Command, args []string) {
        if len(args) > 0 {
                base.Fatalf("go mod tidy: no arguments allowed")
        }
 
-       if tidyGo != "" {
-               if !modfile.GoVersionRE.MatchString(tidyGo) {
-                       base.Fatalf(`go mod: invalid -go option %q; expecting something like "-go 1.17"`, tidyGo)
-               }
-       }
-
        // Tidy aims to make 'go test' reproducible for any package in 'all', so we
        // need to include test dependencies. For modules that specify go 1.15 or
        // earlier this is a no-op (because 'all' saturates transitive test
@@ -80,7 +102,7 @@ func runTidy(ctx context.Context, cmd *base.Command, args []string) {
        modload.RootMode = modload.NeedRoot
 
        modload.LoadPackages(ctx, modload.PackageOpts{
-               GoVersion:                tidyGo,
+               GoVersion:                tidyGo.String(),
                Tags:                     imports.AnyTags(),
                Tidy:                     true,
                VendorModulesInGOROOTSrc: true,
index 5cdea12cd3e2be5eebbe414dc1948f44f98e802f..e358230e74887112e5459eda6c2d71d50204f97c 100644 (file)
@@ -405,7 +405,7 @@ func loadModFile(ctx context.Context) (rs *Requirements, needCommit bool) {
        if modRoot == "" {
                Target = module.Version{Path: "command-line-arguments"}
                targetPrefix = "command-line-arguments"
-               goVersion := latestGoVersion()
+               goVersion := LatestGoVersion()
                rawGoVersion.Store(Target, goVersion)
                requirements = newRequirements(modDepthFromGoVersion(goVersion), nil, nil)
                return requirements, false
@@ -448,7 +448,7 @@ func loadModFile(ctx context.Context) (rs *Requirements, needCommit bool) {
                // TODO(#45551): Do something more principled instead of checking
                // cfg.CmdName directly here.
                if cfg.BuildMod == "mod" && cfg.CmdName != "mod graph" && cfg.CmdName != "mod why" {
-                       addGoStmt(latestGoVersion())
+                       addGoStmt(LatestGoVersion())
                        if go117EnableLazyLoading {
                                // We need to add a 'go' version to the go.mod file, but we must assume
                                // that its existing contents match something between Go 1.11 and 1.16.
@@ -500,7 +500,7 @@ func CreateModFile(ctx context.Context, modPath string) {
        modFile = new(modfile.File)
        modFile.AddModuleStmt(modPath)
        initTarget(modFile.Module.Mod)
-       addGoStmt(latestGoVersion()) // Add the go directive before converted module requirements.
+       addGoStmt(LatestGoVersion()) // Add the go directive before converted module requirements.
 
        convertedFrom, err := convertLegacyConfig(modPath)
        if convertedFrom != "" {
@@ -793,9 +793,9 @@ func addGoStmt(v string) {
        rawGoVersion.Store(Target, v)
 }
 
-// latestGoVersion returns the latest version of the Go language supported by
+// LatestGoVersion returns the latest version of the Go language supported by
 // this toolchain, like "1.17".
-func latestGoVersion() string {
+func LatestGoVersion() string {
        tags := build.Default.ReleaseTags
        version := tags[len(tags)-1]
        if !strings.HasPrefix(version, "go") || !modfile.GoVersionRE.MatchString(version[2:]) {
index 83fc7c09c37ad07c2a3d686dd3c774205ad699ee..23ee3824f3126f60607bf8b0a746e9a8ae7c6d60 100644 (file)
@@ -931,8 +931,8 @@ func loadFromRoots(ctx context.Context, params loaderParams) *loader {
                        ld.allClosesOverTests = true
                }
 
-               if ld.Tidy && semver.Compare(goVersionV, "v"+latestGoVersion()) > 0 {
-                       ld.errorf("go mod tidy: go.mod file indicates go %s, but maximum supported version is %s\n", params.GoVersion, latestGoVersion())
+               if ld.Tidy && semver.Compare(goVersionV, "v"+LatestGoVersion()) > 0 {
+                       ld.errorf("go mod tidy: go.mod file indicates go %s, but maximum supported version is %s\n", params.GoVersion, LatestGoVersion())
                        base.ExitIfErrors()
                }
 
index bafff3e080ebff00808c9751e711b6401597cf0b..a9c3a91d35da2d57bfcbd1b38ee4beb06b03a85b 100644 (file)
@@ -55,7 +55,7 @@ var modFile *modfile.File
 // in modFile are intepreted, or the latest Go version if modFile is nil.
 func modFileGoVersion() string {
        if modFile == nil {
-               return latestGoVersion()
+               return LatestGoVersion()
        }
        if modFile.Go == nil || modFile.Go.Version == "" {
                // The main module necessarily has a go.mod file, and that file lacks a
index 5441d9cc06fc46c2df0e5ca8c3e441816c146948..eaa6ee7b0db06ddea453d9c914911480fdc4c068 100644 (file)
 
 cp go.mod go.mod.orig
 
+
 # An invalid argument should be rejected.
 
 ! go mod tidy -go=bananas
-stderr '^go mod: invalid -go option "bananas"; expecting something like "-go 1.17"$'
+stderr '^invalid value "bananas" for flag -go: expecting a Go version like "'$goversion'"$'
 cmp go.mod go.mod.orig
 
+! go mod tidy -go=0.9
+stderr '^invalid value "0.9" for flag -go: expecting a Go version like "'$goversion'"$'
+
+! go mod tidy -go=2000.0
+stderr '^invalid value "2000.0" for flag -go: maximum supported Go version is '$goversion'$'
+
+
+# Supported versions should change the go.mod file to be tidy according to the
+# indicated version.
 
 go mod tidy -go=1.15
 cmp go.mod go.mod.115