]> Cypherpunks.ru repositories - gostls13.git/commitdiff
flag: exit 0 when -h or -help invoked but undefined
authorShang Jian Ding <sding3@ncsu.edu>
Fri, 3 Apr 2020 00:13:08 +0000 (00:13 +0000)
committerIan Lance Taylor <iant@golang.org>
Fri, 3 Apr 2020 04:24:39 +0000 (04:24 +0000)
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>
doc/go1.15.html
src/flag/flag.go
src/flag/flag_test.go

index c59fc4f151a3b51bee08b9c62c2257ae76da8f7b..d5b583291337ae0ff3df7cb569812c0e85a4c515 100644 (file)
@@ -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 -->
index eb88c1faa8b558d173ea3e026f4682d0e63834cd..286bba687390fee3c272b99b18a67afcef31b08e 100644 (file)
@@ -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)
index 0d9491c02089de4a59d06a8ec4156a956c6588d4..a7450f3f48387e7714444d56865ade1c47caebd7 100644 (file)
@@ -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)
+               }
+       }
+}