Skip to content

Commit

Permalink
flag: exit 0 when -h or -help invoked but undefined
Browse files Browse the repository at this point in the history
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: 83f64d7
GitHub-Pull-Request: #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>
  • Loading branch information
sding3 authored and ianlancetaylor committed Apr 3, 2020
1 parent 041bcb3 commit dcf0929
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 1 deletion.
15 changes: 15 additions & 0 deletions doc/go1.15.html
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,21 @@ <h3 id="minor_library_changes">Minor changes to the library</h3>
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 -->
Expand Down
5 changes: 4 additions & 1 deletion src/flag/flag.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
)

Expand Down Expand Up @@ -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)
Expand Down
61 changes: 61 additions & 0 deletions src/flag/flag_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ import (
"bytes"
. "flag"
"fmt"
"internal/testenv"
"io"
"io/ioutil"
"os"
"os/exec"
"sort"
"strconv"
"strings"
Expand Down Expand Up @@ -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)
}
}
}

0 comments on commit dcf0929

Please sign in to comment.