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 <ijc@docker.com>
This commit is contained in:
Ian Campbell 2018-12-17 16:59:11 +00:00
parent 158a766886
commit ccef1598b1
3 changed files with 51 additions and 19 deletions

View File

@ -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{ var helpCommand = &cobra.Command{
Use: "help [command]", Use: "help [command]",
Short: "Help about the command", Short: "Help about the command",

30
cli/cobra_test.go Normal file
View File

@ -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)
}

View File

@ -57,19 +57,12 @@ func newDockerCommand(dockerCli *command.DockerCli) *cobra.Command {
cmd.SetOutput(dockerCli.Out()) cmd.SetOutput(dockerCli.Out())
commands.AddCommands(cmd, dockerCli) commands.AddCommands(cmd, dockerCli)
disableFlagsInUseLine(cmd) cli.DisableFlagsInUseLine(cmd)
setValidateArgs(dockerCli, cmd, flags, opts) setValidateArgs(dockerCli, cmd, flags, opts)
return cmd 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) { 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 // When invoking `docker stack --nonsense`, we need to make sure FlagErrorFunc return appropriate
// output if the feature is not supported. // 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, // 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. // 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. // 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, // if there is no tags for a command or any of its parent,
// there is no need to wrap the Args validation. // there is no need to wrap the Args validation.
if !hasTags(ccmd) { if !hasTags(ccmd) {
@ -145,16 +138,6 @@ func initializeDockerCli(dockerCli *command.DockerCli, flags *pflag.FlagSet, opt
return dockerCli.Initialize(opts) 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 { func noArgs(cmd *cobra.Command, args []string) error {
if len(args) == 0 { if len(args) == 0 {
return nil return nil