From ccef1598b198ab53049cd50968cf7976803b96be Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Mon, 17 Dec 2018 16:59:11 +0000 Subject: [PATCH] Move `disableFlagsInUseLine` from `main` into our `cli` library ... and expose. I would like to use this from another site. This implies also moving (and exposing) the `visitAll` helper. Unit test them while I'm here. Signed-off-by: Ian Campbell --- cli/cobra.go | 19 +++++++++++++++++++ cli/cobra_test.go | 30 ++++++++++++++++++++++++++++++ cmd/docker/docker.go | 21 ++------------------- 3 files changed, 51 insertions(+), 19 deletions(-) create mode 100644 cli/cobra_test.go diff --git a/cli/cobra.go b/cli/cobra.go index a7431a0876..b0c50a2aa9 100644 --- a/cli/cobra.go +++ b/cli/cobra.go @@ -46,6 +46,25 @@ func FlagErrorFunc(cmd *cobra.Command, err error) error { } } +// VisitAll will traverse all commands from the root. +// This is different from the VisitAll of cobra.Command where only parents +// are checked. +func VisitAll(root *cobra.Command, fn func(*cobra.Command)) { + for _, cmd := range root.Commands() { + VisitAll(cmd, fn) + } + fn(root) +} + +// DisableFlagsInUseLine sets the DisableFlagsInUseLine flag on all +// commands within the tree rooted at cmd. +func DisableFlagsInUseLine(cmd *cobra.Command) { + VisitAll(cmd, func(ccmd *cobra.Command) { + // do not add a `[flags]` to the end of the usage line. + ccmd.DisableFlagsInUseLine = true + }) +} + var helpCommand = &cobra.Command{ Use: "help [command]", Short: "Help about the command", diff --git a/cli/cobra_test.go b/cli/cobra_test.go new file mode 100644 index 0000000000..8c9cf1b19f --- /dev/null +++ b/cli/cobra_test.go @@ -0,0 +1,30 @@ +package cli + +import ( + "testing" + + "github.com/spf13/cobra" + "gotest.tools/assert" +) + +func TestVisitAll(t *testing.T) { + root := &cobra.Command{Use: "root"} + sub1 := &cobra.Command{Use: "sub1"} + sub1sub1 := &cobra.Command{Use: "sub1sub1"} + sub1sub2 := &cobra.Command{Use: "sub1sub2"} + sub2 := &cobra.Command{Use: "sub2"} + + root.AddCommand(sub1, sub2) + sub1.AddCommand(sub1sub1, sub1sub2) + + // Take the opportunity to test DisableFlagsInUseLine too + DisableFlagsInUseLine(root) + + var visited []string + VisitAll(root, func(ccmd *cobra.Command) { + visited = append(visited, ccmd.Name()) + assert.Assert(t, ccmd.DisableFlagsInUseLine, "DisableFlagsInUseLine not set on %q", ccmd.Name()) + }) + expected := []string{"sub1sub1", "sub1sub2", "sub1", "sub2", "root"} + assert.DeepEqual(t, expected, visited) +} diff --git a/cmd/docker/docker.go b/cmd/docker/docker.go index b16b3ec194..69d773aa2e 100644 --- a/cmd/docker/docker.go +++ b/cmd/docker/docker.go @@ -57,19 +57,12 @@ func newDockerCommand(dockerCli *command.DockerCli) *cobra.Command { cmd.SetOutput(dockerCli.Out()) commands.AddCommands(cmd, dockerCli) - disableFlagsInUseLine(cmd) + cli.DisableFlagsInUseLine(cmd) setValidateArgs(dockerCli, cmd, flags, opts) return cmd } -func disableFlagsInUseLine(cmd *cobra.Command) { - visitAll(cmd, func(ccmd *cobra.Command) { - // do not add a `[flags]` to the end of the usage line. - ccmd.DisableFlagsInUseLine = true - }) -} - func setFlagErrorFunc(dockerCli *command.DockerCli, cmd *cobra.Command, flags *pflag.FlagSet, opts *cliflags.ClientOptions) { // When invoking `docker stack --nonsense`, we need to make sure FlagErrorFunc return appropriate // output if the feature is not supported. @@ -111,7 +104,7 @@ func setValidateArgs(dockerCli *command.DockerCli, cmd *cobra.Command, flags *pf // As a result, here we replace the existing Args validation func to a wrapper, // where the wrapper will check to see if the feature is supported or not. // The Args validation error will only be returned if the feature is supported. - visitAll(cmd, func(ccmd *cobra.Command) { + cli.VisitAll(cmd, func(ccmd *cobra.Command) { // if there is no tags for a command or any of its parent, // there is no need to wrap the Args validation. if !hasTags(ccmd) { @@ -145,16 +138,6 @@ func initializeDockerCli(dockerCli *command.DockerCli, flags *pflag.FlagSet, opt return dockerCli.Initialize(opts) } -// visitAll will traverse all commands from the root. -// This is different from the VisitAll of cobra.Command where only parents -// are checked. -func visitAll(root *cobra.Command, fn func(*cobra.Command)) { - for _, cmd := range root.Commands() { - visitAll(cmd, fn) - } - fn(root) -} - func noArgs(cmd *cobra.Command, args []string) error { if len(args) == 0 { return nil