]> Cypherpunks repositories - gostls13.git/commitdiff
[release-branch.go1.15] cmd/go: relax version's error on unexpected flags
authorDaniel Martí <mvdan@mvdan.cc>
Thu, 10 Sep 2020 21:53:59 +0000 (22:53 +0100)
committerDmitri Shuralyov <dmitshur@golang.org>
Wed, 7 Oct 2020 20:53:14 +0000 (20:53 +0000)
In https://golang.org/cl/221397 we made commands like "go version -v"
error, since both of the command's flags only make sense when arguments
follow them. Without arguments, the command only reports Go's own
version, and the flags are most likely a mistake.

However, the script below is entirely reasonable:

export GOFLAGS=-v # make all Go commands verbose
go version
go build

After the previous CL, "go version" would error. Instead, only error if
the flag was passed explicitly, and not via GOFLAGS.

The patch does mean that we won't error on "GOFLAGS=-v go version -v",
but that very unlikely false negative is okay. The error is only meant
to help the user not misuse the flags, anyway - it's not a critical
error of any sort.

To reuse inGOFLAGS, we move it to the base package and export it there,
since it's where the rest of the GOFLAGS funcs are.

Fixes #41464.

Change-Id: I74003dd25d94bacf9ac507b5cad778fd65233321
Reviewed-on: https://go-review.googlesource.com/c/go/+/254157
Trust: Daniel Martí <mvdan@mvdan.cc>
Run-TryBot: Daniel Martí <mvdan@mvdan.cc>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Bryan C. Mills <bcmills@google.com>
(cherry picked from commit de0957dc081e1ec49c99a0f37403ceadbaaedf85)
Reviewed-on: https://go-review.googlesource.com/c/go/+/255498
Trust: Bryan C. Mills <bcmills@google.com>
Run-TryBot: Bryan C. Mills <bcmills@google.com>

src/cmd/go/internal/base/goflags.go
src/cmd/go/internal/version/version.go
src/cmd/go/internal/work/init.go
src/cmd/go/testdata/script/version.txt

index 34766134b090ff6e378d965a8232bac72f849224..f29cc3cf9a5d0d7be56a42cd50cc8e2108ccf00a 100644 (file)
@@ -153,3 +153,20 @@ func SetFromGOFLAGS(flags *flag.FlagSet) {
                }
        }
 }
+
+// InGOFLAGS returns whether GOFLAGS contains the given flag, such as "-mod".
+func InGOFLAGS(flag string) bool {
+       for _, goflag := range GOFLAGS() {
+               name := goflag
+               if strings.HasPrefix(name, "--") {
+                       name = name[1:]
+               }
+               if i := strings.Index(name, "="); i >= 0 {
+                       name = name[:i]
+               }
+               if name == flag {
+                       return true
+               }
+       }
+       return false
+}
index ac2ae501552926258ef63261be6fc0d92f8f170d..a5b13653cd6d39ce929f7ea96fc3aa55b2677411 100644 (file)
@@ -53,7 +53,14 @@ var (
 
 func runVersion(cmd *base.Command, args []string) {
        if len(args) == 0 {
-               if *versionM || *versionV {
+               // If any of this command's flags were passed explicitly, error
+               // out, because they only make sense with arguments.
+               //
+               // Don't error if the flags came from GOFLAGS, since that can be
+               // a reasonable use case. For example, imagine GOFLAGS=-v to
+               // turn "verbose mode" on for all Go commands, which should not
+               // break "go version".
+               if (!base.InGOFLAGS("-m") && *versionM) || (!base.InGOFLAGS("-v") && *versionV) {
                        fmt.Fprintf(os.Stderr, "go version: flags can only be used with arguments\n")
                        base.SetExitStatus(2)
                        return
index dad3b10111d0d1d177799849561a0bfd68e94990..c168364cd173a52ba19dee73ebb94383affd31ad 100644 (file)
@@ -254,34 +254,18 @@ func buildModeInit() {
        case "":
                // ok
        case "readonly", "vendor", "mod":
-               if !cfg.ModulesEnabled && !inGOFLAGS("-mod") {
+               if !cfg.ModulesEnabled && !base.InGOFLAGS("-mod") {
                        base.Fatalf("build flag -mod=%s only valid when using modules", cfg.BuildMod)
                }
        default:
                base.Fatalf("-mod=%s not supported (can be '', 'mod', 'readonly', or 'vendor')", cfg.BuildMod)
        }
        if !cfg.ModulesEnabled {
-               if cfg.ModCacheRW && !inGOFLAGS("-modcacherw") {
+               if cfg.ModCacheRW && !base.InGOFLAGS("-modcacherw") {
                        base.Fatalf("build flag -modcacherw only valid when using modules")
                }
-               if cfg.ModFile != "" && !inGOFLAGS("-mod") {
+               if cfg.ModFile != "" && !base.InGOFLAGS("-mod") {
                        base.Fatalf("build flag -modfile only valid when using modules")
                }
        }
 }
-
-func inGOFLAGS(flag string) bool {
-       for _, goflag := range base.GOFLAGS() {
-               name := goflag
-               if strings.HasPrefix(name, "--") {
-                       name = name[1:]
-               }
-               if i := strings.Index(name, "="); i >= 0 {
-                       name = name[:i]
-               }
-               if name == flag {
-                       return true
-               }
-       }
-       return false
-}
index 0123ac6d53f3934fb4ca088e906436317b736ba5..87cb6befe932683733df2faac2270cc8bd3c8950 100644 (file)
@@ -9,6 +9,12 @@ stderr 'with arguments'
 ! go version -v
 stderr 'with arguments'
 
+# Neither of the two flags above should be an issue via GOFLAGS.
+env GOFLAGS='-m -v'
+go version
+stdout '^go version'
+env GOFLAGS=
+
 env GO111MODULE=on
 # Skip the builds below if we are running in short mode.
 [short] skip