lib: Convert all cmdline users to cmdline2.

This also includes changes in cmdline2 to allow commands with
both Children and Runner set, as long as the runner doesn't take
any args.  This makes sense since the runner handles the no-arg
case, while the children handle the with-args case.  This was
already being used by "v23 buildcop" and "deviced", and it seemed
better to allow this behavior.

Also fixed a bug in the cmdline2 package where the "at least one
of Children and Runner" check wasn't returning an error, if the
bad Command wasn't the root.  Added tests for this case.

Finally, but also important, changed how global flags are
handled.  Previously I was hoping we could simply change
"v.io/x/ref/lib/flags" to check flag.Parsed and avoid
double-parsing the flags.  But the previous strategy always
merged flags into a new FlagSet, and then overwrote
flag.CommandLine with that value.  Our usage of ref/lib/flags
stashes the flag.CommandLine pointer away in an init function,
which breaks that strategy.

In addition, ref/lib/flags has some weird logic to set certain
flags to their "default values".  Presumably this was a hack to
deal with double-parsing the flags for flags that are specified
multiple times on the command line, and append their values.
This makes it questionable whether we can really depend on not
double-parsing flags.

I'll look into changing our flags so that they don't depend on
the multi-specification-append behavior, since that's just weird.
But I'll do that separately.

The actual conversions of all programs is mechanical.

MultiPart: 2/3

Change-Id: I3f972421ab0dd2e684a62d68af4bb09b0b6ec5fa
diff --git a/cmdline2/cmdline.go b/cmdline2/cmdline.go
index e56126c..0d829df 100644
--- a/cmdline2/cmdline.go
+++ b/cmdline2/cmdline.go
@@ -58,12 +58,16 @@
 	ArgsName string       // Name of the args, shown in usage line.
 	ArgsLong string       // Long description of the args, shown in help.
 
-	// Children of the command - set for non-leaf commands in the tree.
-	// Exactly one of Children or Runner must be specified.
+	// Children of the command.
 	Children []*Command
 
-	// Runner that runs the command - set for leaf commands in the tree.
+	// Runner that runs the command.
 	// Use RunnerFunc to adapt regular functions into Runners.
+	//
+	// At least one of Children or Runner must be specified.  If both are
+	// specified, ArgsName and ArgsLong must be empty, meaning the Runner doesn't
+	// take any args.  Otherwise there's a possible conflict between child names
+	// and the runner args, and an error is returned from Parse.
 	Runner Runner
 
 	// Topics that provide additional info via the default help command.
@@ -139,24 +143,31 @@
 //     return runner.Run(env, args)
 //   }
 //
-// Parse sets flag.CommandLine to the root flag set that was parsed, so that
-// subsequent calls to flag.Parsed return true.
+// Parse merges root flags into flag.CommandLine and sets ContinueOnError, so
+// that subsequent calls to flag.Parsed return true.
 func Parse(root *Command, env *Env, args []string) (Runner, []string, error) {
+	if globalFlags == nil {
+		// Initialize our global flags to a cleaned copy.  We don't want the merging
+		// in parseFlags to contaminate the global flags, even if Parse is called
+		// multiple times, so we keep a single package-level copy.
+		cleanFlags(flag.CommandLine)
+		globalFlags = copyFlags(flag.CommandLine)
+	}
 	// Set env.Usage to the usage of the root command, in case the parse fails.
 	path := []*Command{root}
-	env.Usage = makeHelpRunner(path, env, flag.CommandLine).usageFunc
+	env.Usage = makeHelpRunner(path, env).usageFunc
 	if err := cleanTree(path); err != nil {
 		return nil, nil, err
 	}
-	cleanFlags(flag.CommandLine)
-	runner, args, globals, err := root.parse(nil, env, args, flag.CommandLine)
+	runner, args, err := root.parse(nil, env, args)
 	if err != nil {
 		return nil, nil, err
 	}
-	flag.CommandLine = globals
 	return runner, args, nil
 }
 
+var globalFlags *flag.FlagSet
+
 // ParseAndRun is a convenience that calls Parse, and then calls Run on the
 // returned runner with the given env and parsed args.
 func ParseAndRun(root *Command, env *Env, args []string) error {
@@ -182,16 +193,26 @@
 		trimSpace(&cmd.Topics[tx].Long)
 	}
 	cleanFlags(&cmd.Flags)
-	// Check that exactly one of Children or Runner is specified, so that
-	// subsequent code can rely on this invariant.
+	// Check that our Children / Runner invariant is satisfied.  At least one must
+	// be specified, and if both are specified then ArgsName and ArgsLong must be
+	// empty, meaning the Runner doesn't take any args.
 	switch hasC, hasR := len(cmd.Children) > 0, cmd.Runner != nil; {
-	case hasC && hasR:
-		return fmt.Errorf("%v: both Children and Run specified", cmdPath)
 	case !hasC && !hasR:
-		return fmt.Errorf("%v: neither Children nor Run specified", cmdPath)
+		return fmt.Errorf(`%v: CODE INVARIANT BROKEN; FIX YOUR CODE
+
+At least one of Children or Runner must be specified.
+`, cmdPath)
+	case hasC && hasR && (cmd.ArgsName != "" || cmd.ArgsLong != ""):
+		return fmt.Errorf(`%v: CODE INVARIANT BROKEN; FIX YOUR CODE
+
+Since both Children and Runner are specified, the Runner cannot take args.
+Otherwise a conflict between child names and runner args is possible.
+`, cmdPath)
 	}
 	for _, child := range cmd.Children {
-		cleanTree(append(path, child))
+		if err := cleanTree(append(path, child)); err != nil {
+			return err
+		}
 	}
 	return nil
 }
@@ -210,58 +231,93 @@
 	return name
 }
 
-func (cmd *Command) parse(path []*Command, env *Env, args []string, globals *flag.FlagSet) (Runner, []string, *flag.FlagSet, error) {
+func (cmd *Command) parse(path []*Command, env *Env, args []string) (Runner, []string, error) {
 	path = append(path, cmd)
 	cmdPath := pathName(path)
-	runHelp := makeHelpRunner(path, env, globals)
+	runHelp := makeHelpRunner(path, env)
 	env.Usage = runHelp.usageFunc
-	// Parse the merged command-specific and global flags.
-	flags := newSilentFlagSet(cmd.Name)
-	mergeFlags(flags, &cmd.Flags)
-	mergeFlags(flags, globals)
-	switch err := flags.Parse(args); {
+	// Parse flags and retrieve the args remaining after the parse.
+	args, err := parseFlags(path, env, args)
+	switch {
 	case err == flag.ErrHelp:
-		return runHelp, nil, flags, nil
+		return runHelp, nil, nil
 	case err != nil:
-		return nil, nil, nil, env.UsageErrorf("%s: %v", cmdPath, err)
+		return nil, nil, env.UsageErrorf("%s: %v", cmdPath, err)
 	}
-	// Look for matching children.
-	args = flags.Args()
-	if len(cmd.Children) > 0 {
-		if len(args) == 0 {
-			return nil, nil, nil, env.UsageErrorf("%s: no command specified", cmdPath)
+	// First handle the no-args case.
+	if len(args) == 0 {
+		if cmd.Runner != nil {
+			return cmd.Runner, nil, nil
 		}
-		subName, subArgs := args[0], args[1:]
+		return nil, nil, env.UsageErrorf("%s: no command specified", cmdPath)
+	}
+	// INVARIANT: len(args) > 0
+	// Look for matching children.
+	subName, subArgs := args[0], args[1:]
+	if len(cmd.Children) > 0 {
 		for _, child := range cmd.Children {
 			if child.Name == subName {
-				runner, args, _, err := child.parse(path, env, subArgs, globals)
-				return runner, args, flags, err
+				return child.parse(path, env, subArgs)
 			}
 		}
 		// Every non-leaf command gets a default help command.
 		if helpName == subName {
-			runner, args, _, err := runHelp.newCommand().parse(path, env, subArgs, globals)
-			return runner, args, flags, err
+			return runHelp.newCommand().parse(path, env, subArgs)
 		}
-		return nil, nil, nil, env.UsageErrorf("%s: unknown command %q", cmdPath, subName)
 	}
-	// We've reached a leaf command.
-	if len(args) > 0 && cmd.ArgsName == "" {
-		return nil, nil, nil, env.UsageErrorf("%s: doesn't take arguments", cmdPath)
+	// No matching children, check various error cases.
+	switch {
+	case cmd.Runner == nil:
+		return nil, nil, env.UsageErrorf("%s: unknown command %q", cmdPath, subName)
+	case cmd.ArgsName == "":
+		if len(cmd.Children) > 0 {
+			return nil, nil, env.UsageErrorf("%s: unknown command %q", cmdPath, subName)
+		}
+		return nil, nil, env.UsageErrorf("%s: doesn't take arguments", cmdPath)
 	}
-	return cmd.Runner, args, flags, nil
+	// INVARIANT: cmd.Runner != nil && len(args) > 0 && cmd.ArgsName != ""
+	return cmd.Runner, args, nil
 }
 
-func newSilentFlagSet(name string) *flag.FlagSet {
+func parseFlags(path []*Command, env *Env, args []string) ([]string, error) {
+	cmd, isRoot := path[len(path)-1], len(path) == 1
+	// Parse the merged command-specific and global flags.
+	var flags *flag.FlagSet
+	if isRoot {
+		// The root command is special, due to the pitfall described above in the
+		// package doc.  Merge into flag.CommandLine and use that for parsing.  This
+		// ensures that subsequent calls to flag.Parsed will return true, so the
+		// user can check whether flags have already been parsed.  Global flags take
+		// precedence over command flags for the root command.
+		flags = flag.CommandLine
+		mergeFlags(flags, &cmd.Flags)
+	} else {
+		// Command flags take precedence over global flags for non-root commands.
+		flags = copyFlags(&cmd.Flags)
+		mergeFlags(flags, globalFlags)
+	}
 	// Silence the many different ways flags.Parse can produce ugly output; we
 	// just want it to return any errors and handle the output ourselves.
 	//   1) Set flag.ContinueOnError so that Parse() doesn't exit or panic.
 	//   2) Discard all output (can't be nil, that means stderr).
 	//   3) Set an empty Usage (can't be nil, that means use the default).
-	flags := flag.NewFlagSet(name, flag.ContinueOnError)
+	flags.Init(cmd.Name, flag.ContinueOnError)
 	flags.SetOutput(ioutil.Discard)
 	flags.Usage = func() {}
-	return flags
+	if isRoot {
+		// If this is the root command, we must remember to undo the above changes
+		// on flag.CommandLine after the parse.  We don't know the original settings
+		// of these values, so we just blindly set back to the default values.
+		defer func() {
+			flags.Init(cmd.Name, flag.ExitOnError)
+			flags.SetOutput(nil)
+			flags.Usage = func() { env.Usage(env.Stderr) }
+		}()
+	}
+	if err := flags.Parse(args); err != nil {
+		return nil, err
+	}
+	return flags.Args(), nil
 }
 
 func mergeFlags(dst, src *flag.FlagSet) {
@@ -274,6 +330,12 @@
 	})
 }
 
+func copyFlags(flags *flag.FlagSet) *flag.FlagSet {
+	cp := new(flag.FlagSet)
+	mergeFlags(cp, flags)
+	return cp
+}
+
 // ErrExitCode may be returned by Runner.Run to cause the program to exit with a
 // specific error code.
 type ErrExitCode int
diff --git a/cmdline2/cmdline_test.go b/cmdline2/cmdline_test.go
index 2ddafa4..86ce728 100644
--- a/cmdline2/cmdline_test.go
+++ b/cmdline2/cmdline_test.go
@@ -142,49 +142,261 @@
 	}
 }
 
-func TestNoChildrenOrRun(t *testing.T) {
+func TestNoChildrenOrRunner(t *testing.T) {
 	neither := &Command{
 		Name:  "neither",
 		Short: "Neither is invalid.",
 		Long:  "Neither has no commands and no runner.",
 	}
+	wantErr := `neither: CODE INVARIANT BROKEN; FIX YOUR CODE
+
+At least one of Children or Runner must be specified.
+`
 	tests := []testCase{
-		{
-			Args: []string{},
-			Err:  `neither: neither Children nor Run specified`,
-		},
-		{
-			Args: []string{"foo"},
-			Err:  `neither: neither Children nor Run specified`,
-		},
+		{Args: []string{}, Err: wantErr},
+		{Args: []string{"foo"}, Err: wantErr},
 	}
 	runTestCases(t, neither, tests)
+	parent := &Command{
+		Name:     "parent",
+		Short:    "parent",
+		Long:     "parent",
+		Children: []*Command{neither},
+	}
+	wantErr = "parent " + wantErr
+	tests = []testCase{
+		{Args: []string{}, Err: wantErr},
+		{Args: []string{"foo"}, Err: wantErr},
+	}
+	runTestCases(t, parent, tests)
 }
 
-func TestBothChildrenAndRun(t *testing.T) {
+func TestBothChildrenAndRunnerWithArgs(t *testing.T) {
 	child := &Command{
-		Name:  "child",
-		Short: "Child command.",
-		Long:  "Child command.",
+		Name:   "child",
+		Short:  "Child command.",
+		Long:   "Child command.",
+		Runner: RunnerFunc(runEcho),
 	}
 	both := &Command{
 		Name:     "both",
 		Short:    "Both is invalid.",
-		Long:     "Both has both commands and a runner.",
+		Long:     "Both has both commands and a runner with args.",
+		ArgsName: "[strings]",
+		ArgsLong: "[strings] are arbitrary strings that will be echoed.",
 		Children: []*Command{child},
 		Runner:   RunnerFunc(runEcho),
 	}
+	wantErr := `both: CODE INVARIANT BROKEN; FIX YOUR CODE
+
+Since both Children and Runner are specified, the Runner cannot take args.
+Otherwise a conflict between child names and runner args is possible.
+`
 	tests := []testCase{
+		{Args: []string{}, Err: wantErr},
+		{Args: []string{"foo"}, Err: wantErr},
+	}
+	runTestCases(t, both, tests)
+	parent := &Command{
+		Name:     "parent",
+		Short:    "parent",
+		Long:     "parent",
+		Children: []*Command{both},
+	}
+	wantErr = "parent " + wantErr
+	tests = []testCase{
+		{Args: []string{}, Err: wantErr},
+		{Args: []string{"foo"}, Err: wantErr},
+	}
+	runTestCases(t, parent, tests)
+}
+
+func TestBothChildrenAndRunnerNoArgs(t *testing.T) {
+	cmdEcho := &Command{
+		Name:     "echo",
+		Short:    "Print strings on stdout",
+		Long:     "Echo prints any strings passed in to stdout.",
+		Runner:   RunnerFunc(runEcho),
+		ArgsName: "[strings]",
+		ArgsLong: "[strings] are arbitrary strings that will be echoed.",
+	}
+	prog := &Command{
+		Name:     "cmdrun",
+		Short:    "Cmdrun program.",
+		Long:     "Cmdrun has the echo command and a Run function with no args.",
+		Children: []*Command{cmdEcho},
+		Runner:   RunnerFunc(runHello),
+	}
+	var tests = []testCase{
 		{
-			Args: []string{},
-			Err:  `both: both Children and Run specified`,
+			Args:   []string{},
+			Stdout: "Hello\n",
 		},
 		{
 			Args: []string{"foo"},
-			Err:  `both: both Children and Run specified`,
+			Err:  errUsageStr,
+			Stderr: `ERROR: cmdrun: unknown command "foo"
+
+Cmdrun has the echo command and a Run function with no args.
+
+Usage:
+   cmdrun
+   cmdrun <command>
+
+The cmdrun commands are:
+   echo        Print strings on stdout
+   help        Display help for commands or topics
+Run "cmdrun help [command]" for command usage.
+
+The global flags are:
+ -global1=
+   global test flag 1
+ -global2=0
+   global test flag 2
+`,
+		},
+		{
+			Args: []string{"help"},
+			Stdout: `Cmdrun has the echo command and a Run function with no args.
+
+Usage:
+   cmdrun
+   cmdrun <command>
+
+The cmdrun commands are:
+   echo        Print strings on stdout
+   help        Display help for commands or topics
+Run "cmdrun help [command]" for command usage.
+
+The global flags are:
+ -global1=
+   global test flag 1
+ -global2=0
+   global test flag 2
+`,
+		},
+		{
+			Args: []string{"help", "echo"},
+			Stdout: `Echo prints any strings passed in to stdout.
+
+Usage:
+   cmdrun echo [strings]
+
+[strings] are arbitrary strings that will be echoed.
+
+The global flags are:
+ -global1=
+   global test flag 1
+ -global2=0
+   global test flag 2
+`,
+		},
+		{
+			Args: []string{"help", "..."},
+			Stdout: `Cmdrun has the echo command and a Run function with no args.
+
+Usage:
+   cmdrun
+   cmdrun <command>
+
+The cmdrun commands are:
+   echo        Print strings on stdout
+   help        Display help for commands or topics
+Run "cmdrun help [command]" for command usage.
+
+The global flags are:
+ -global1=
+   global test flag 1
+ -global2=0
+   global test flag 2
+================================================================================
+Cmdrun echo
+
+Echo prints any strings passed in to stdout.
+
+Usage:
+   cmdrun echo [strings]
+
+[strings] are arbitrary strings that will be echoed.
+================================================================================
+Cmdrun help
+
+Help with no args displays the usage of the parent command.
+
+Help with args displays the usage of the specified sub-command or help topic.
+
+"help ..." recursively displays help for all commands and topics.
+
+Usage:
+   cmdrun help [flags] [command/topic ...]
+
+[command/topic ...] optionally identifies a specific sub-command or help topic.
+
+The cmdrun help flags are:
+ -style=compact
+   The formatting style for help output:
+      compact - Good for compact cmdline output.
+      full    - Good for cmdline output, shows all global flags.
+      godoc   - Good for godoc processing.
+   Override the default by setting the CMDLINE_STYLE environment variable.
+ -width=80
+   Format output to this target width in runes, or unlimited if width < 0.
+   Defaults to the terminal width if available.  Override the default by setting
+   the CMDLINE_WIDTH environment variable.
+`,
+		},
+		{
+			Args: []string{"help", "foo"},
+			Err:  errUsageStr,
+			Stderr: `ERROR: cmdrun: unknown command or topic "foo"
+
+Cmdrun has the echo command and a Run function with no args.
+
+Usage:
+   cmdrun
+   cmdrun <command>
+
+The cmdrun commands are:
+   echo        Print strings on stdout
+   help        Display help for commands or topics
+Run "cmdrun help [command]" for command usage.
+
+The global flags are:
+ -global1=
+   global test flag 1
+ -global2=0
+   global test flag 2
+`,
+		},
+		{
+			Args:   []string{"echo", "foo", "bar"},
+			Stdout: "[foo bar]\n",
+		},
+		{
+			Args: []string{"echo", "error"},
+			Err:  errEchoStr,
+		},
+		{
+			Args: []string{"echo", "bad_arg"},
+			Err:  errUsageStr,
+			Stderr: `ERROR: Invalid argument bad_arg
+
+Echo prints any strings passed in to stdout.
+
+Usage:
+   cmdrun echo [strings]
+
+[strings] are arbitrary strings that will be echoed.
+
+The global flags are:
+ -global1=
+   global test flag 1
+ -global2=0
+   global test flag 2
+`,
 		},
 	}
-	runTestCases(t, both, tests)
+	runTestCases(t, prog, tests)
 }
 
 func TestOneCommand(t *testing.T) {
@@ -1858,7 +2070,6 @@
 `,
 		},
 	}
-
 	runTestCases(t, progHello1, tests)
 }
 
@@ -2007,7 +2218,7 @@
 		},
 	}
 	runTestCases(t, prog, tests)
-	compactGlobalFlags = nil
+	nonHiddenGlobalFlags = nil
 }
 
 func TestHideGlobalFlagsRootNoChildren(t *testing.T) {
@@ -2051,5 +2262,55 @@
 		},
 	}
 	runTestCases(t, prog, tests)
-	compactGlobalFlags = nil
+	nonHiddenGlobalFlags = nil
+}
+
+func TestRootCommandFlags(t *testing.T) {
+	root := &Command{
+		Name:   "root",
+		Short:  "Test root command flags.",
+		Long:   "Test root command flags.",
+		Runner: RunnerFunc(runHello),
+	}
+	rb := root.Flags.Bool("rbool", false, "rbool desc")
+	rs := root.Flags.String("rstring", "abc", "rstring desc")
+	origFlags := flag.CommandLine
+	// Parse and make sure the flags get set appropriately.
+	_, _, err := Parse(root, NewEnv(), []string{"-rbool=true", "-rstring=XYZ"})
+	if err != nil {
+		t.Fatalf("Parse failed: %v", err)
+	}
+	if got, want := *rb, true; got != want {
+		t.Errorf("rbool got %v want %v", got, want)
+	}
+	if got, want := *rs, "XYZ"; got != want {
+		t.Errorf("rstring got %v want %v", got, want)
+	}
+	// Make sure we haven't changed the flag.CommandLine pointer, and that it's
+	// parsed, and it contains our root command flags.  These properties are
+	// important to ensure so that users can check whether the flags are already
+	// parsed to avoid double-parsing.  Even if they do call flag.Parse it'll
+	// succeed, as long as cmdline.Parse succeeded.
+	if got, want := flag.CommandLine, origFlags; got != want {
+		t.Errorf("flag.CommandLine pointer changed, got %p want %p", got, want)
+	}
+	if got, want := flag.CommandLine.Parsed(), true; got != want {
+		t.Errorf("flag.CommandLine.Parsed() got %v, want %v", got, want)
+	}
+	if name := "rbool"; flag.CommandLine.Lookup(name) == nil {
+		t.Errorf("flag.CommandLine.Lookup(%q) failed", name)
+	}
+	if name := "rstring"; flag.CommandLine.Lookup(name) == nil {
+		t.Errorf("flag.CommandLine.Lookup(%q) failed", name)
+	}
+	// Actually try double-parsing flag.CommandLine.
+	if err := flag.CommandLine.Parse([]string{"-rbool=false", "-rstring=123"}); err != nil {
+		t.Errorf("flag.CommandLine.Parse() failed: %v", err)
+	}
+	if got, want := *rb, false; got != want {
+		t.Errorf("rbool got %v want %v", got, want)
+	}
+	if got, want := *rs, "123"; got != want {
+		t.Errorf("rstring got %v want %v", got, want)
+	}
 }
diff --git a/cmdline2/help.go b/cmdline2/help.go
index d3c5af6..3b449ec 100644
--- a/cmdline2/help.go
+++ b/cmdline2/help.go
@@ -23,16 +23,15 @@
 	*helpConfig
 }
 
-func makeHelpRunner(path []*Command, env *Env, globals *flag.FlagSet) helpRunner {
-	return helpRunner{path, &helpConfig{globals, env.style(), env.width()}}
+func makeHelpRunner(path []*Command, env *Env) helpRunner {
+	return helpRunner{path, &helpConfig{env.style(), env.width()}}
 }
 
 // helpConfig holds configuration data for help.  The style and width may be
 // overriden by flags if the command returned by newCommand is parsed.
 type helpConfig struct {
-	globals *flag.FlagSet
-	style   style
-	width   int
+	style style
+	width int
 }
 
 // Run implements the Runner interface method.
@@ -202,13 +201,15 @@
 	if countFlags(&cmd.Flags, nil, true) > 0 {
 		cmdPathF += " [flags]"
 	}
-	switch {
-	case len(children) > 0:
+	if cmd.Runner != nil {
+		if cmd.ArgsName != "" {
+			fmt.Fprintln(w, cmdPathF, cmd.ArgsName)
+		} else {
+			fmt.Fprintln(w, cmdPathF)
+		}
+	}
+	if len(children) > 0 {
 		fmt.Fprintln(w, cmdPathF, "<command>")
-	case cmd.ArgsName != "":
-		fmt.Fprintln(w, cmdPathF, cmd.ArgsName)
-	default:
-		fmt.Fprintln(w, cmdPathF)
 	}
 	// Commands.
 	const minNameWidth = 11
@@ -273,18 +274,18 @@
 	if !firstCall {
 		return
 	}
-	hasCompact := countFlags(config.globals, compactGlobalFlags, true) > 0
-	hasFull := countFlags(config.globals, compactGlobalFlags, false) > 0
+	hasCompact := countFlags(globalFlags, nonHiddenGlobalFlags, true) > 0
+	hasFull := countFlags(globalFlags, nonHiddenGlobalFlags, false) > 0
 	if config.style != styleCompact {
 		// Non-compact style, always show all global flags.
 		if hasCompact || hasFull {
 			fmt.Fprintln(w)
 			fmt.Fprintln(w, "The global flags are:")
-			printFlags(w, config.globals, config.style, compactGlobalFlags, true)
+			printFlags(w, globalFlags, config.style, nonHiddenGlobalFlags, true)
 			if hasCompact && hasFull {
 				fmt.Fprintln(w)
 			}
-			printFlags(w, config.globals, config.style, compactGlobalFlags, false)
+			printFlags(w, globalFlags, config.style, nonHiddenGlobalFlags, false)
 		}
 		return
 	}
@@ -292,7 +293,7 @@
 	if hasCompact {
 		fmt.Fprintln(w)
 		fmt.Fprintln(w, "The global flags are:")
-		printFlags(w, config.globals, config.style, compactGlobalFlags, true)
+		printFlags(w, globalFlags, config.style, nonHiddenGlobalFlags, true)
 	}
 	if hasFull {
 		fmt.Fprintln(w)
@@ -354,7 +355,7 @@
 	return false
 }
 
-var compactGlobalFlags []*regexp.Regexp
+var nonHiddenGlobalFlags []*regexp.Regexp
 
 // HideGlobalFlagsExcept hides global flags from the default compact-style usage
 // message, except for the given regexps.  Global flag names that match any of
@@ -363,10 +364,10 @@
 //
 // All global flags are always shown in non-compact style usage messages.
 func HideGlobalFlagsExcept(regexps ...*regexp.Regexp) {
-	// NOTE: compactGlobalFlags is used as the argument to matchRegexps, where nil
-	// means "all names match" and empty means "no names match".
-	compactGlobalFlags = append(compactGlobalFlags, regexps...)
-	if compactGlobalFlags == nil {
-		compactGlobalFlags = []*regexp.Regexp{}
+	// NOTE: nonHiddenGlobalFlags is used as the argument to matchRegexps, where
+	// nil means "all names match" and empty means "no names match".
+	nonHiddenGlobalFlags = append(nonHiddenGlobalFlags, regexps...)
+	if nonHiddenGlobalFlags == nil {
+		nonHiddenGlobalFlags = []*regexp.Regexp{}
 	}
 }