aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShang Jian Ding <sding3@ncsu.edu>2020-04-03 00:13:08 +0000
committerIan Lance Taylor <iant@golang.org>2020-04-03 04:24:39 +0000
commitdcf0929de6a12103a8fd7097abd6e797188c366d (patch)
treeacbd8fa6dd75d2fdc5249219f39d5345ec7c4eea
parent041bcb32b59b37ff55ad527083b7bd4ffa4c1a3d (diff)
downloadgo-dcf0929de6a12103a8fd7097abd6e797188c366d.tar.gz
go-dcf0929de6a12103a8fd7097abd6e797188c366d.zip
flag: exit 0 when -h or -help invoked but undefined
flag treats -h or -help as a special case to print a nice help message, but exit with a status code of 2. This update makes that status code 0. Fixes #37533 Change-Id: I7e0bd29944ce46607fb7cfc6740734f7444a151a GitHub-Last-Rev: 83f64d757bc3a9957c49caa5de74d05a96724771 GitHub-Pull-Request: golang/go#37530 Reviewed-on: https://go-review.googlesource.com/c/go/+/221427 Run-TryBot: Ian Lance Taylor <iant@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org>
-rw-r--r--doc/go1.15.html15
-rw-r--r--src/flag/flag.go5
-rw-r--r--src/flag/flag_test.go61
3 files changed, 80 insertions, 1 deletions
diff --git a/doc/go1.15.html b/doc/go1.15.html
index c59fc4f151..d5b5832913 100644
--- a/doc/go1.15.html
+++ b/doc/go1.15.html
@@ -119,6 +119,21 @@ TODO
TODO
</p>
+<dl id="flag"><dt><a href="/pkg/flag/">flag</a></dt>
+ <dd>
+ <p><!-- CL 221427 -->
+ When the flag package sees <code>-h</code> or <code>-help</code>, and
+ those flags are not defined, the flag package prints a usage message.
+ If the <a href=/pkg/flag/#FlagSet><code>FlagSet</code></a> was created with
+ <a href=/pkg/flag/#ExitOnError><code>ExitOnError</code></a>,
+ <a href=/pkg/flag/#FlagSet.Parse><code>FlagSet.Parse</code></a> would then
+ exit with a status of 2. In this release, the exit status for <code>-h</code>
+ or <code>-help</code> has been changed to 0. In particular, this applies to
+ the default handling of command line flags.
+ </p>
+ </dd>
+</dl>
+
<dl id="pkg-runtime"><dt><a href="/pkg/runtime/">runtime</a></dt>
<dd>
<p><!-- CL 221779 -->
diff --git a/src/flag/flag.go b/src/flag/flag.go
index eb88c1faa8..286bba6873 100644
--- a/src/flag/flag.go
+++ b/src/flag/flag.go
@@ -308,7 +308,7 @@ type ErrorHandling int
// These constants cause FlagSet.Parse to behave as described if the parse fails.
const (
ContinueOnError ErrorHandling = iota // Return a descriptive error.
- ExitOnError // Call os.Exit(2).
+ ExitOnError // Call os.Exit(2) or for -h/-help Exit(0).
PanicOnError // Call panic with a descriptive error.
)
@@ -979,6 +979,9 @@ func (f *FlagSet) Parse(arguments []string) error {
case ContinueOnError:
return err
case ExitOnError:
+ if err == ErrHelp {
+ os.Exit(0)
+ }
os.Exit(2)
case PanicOnError:
panic(err)
diff --git a/src/flag/flag_test.go b/src/flag/flag_test.go
index 0d9491c020..a7450f3f48 100644
--- a/src/flag/flag_test.go
+++ b/src/flag/flag_test.go
@@ -8,9 +8,11 @@ import (
"bytes"
. "flag"
"fmt"
+ "internal/testenv"
"io"
"io/ioutil"
"os"
+ "os/exec"
"sort"
"strconv"
"strings"
@@ -544,3 +546,62 @@ func TestRangeError(t *testing.T) {
}
}
}
+
+func TestExitCode(t *testing.T) {
+ testenv.MustHaveExec(t)
+
+ magic := 123
+ if os.Getenv("GO_CHILD_FLAG") != "" {
+ fs := NewFlagSet("test", ExitOnError)
+ if os.Getenv("GO_CHILD_FLAG_HANDLE") != "" {
+ var b bool
+ fs.BoolVar(&b, os.Getenv("GO_CHILD_FLAG_HANDLE"), false, "")
+ }
+ fs.Parse([]string{os.Getenv("GO_CHILD_FLAG")})
+ os.Exit(magic)
+ }
+
+ tests := []struct {
+ flag string
+ flagHandle string
+ expectExit int
+ }{
+ {
+ flag: "-h",
+ expectExit: 0,
+ },
+ {
+ flag: "-help",
+ expectExit: 0,
+ },
+ {
+ flag: "-undefined",
+ expectExit: 2,
+ },
+ {
+ flag: "-h",
+ flagHandle: "h",
+ expectExit: magic,
+ },
+ {
+ flag: "-help",
+ flagHandle: "help",
+ expectExit: magic,
+ },
+ }
+
+ for _, test := range tests {
+ cmd := exec.Command(os.Args[0], "-test.run=TestExitCode")
+ cmd.Env = append(
+ os.Environ(),
+ "GO_CHILD_FLAG="+test.flag,
+ "GO_CHILD_FLAG_HANDLE="+test.flagHandle,
+ )
+ cmd.Run()
+ got := cmd.ProcessState.ExitCode()
+ if got != test.expectExit {
+ t.Errorf("unexpected exit code for test case %+v \n: got %d, expect %d",
+ test, got, test.expectExit)
+ }
+ }
+}