diff options
Diffstat (limited to 'vendor/github.com/spf13')
26 files changed, 1649 insertions, 69 deletions
diff --git a/vendor/github.com/spf13/cobra/README.md b/vendor/github.com/spf13/cobra/README.md index 5d2504b1c..2efda5920 100644 --- a/vendor/github.com/spf13/cobra/README.md +++ b/vendor/github.com/spf13/cobra/README.md @@ -157,7 +157,12 @@ In a Cobra app, typically the main.go file is very bare. It serves, one purpose, ```go package main -import "{pathToYourApp}/cmd" +import ( + "fmt" + "os" + + "{pathToYourApp}/cmd" +) func main() { if err := cmd.RootCmd.Execute(); err != nil { @@ -313,7 +318,12 @@ In a Cobra app, typically the main.go file is very bare. It serves, one purpose, ```go package main -import "{pathToYourApp}/cmd" +import ( + "fmt" + "os" + + "{pathToYourApp}/cmd" +) func main() { if err := cmd.RootCmd.Execute(); err != nil { @@ -337,6 +347,7 @@ package cmd import ( "github.com/spf13/cobra" + "fmt" ) func init() { diff --git a/vendor/github.com/spf13/cobra/bash_completions.go b/vendor/github.com/spf13/cobra/bash_completions.go index 7a5bd4d7d..8820ba8fc 100644 --- a/vendor/github.com/spf13/cobra/bash_completions.go +++ b/vendor/github.com/spf13/cobra/bash_completions.go @@ -10,6 +10,7 @@ import ( "github.com/spf13/pflag" ) +// Annotations for Bash completion. const ( BashCompFilenameExt = "cobra_annotation_bash_completion_filename_extensions" BashCompCustom = "cobra_annotation_bash_completion_custom" @@ -22,7 +23,7 @@ func preamble(out io.Writer, name string) error { if err != nil { return err } - _, err = fmt.Fprint(out, ` + preamStr := ` __debug() { if [[ -n ${BASH_COMP_DEBUG_FILE} ]]; then @@ -246,7 +247,8 @@ __handle_word() __handle_word } -`) +` + _, err = fmt.Fprint(out, preamStr) return err } @@ -566,6 +568,7 @@ func gen(cmd *Command, w io.Writer) error { return nil } +// GenBashCompletion generates bash completion file and writes to the passed writer. func (cmd *Command) GenBashCompletion(w io.Writer) error { if err := preamble(w, cmd.Name()); err != nil { return err @@ -585,6 +588,7 @@ func nonCompletableFlag(flag *pflag.Flag) bool { return flag.Hidden || len(flag.Deprecated) > 0 } +// GenBashCompletionFile generates bash completion file. func (cmd *Command) GenBashCompletionFile(filename string) error { outFile, err := os.Create(filename) if err != nil { diff --git a/vendor/github.com/spf13/cobra/bash_completions.md b/vendor/github.com/spf13/cobra/bash_completions.md index 6e3b71f13..7fa970fa2 100644 --- a/vendor/github.com/spf13/cobra/bash_completions.md +++ b/vendor/github.com/spf13/cobra/bash_completions.md @@ -18,7 +18,7 @@ func main() { } ``` -That will get you completions of subcommands and flags. If you make additional annotations to your code, you can get even more intelligent and flexible behavior. +`out.sh` will get you completions of subcommands and flags. Copy it to `/etc/bash_completion.d/` as described [here](https://debian-administration.org/article/316/An_introduction_to_bash_completion_part_1) and reset your terminal to use autocompletion. If you make additional annotations to your code, you can get even more intelligent and flexible behavior. ## Creating your own custom functions diff --git a/vendor/github.com/spf13/cobra/cobra.go b/vendor/github.com/spf13/cobra/cobra.go index b39c715a5..9605b984c 100644 --- a/vendor/github.com/spf13/cobra/cobra.go +++ b/vendor/github.com/spf13/cobra/cobra.go @@ -37,7 +37,8 @@ var templateFuncs = template.FuncMap{ var initializers []func() -// Automatic prefix matching can be a dangerous thing to automatically enable in CLI tools. +// EnablePrefixMatching allows to set automatic prefix matching. Automatic prefix matching can be a dangerous thing +// to automatically enable in CLI tools. // Set this to true to enable it. var EnablePrefixMatching = false diff --git a/vendor/github.com/spf13/cobra/command.go b/vendor/github.com/spf13/cobra/command.go index 49889318c..3ee1a0a9d 100644 --- a/vendor/github.com/spf13/cobra/command.go +++ b/vendor/github.com/spf13/cobra/command.go @@ -129,7 +129,7 @@ type Command struct { DisableFlagParsing bool } -// os.Args[1:] by default, if desired, can be overridden +// SetArgs sets arguments for the command. It is set to os.Args[1:] by default, if desired, can be overridden // particularly useful when testing. func (c *Command) SetArgs(a []string) { c.args = a @@ -141,12 +141,12 @@ func (c *Command) SetOutput(output io.Writer) { c.output = &output } -// Usage can be defined by application. +// SetUsageFunc sets usage function. Usage can be defined by application. func (c *Command) SetUsageFunc(f func(*Command) error) { c.usageFunc = f } -// Can be defined by Application. +// SetUsageTemplate sets usage template. Can be defined by Application. func (c *Command) SetUsageTemplate(s string) { c.usageTemplate = s } @@ -157,16 +157,17 @@ func (c *Command) SetFlagErrorFunc(f func(*Command, error) error) { c.flagErrorFunc = f } -// Can be defined by Application +// SetHelpFunc sets help function. Can be defined by Application func (c *Command) SetHelpFunc(f func(*Command, []string)) { c.helpFunc = f } +// SetHelpCommand sets help command. func (c *Command) SetHelpCommand(cmd *Command) { c.helpCommand = cmd } -// Can be defined by Application. +// SetHelpTemplate sets help template to be used. Application can use it to set custom template. func (c *Command) SetHelpTemplate(s string) { c.helpTemplate = s } @@ -183,10 +184,12 @@ func (c *Command) SetGlobalNormalizationFunc(n func(f *flag.FlagSet, name string } } +// OutOrStdout returns output to stdout func (c *Command) OutOrStdout() io.Writer { return c.getOut(os.Stdout) } +// OutOrStderr returns output to stderr func (c *Command) OutOrStderr() io.Writer { return c.getOut(os.Stderr) } @@ -265,6 +268,7 @@ func (c *Command) Help() error { return nil } +// UsageString return usage string. func (c *Command) UsageString() string { tmpOutput := c.output bb := new(bytes.Buffer) @@ -292,6 +296,7 @@ func (c *Command) FlagErrorFunc() (f func(*Command, error) error) { var minUsagePadding = 25 +// UsagePadding return padding for the usage. func (c *Command) UsagePadding() int { if c.parent == nil || minUsagePadding > c.parent.commandsMaxUseLen { return minUsagePadding @@ -301,7 +306,7 @@ func (c *Command) UsagePadding() int { var minCommandPathPadding = 11 -// +// CommandPathPadding return padding for the command path. func (c *Command) CommandPathPadding() int { if c.parent == nil || minCommandPathPadding > c.parent.commandsMaxCommandPathLen { return minCommandPathPadding @@ -311,6 +316,7 @@ func (c *Command) CommandPathPadding() int { var minNamePadding = 11 +// NamePadding returns padding for the name. func (c *Command) NamePadding() int { if c.parent == nil || minNamePadding > c.parent.commandsMaxNameLen { return minNamePadding @@ -318,6 +324,7 @@ func (c *Command) NamePadding() int { return c.parent.commandsMaxNameLen } +// UsageTemplate returns usage template for the command. func (c *Command) UsageTemplate() string { if c.usageTemplate != "" { return c.usageTemplate @@ -353,6 +360,7 @@ Use "{{.CommandPath}} [command] --help" for more information about a command.{{e ` } +// HelpTemplate return help template for the command. func (c *Command) HelpTemplate() string { if c.helpTemplate != "" { return c.helpTemplate @@ -418,7 +426,7 @@ func stripFlags(args []string, c *Command) []string { case inFlag: inFlag = false case y == "": - // strip empty commands, as the go tests expect this to be ok.... + // strip empty commands, as the go tests expect this to be ok.... case !strings.HasPrefix(y, "-"): commands = append(commands, y) inFlag = false @@ -447,7 +455,7 @@ func argsMinusFirstX(args []string, x string) []string { return args } -// find the target command given the args and command tree +// Find finds the target command given the args and command tree // Meant to be run on the highest node. Only searches down. func (c *Command) Find(args []string) (*Command, []string, error) { if c == nil { @@ -515,6 +523,7 @@ func (c *Command) Find(args []string) (*Command, []string, error) { return commandFound, a, nil } +// SuggestionsFor provides suggestions for the typedName. func (c *Command) SuggestionsFor(typedName string) []string { suggestions := []string{} for _, cmd := range c.commands { @@ -535,6 +544,7 @@ func (c *Command) SuggestionsFor(typedName string) []string { return suggestions } +// VisitParents visits all parents of the command and invokes fn on each parent. func (c *Command) VisitParents(fn func(*Command)) { var traverse func(*Command) *Command @@ -550,6 +560,7 @@ func (c *Command) VisitParents(fn func(*Command)) { traverse(c) } +// Root finds root command. func (c *Command) Root() *Command { var findRoot func(*Command) *Command @@ -674,7 +685,7 @@ func (c *Command) errorMsgFromParse() string { return "" } -// Call execute to use the args (os.Args[1:] by default) +// Execute Call execute to use the args (os.Args[1:] by default) // and run through the command tree finding appropriate matches // for commands and then corresponding flags. func (c *Command) Execute() error { @@ -682,6 +693,7 @@ func (c *Command) Execute() error { return err } +// ExecuteC executes the command. func (c *Command) ExecuteC() (cmd *Command, err error) { // Regardless of what command execute is called on, run on Root only @@ -779,7 +791,7 @@ func (c *Command) initHelpCmd() { c.AddCommand(c.helpCommand) } -// Used for testing. +// ResetCommands used for testing. func (c *Command) ResetCommands() { c.commands = nil c.helpCommand = nil @@ -902,7 +914,7 @@ func (c *Command) UseLine() string { return str + c.Use } -// For use in determining which flags have been assigned to which commands +// DebugFlags used to determine which flags have been assigned to which commands // and which persist. func (c *Command) DebugFlags() { c.Println("DebugFlags called on", c.Name()) @@ -970,10 +982,12 @@ func (c *Command) HasAlias(s string) bool { return false } +// NameAndAliases returns string containing name and all aliases func (c *Command) NameAndAliases() string { return strings.Join(append([]string{c.Name()}, c.Aliases...), ", ") } +// HasExample determines if the command has example. func (c *Command) HasExample() bool { return len(c.Example) > 0 } @@ -1070,7 +1084,7 @@ func (c *Command) GlobalNormalizationFunc() func(f *flag.FlagSet, name string) f return c.globNormFunc } -// Flage returns the complete FlagSet that applies +// Flags returns the complete FlagSet that applies // to this command (local and persistent declared here and by all parents). func (c *Command) Flags() *flag.FlagSet { if c.flags == nil { @@ -1170,44 +1184,44 @@ func (c *Command) ResetFlags() { c.pflags.SetOutput(c.flagErrorBuf) } -// Does the command contain any flags (local plus persistent from the entire structure). +// HasFlags checks if the command contains any flags (local plus persistent from the entire structure). func (c *Command) HasFlags() bool { return c.Flags().HasFlags() } -// Does the command contain persistent flags. +// HasPersistentFlags checks if the command contains persistent flags. func (c *Command) HasPersistentFlags() bool { return c.PersistentFlags().HasFlags() } -// Does the command has flags specifically declared locally. +// HasLocalFlags checks if the command has flags specifically declared locally. func (c *Command) HasLocalFlags() bool { return c.LocalFlags().HasFlags() } -// Does the command have flags inherited from its parent command. +// HasInheritedFlags checks if the command has flags inherited from its parent command. func (c *Command) HasInheritedFlags() bool { return c.InheritedFlags().HasFlags() } -// Does the command contain any flags (local plus persistent from the entire +// HasAvailableFlags checks if the command contains any flags (local plus persistent from the entire // structure) which are not hidden or deprecated. func (c *Command) HasAvailableFlags() bool { return c.Flags().HasAvailableFlags() } -// Does the command contain persistent flags which are not hidden or deprecated. +// HasAvailablePersistentFlags checks if the command contains persistent flags which are not hidden or deprecated. func (c *Command) HasAvailablePersistentFlags() bool { return c.PersistentFlags().HasAvailableFlags() } -// Does the command has flags specifically declared locally which are not hidden +// HasAvailableLocalFlags checks if the command has flags specifically declared locally which are not hidden // or deprecated. func (c *Command) HasAvailableLocalFlags() bool { return c.LocalFlags().HasAvailableFlags() } -// Does the command have flags inherited from its parent command which are +// HasAvailableInheritedFlags checks if the command has flags inherited from its parent command which are // not hidden or deprecated. func (c *Command) HasAvailableInheritedFlags() bool { return c.InheritedFlags().HasAvailableFlags() diff --git a/vendor/github.com/spf13/cobra/doc/man_docs.go b/vendor/github.com/spf13/cobra/doc/man_docs.go index 5798d0fbf..fd7107c42 100644 --- a/vendor/github.com/spf13/cobra/doc/man_docs.go +++ b/vendor/github.com/spf13/cobra/doc/man_docs.go @@ -37,7 +37,7 @@ func GenManTree(cmd *cobra.Command, header *GenManHeader, dir string) error { return GenManTreeFromOpts(cmd, GenManTreeOptions{ Header: header, Path: dir, - CommandSeparator: "_", + CommandSeparator: "-", }) } diff --git a/vendor/github.com/spf13/cobra/doc/md_docs.md b/vendor/github.com/spf13/cobra/doc/md_docs.md index 480b152f0..beec3e0e8 100644 --- a/vendor/github.com/spf13/cobra/doc/md_docs.md +++ b/vendor/github.com/spf13/cobra/doc/md_docs.md @@ -32,15 +32,15 @@ import ( "io/ioutil" "os" - kubectlcmd "k8s.io/kubernetes/pkg/kubectl/cmd" + "k8s.io/kubernetes/pkg/kubectl/cmd" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" "github.com/spf13/cobra/doc" ) func main() { - cmd := kubectlcmd.NewKubectlCommand(cmdutil.NewFactory(nil), os.Stdin, ioutil.Discard, ioutil.Discard) - doc.GenMarkdownTree(cmd, "./") + kubectl := cmd.NewKubectlCommand(cmdutil.NewFactory(nil), os.Stdin, ioutil.Discard, ioutil.Discard) + doc.GenMarkdownTree(kubectl, "./") } ``` diff --git a/vendor/github.com/spf13/cobra/doc/util.go b/vendor/github.com/spf13/cobra/doc/util.go index a1c6b89ba..a7d2765a9 100644 --- a/vendor/github.com/spf13/cobra/doc/util.go +++ b/vendor/github.com/spf13/cobra/doc/util.go @@ -13,7 +13,11 @@ package doc -import "github.com/spf13/cobra" +import ( + "strings" + + "github.com/spf13/cobra" +) // Test to see if we have a reason to print See Also information in docs // Basically this is a test for a parent commend or a subcommand which is @@ -31,6 +35,15 @@ func hasSeeAlso(cmd *cobra.Command) bool { return false } +// Temporary workaround for yaml lib generating incorrect yaml with long strings +// that do not contain \n. +func forceMultiLine(s string) string { + if len(s) > 60 && !strings.Contains(s, "\n") { + s = s + "\n" + } + return s +} + type byName []*cobra.Command func (s byName) Len() int { return len(s) } diff --git a/vendor/github.com/spf13/cobra/doc/yaml_docs.go b/vendor/github.com/spf13/cobra/doc/yaml_docs.go new file mode 100644 index 000000000..75474d299 --- /dev/null +++ b/vendor/github.com/spf13/cobra/doc/yaml_docs.go @@ -0,0 +1,165 @@ +// Copyright 2016 French Ben. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package doc + +import ( + "fmt" + "io" + "os" + "path/filepath" + "sort" + "strings" + + "github.com/spf13/cobra" + "github.com/spf13/pflag" + "gopkg.in/yaml.v2" +) + +type cmdOption struct { + Name string + Shorthand string `yaml:",omitempty"` + DefaultValue string `yaml:"default_value,omitempty"` + Usage string `yaml:",omitempty"` +} + +type cmdDoc struct { + Name string + Synopsis string `yaml:",omitempty"` + Description string `yaml:",omitempty"` + Options []cmdOption `yaml:",omitempty"` + InheritedOptions []cmdOption `yaml:"inherited_options,omitempty"` + Example string `yaml:",omitempty"` + SeeAlso []string `yaml:"see_also,omitempty"` +} + +// GenYamlTree creates yaml structured ref files for this command and all descendants +// in the directory given. This function may not work +// correctly if your command names have - in them. If you have `cmd` with two +// subcmds, `sub` and `sub-third`. And `sub` has a subcommand called `third` +// it is undefined which help output will be in the file `cmd-sub-third.1`. +func GenYamlTree(cmd *cobra.Command, dir string) error { + identity := func(s string) string { return s } + emptyStr := func(s string) string { return "" } + return GenYamlTreeCustom(cmd, dir, emptyStr, identity) +} + +// GenYamlTreeCustom creates yaml structured ref files +func GenYamlTreeCustom(cmd *cobra.Command, dir string, filePrepender, linkHandler func(string) string) error { + for _, c := range cmd.Commands() { + if !c.IsAvailableCommand() || c.IsHelpCommand() { + continue + } + if err := GenYamlTreeCustom(c, dir, filePrepender, linkHandler); err != nil { + return err + } + } + + basename := strings.Replace(cmd.CommandPath(), " ", "_", -1) + ".yaml" + filename := filepath.Join(dir, basename) + f, err := os.Create(filename) + if err != nil { + return err + } + defer f.Close() + + if _, err := io.WriteString(f, filePrepender(filename)); err != nil { + return err + } + if err := GenYamlCustom(cmd, f, linkHandler); err != nil { + return err + } + return nil +} + +// GenYaml creates yaml output +func GenYaml(cmd *cobra.Command, w io.Writer) error { + return GenYamlCustom(cmd, w, func(s string) string { return s }) +} + +// GenYamlCustom creates custom yaml output +func GenYamlCustom(cmd *cobra.Command, w io.Writer, linkHandler func(string) string) error { + yamlDoc := cmdDoc{} + yamlDoc.Name = cmd.CommandPath() + + yamlDoc.Synopsis = forceMultiLine(cmd.Short) + yamlDoc.Description = forceMultiLine(cmd.Long) + + if len(cmd.Example) > 0 { + yamlDoc.Example = cmd.Example + } + + flags := cmd.NonInheritedFlags() + if flags.HasFlags() { + yamlDoc.Options = genFlagResult(flags) + } + flags = cmd.InheritedFlags() + if flags.HasFlags() { + yamlDoc.InheritedOptions = genFlagResult(flags) + } + + if hasSeeAlso(cmd) { + result := []string{} + if cmd.HasParent() { + parent := cmd.Parent() + result = append(result, parent.CommandPath()+" - "+parent.Short) + } + children := cmd.Commands() + sort.Sort(byName(children)) + for _, child := range children { + if !child.IsAvailableCommand() || child.IsHelpCommand() { + continue + } + result = append(result, child.Name()+" - "+child.Short) + } + yamlDoc.SeeAlso = result + } + + final, err := yaml.Marshal(&yamlDoc) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + if _, err := fmt.Fprintf(w, string(final)); err != nil { + return err + } + return nil +} + +func genFlagResult(flags *pflag.FlagSet) []cmdOption { + var result []cmdOption + + flags.VisitAll(func(flag *pflag.Flag) { + // Todo, when we mark a shorthand is deprecated, but specify an empty message. + // The flag.ShorthandDeprecated is empty as the shorthand is deprecated. + // Using len(flag.ShorthandDeprecated) > 0 can't handle this, others are ok. + if !(len(flag.ShorthandDeprecated) > 0) && len(flag.Shorthand) > 0 { + opt := cmdOption{ + flag.Name, + flag.Shorthand, + flag.DefValue, + forceMultiLine(flag.Usage), + } + result = append(result, opt) + } else { + opt := cmdOption{ + Name: flag.Name, + DefaultValue: forceMultiLine(flag.DefValue), + Usage: forceMultiLine(flag.Usage), + } + result = append(result, opt) + } + }) + + return result +} diff --git a/vendor/github.com/spf13/cobra/doc/yaml_docs.md b/vendor/github.com/spf13/cobra/doc/yaml_docs.md new file mode 100644 index 000000000..4d0c75a12 --- /dev/null +++ b/vendor/github.com/spf13/cobra/doc/yaml_docs.md @@ -0,0 +1,103 @@ +# Generating Yaml Docs For Your Own cobra.Command + +Generating yaml files from a cobra command is incredibly easy. An example is as follows: + +```go +package main + +import ( + "github.com/spf13/cobra" + "github.com/spf13/cobra/doc" +) + +func main() { + cmd := &cobra.Command{ + Use: "test", + Short: "my test program", + } + doc.GenYamlTree(cmd, "/tmp") +} +``` + +That will get you a Yaml document `/tmp/test.yaml` + +## Generate yaml docs for the entire command tree + +This program can actually generate docs for the kubectl command in the kubernetes project + +```go +package main + +import ( + "io/ioutil" + "os" + + "k8s.io/kubernetes/pkg/kubectl/cmd" + cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" + + "github.com/spf13/cobra/doc" +) + +func main() { + kubectl := cmd.NewKubectlCommand(cmdutil.NewFactory(nil), os.Stdin, ioutil.Discard, ioutil.Discard) + doc.GenYamlTree(kubectl, "./") +} +``` + +This will generate a whole series of files, one for each command in the tree, in the directory specified (in this case "./") + +## Generate yaml docs for a single command + +You may wish to have more control over the output, or only generate for a single command, instead of the entire command tree. If this is the case you may prefer to `GenYaml` instead of `GenYamlTree` + +```go + out := new(bytes.Buffer) + doc.GenYaml(cmd, out) +``` + +This will write the yaml doc for ONLY "cmd" into the out, buffer. + +## Customize the output + +Both `GenYaml` and `GenYamlTree` have alternate versions with callbacks to get some control of the output: + +```go +func GenYamlTreeCustom(cmd *Command, dir string, filePrepender, linkHandler func(string) string) error { + //... +} +``` + +```go +func GenYamlCustom(cmd *Command, out *bytes.Buffer, linkHandler func(string) string) error { + //... +} +``` + +The `filePrepender` will prepend the return value given the full filepath to the rendered Yaml file. A common use case is to add front matter to use the generated documentation with [Hugo](http://gohugo.io/): + +```go +const fmTemplate = `--- +date: %s +title: "%s" +slug: %s +url: %s +--- +` + +filePrepender := func(filename string) string { + now := time.Now().Format(time.RFC3339) + name := filepath.Base(filename) + base := strings.TrimSuffix(name, path.Ext(name)) + url := "/commands/" + strings.ToLower(base) + "/" + return fmt.Sprintf(fmTemplate, now, strings.Replace(base, "_", " ", -1), base, url) +} +``` + +The `linkHandler` can be used to customize the rendered internal links to the commands, given a filename: + +```go +linkHandler := func(name string) string { + base := strings.TrimSuffix(name, path.Ext(name)) + return "/commands/" + strings.ToLower(base) + "/" +} +``` diff --git a/vendor/github.com/spf13/cobra/doc/yaml_docs_test.go b/vendor/github.com/spf13/cobra/doc/yaml_docs_test.go new file mode 100644 index 000000000..a41499e1f --- /dev/null +++ b/vendor/github.com/spf13/cobra/doc/yaml_docs_test.go @@ -0,0 +1,88 @@ +package doc + +import ( + "bytes" + "fmt" + "os" + "strings" + "testing" +) + +var _ = fmt.Println +var _ = os.Stderr + +func TestGenYamlDoc(t *testing.T) { + c := initializeWithRootCmd() + // Need two commands to run the command alphabetical sort + cmdEcho.AddCommand(cmdTimes, cmdEchoSub, cmdDeprecated) + c.AddCommand(cmdPrint, cmdEcho) + cmdRootWithRun.PersistentFlags().StringVarP(&flags2a, "rootflag", "r", "two", strtwoParentHelp) + + out := new(bytes.Buffer) + + // We generate on s subcommand so we have both subcommands and parents + if err := GenYaml(cmdEcho, out); err != nil { + t.Fatal(err) + } + found := out.String() + + // Our description + expected := cmdEcho.Long + if !strings.Contains(found, expected) { + t.Errorf("Unexpected response.\nExpecting to contain: \n %q\nGot:\n %q\n", expected, found) + } + + // Better have our example + expected = cmdEcho.Example + if !strings.Contains(found, expected) { + t.Errorf("Unexpected response.\nExpecting to contain: \n %q\nGot:\n %q\n", expected, found) + } + + // A local flag + expected = "boolone" + if !strings.Contains(found, expected) { + t.Errorf("Unexpected response.\nExpecting to contain: \n %q\nGot:\n %q\n", expected, found) + } + + // persistent flag on parent + expected = "rootflag" + if !strings.Contains(found, expected) { + t.Errorf("Unexpected response.\nExpecting to contain: \n %q\nGot:\n %q\n", expected, found) + } + + // We better output info about our parent + expected = cmdRootWithRun.Short + if !strings.Contains(found, expected) { + t.Errorf("Unexpected response.\nExpecting to contain: \n %q\nGot:\n %q\n", expected, found) + } + + // And about subcommands + expected = cmdEchoSub.Short + if !strings.Contains(found, expected) { + t.Errorf("Unexpected response.\nExpecting to contain: \n %q\nGot:\n %q\n", expected, found) + } + + unexpected := cmdDeprecated.Short + if strings.Contains(found, unexpected) { + t.Errorf("Unexpected response.\nFound: %v\nBut should not have!!\n", unexpected) + } +} + +func TestGenYamlNoTag(t *testing.T) { + c := initializeWithRootCmd() + // Need two commands to run the command alphabetical sort + cmdEcho.AddCommand(cmdTimes, cmdEchoSub, cmdDeprecated) + c.AddCommand(cmdPrint, cmdEcho) + c.DisableAutoGenTag = true + cmdRootWithRun.PersistentFlags().StringVarP(&flags2a, "rootflag", "r", "two", strtwoParentHelp) + out := new(bytes.Buffer) + + if err := GenYaml(c, out); err != nil { + t.Fatal(err) + } + found := out.String() + + unexpected := "Auto generated" + checkStringOmits(t, found, unexpected) + +} diff --git a/vendor/github.com/spf13/pflag/.gitignore b/vendor/github.com/spf13/pflag/.gitignore new file mode 100644 index 000000000..c3da29013 --- /dev/null +++ b/vendor/github.com/spf13/pflag/.gitignore @@ -0,0 +1,2 @@ +.idea/* + diff --git a/vendor/github.com/spf13/pflag/README.md b/vendor/github.com/spf13/pflag/README.md index 08ad94565..eefb46dec 100644 --- a/vendor/github.com/spf13/pflag/README.md +++ b/vendor/github.com/spf13/pflag/README.md @@ -1,4 +1,6 @@ [![Build Status](https://travis-ci.org/spf13/pflag.svg?branch=master)](https://travis-ci.org/spf13/pflag) +[![Go Report Card](https://goreportcard.com/badge/github.com/spf13/pflag)](https://goreportcard.com/report/github.com/spf13/pflag) +[![GoDoc](https://godoc.org/github.com/spf13/pflag?status.svg)](https://godoc.org/github.com/spf13/pflag) ## Description @@ -106,9 +108,9 @@ that give one-letter shorthands for flags. You can use these by appending var ip = flag.IntP("flagname", "f", 1234, "help message") var flagvar bool func init() { - flag.BoolVarP("boolname", "b", true, "help message") + flag.BoolVarP(&flagvar, "boolname", "b", true, "help message") } -flag.VarP(&flagVar, "varname", "v", 1234, "help message") +flag.VarP(&flagVal, "varname", "v", "help message") ``` Shorthand letters can be used with single dashes on the command line. diff --git a/vendor/github.com/spf13/pflag/bool_slice.go b/vendor/github.com/spf13/pflag/bool_slice.go new file mode 100644 index 000000000..5af02f1a7 --- /dev/null +++ b/vendor/github.com/spf13/pflag/bool_slice.go @@ -0,0 +1,147 @@ +package pflag + +import ( + "io" + "strconv" + "strings" +) + +// -- boolSlice Value +type boolSliceValue struct { + value *[]bool + changed bool +} + +func newBoolSliceValue(val []bool, p *[]bool) *boolSliceValue { + bsv := new(boolSliceValue) + bsv.value = p + *bsv.value = val + return bsv +} + +// Set converts, and assigns, the comma-separated boolean argument string representation as the []bool value of this flag. +// If Set is called on a flag that already has a []bool assigned, the newly converted values will be appended. +func (s *boolSliceValue) Set(val string) error { + + // remove all quote characters + rmQuote := strings.NewReplacer(`"`, "", `'`, "", "`", "") + + // read flag arguments with CSV parser + boolStrSlice, err := readAsCSV(rmQuote.Replace(val)) + if err != nil && err != io.EOF { + return err + } + + // parse boolean values into slice + out := make([]bool, 0, len(boolStrSlice)) + for _, boolStr := range boolStrSlice { + b, err := strconv.ParseBool(strings.TrimSpace(boolStr)) + if err != nil { + return err + } + out = append(out, b) + } + + if !s.changed { + *s.value = out + } else { + *s.value = append(*s.value, out...) + } + + s.changed = true + + return nil +} + +// Type returns a string that uniquely represents this flag's type. +func (s *boolSliceValue) Type() string { + return "boolSlice" +} + +// String defines a "native" format for this boolean slice flag value. +func (s *boolSliceValue) String() string { + + boolStrSlice := make([]string, len(*s.value)) + for i, b := range *s.value { + boolStrSlice[i] = strconv.FormatBool(b) + } + + out, _ := writeAsCSV(boolStrSlice) + + return "[" + out + "]" +} + +func boolSliceConv(val string) (interface{}, error) { + val = strings.Trim(val, "[]") + // Empty string would cause a slice with one (empty) entry + if len(val) == 0 { + return []bool{}, nil + } + ss := strings.Split(val, ",") + out := make([]bool, len(ss)) + for i, t := range ss { + var err error + out[i], err = strconv.ParseBool(t) + if err != nil { + return nil, err + } + } + return out, nil +} + +// GetBoolSlice returns the []bool value of a flag with the given name. +func (f *FlagSet) GetBoolSlice(name string) ([]bool, error) { + val, err := f.getFlagType(name, "boolSlice", boolSliceConv) + if err != nil { + return []bool{}, err + } + return val.([]bool), nil +} + +// BoolSliceVar defines a boolSlice flag with specified name, default value, and usage string. +// The argument p points to a []bool variable in which to store the value of the flag. +func (f *FlagSet) BoolSliceVar(p *[]bool, name string, value []bool, usage string) { + f.VarP(newBoolSliceValue(value, p), name, "", usage) +} + +// BoolSliceVarP is like BoolSliceVar, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) BoolSliceVarP(p *[]bool, name, shorthand string, value []bool, usage string) { + f.VarP(newBoolSliceValue(value, p), name, shorthand, usage) +} + +// BoolSliceVar defines a []bool flag with specified name, default value, and usage string. +// The argument p points to a []bool variable in which to store the value of the flag. +func BoolSliceVar(p *[]bool, name string, value []bool, usage string) { + CommandLine.VarP(newBoolSliceValue(value, p), name, "", usage) +} + +// BoolSliceVarP is like BoolSliceVar, but accepts a shorthand letter that can be used after a single dash. +func BoolSliceVarP(p *[]bool, name, shorthand string, value []bool, usage string) { + CommandLine.VarP(newBoolSliceValue(value, p), name, shorthand, usage) +} + +// BoolSlice defines a []bool flag with specified name, default value, and usage string. +// The return value is the address of a []bool variable that stores the value of the flag. +func (f *FlagSet) BoolSlice(name string, value []bool, usage string) *[]bool { + p := []bool{} + f.BoolSliceVarP(&p, name, "", value, usage) + return &p +} + +// BoolSliceP is like BoolSlice, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) BoolSliceP(name, shorthand string, value []bool, usage string) *[]bool { + p := []bool{} + f.BoolSliceVarP(&p, name, shorthand, value, usage) + return &p +} + +// BoolSlice defines a []bool flag with specified name, default value, and usage string. +// The return value is the address of a []bool variable that stores the value of the flag. +func BoolSlice(name string, value []bool, usage string) *[]bool { + return CommandLine.BoolSliceP(name, "", value, usage) +} + +// BoolSliceP is like BoolSlice, but accepts a shorthand letter that can be used after a single dash. +func BoolSliceP(name, shorthand string, value []bool, usage string) *[]bool { + return CommandLine.BoolSliceP(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/bool_slice_test.go b/vendor/github.com/spf13/pflag/bool_slice_test.go new file mode 100644 index 000000000..b617dd237 --- /dev/null +++ b/vendor/github.com/spf13/pflag/bool_slice_test.go @@ -0,0 +1,215 @@ +package pflag + +import ( + "fmt" + "strconv" + "strings" + "testing" +) + +func setUpBSFlagSet(bsp *[]bool) *FlagSet { + f := NewFlagSet("test", ContinueOnError) + f.BoolSliceVar(bsp, "bs", []bool{}, "Command separated list!") + return f +} + +func setUpBSFlagSetWithDefault(bsp *[]bool) *FlagSet { + f := NewFlagSet("test", ContinueOnError) + f.BoolSliceVar(bsp, "bs", []bool{false, true}, "Command separated list!") + return f +} + +func TestEmptyBS(t *testing.T) { + var bs []bool + f := setUpBSFlagSet(&bs) + err := f.Parse([]string{}) + if err != nil { + t.Fatal("expected no error; got", err) + } + + getBS, err := f.GetBoolSlice("bs") + if err != nil { + t.Fatal("got an error from GetBoolSlice():", err) + } + if len(getBS) != 0 { + t.Fatalf("got bs %v with len=%d but expected length=0", getBS, len(getBS)) + } +} + +func TestBS(t *testing.T) { + var bs []bool + f := setUpBSFlagSet(&bs) + + vals := []string{"1", "F", "TRUE", "0"} + arg := fmt.Sprintf("--bs=%s", strings.Join(vals, ",")) + err := f.Parse([]string{arg}) + if err != nil { + t.Fatal("expected no error; got", err) + } + for i, v := range bs { + b, err := strconv.ParseBool(vals[i]) + if err != nil { + t.Fatalf("got error: %v", err) + } + if b != v { + t.Fatalf("expected is[%d] to be %s but got: %t", i, vals[i], v) + } + } + getBS, err := f.GetBoolSlice("bs") + if err != nil { + t.Fatalf("got error: %v", err) + } + for i, v := range getBS { + b, err := strconv.ParseBool(vals[i]) + if err != nil { + t.Fatalf("got error: %v", err) + } + if b != v { + t.Fatalf("expected bs[%d] to be %s but got: %t from GetBoolSlice", i, vals[i], v) + } + } +} + +func TestBSDefault(t *testing.T) { + var bs []bool + f := setUpBSFlagSetWithDefault(&bs) + + vals := []string{"false", "T"} + + err := f.Parse([]string{}) + if err != nil { + t.Fatal("expected no error; got", err) + } + for i, v := range bs { + b, err := strconv.ParseBool(vals[i]) + if err != nil { + t.Fatalf("got error: %v", err) + } + if b != v { + t.Fatalf("expected bs[%d] to be %t from GetBoolSlice but got: %t", i, b, v) + } + } + + getBS, err := f.GetBoolSlice("bs") + if err != nil { + t.Fatal("got an error from GetBoolSlice():", err) + } + for i, v := range getBS { + b, err := strconv.ParseBool(vals[i]) + if err != nil { + t.Fatal("got an error from GetBoolSlice():", err) + } + if b != v { + t.Fatalf("expected bs[%d] to be %t from GetBoolSlice but got: %t", i, b, v) + } + } +} + +func TestBSWithDefault(t *testing.T) { + var bs []bool + f := setUpBSFlagSetWithDefault(&bs) + + vals := []string{"FALSE", "1"} + arg := fmt.Sprintf("--bs=%s", strings.Join(vals, ",")) + err := f.Parse([]string{arg}) + if err != nil { + t.Fatal("expected no error; got", err) + } + for i, v := range bs { + b, err := strconv.ParseBool(vals[i]) + if err != nil { + t.Fatalf("got error: %v", err) + } + if b != v { + t.Fatalf("expected bs[%d] to be %t but got: %t", i, b, v) + } + } + + getBS, err := f.GetBoolSlice("bs") + if err != nil { + t.Fatal("got an error from GetBoolSlice():", err) + } + for i, v := range getBS { + b, err := strconv.ParseBool(vals[i]) + if err != nil { + t.Fatalf("got error: %v", err) + } + if b != v { + t.Fatalf("expected bs[%d] to be %t from GetBoolSlice but got: %t", i, b, v) + } + } +} + +func TestBSCalledTwice(t *testing.T) { + var bs []bool + f := setUpBSFlagSet(&bs) + + in := []string{"T,F", "T"} + expected := []bool{true, false, true} + argfmt := "--bs=%s" + arg1 := fmt.Sprintf(argfmt, in[0]) + arg2 := fmt.Sprintf(argfmt, in[1]) + err := f.Parse([]string{arg1, arg2}) + if err != nil { + t.Fatal("expected no error; got", err) + } + for i, v := range bs { + if expected[i] != v { + t.Fatalf("expected bs[%d] to be %t but got %t", i, expected[i], v) + } + } +} + +func TestBSBadQuoting(t *testing.T) { + + tests := []struct { + Want []bool + FlagArg []string + }{ + { + Want: []bool{true, false, true}, + FlagArg: []string{"1", "0", "true"}, + }, + { + Want: []bool{true, false}, + FlagArg: []string{"True", "F"}, + }, + { + Want: []bool{true, false}, + FlagArg: []string{"T", "0"}, + }, + { + Want: []bool{true, false}, + FlagArg: []string{"1", "0"}, + }, + { + Want: []bool{true, false, false}, + FlagArg: []string{"true,false", "false"}, + }, + { + Want: []bool{true, false, false, true, false, true, false}, + FlagArg: []string{`"true,false,false,1,0, T"`, " false "}, + }, + { + Want: []bool{false, false, true, false, true, false, true}, + FlagArg: []string{`"0, False, T,false , true,F"`, "true"}, + }, + } + + for i, test := range tests { + + var bs []bool + f := setUpBSFlagSet(&bs) + + if err := f.Parse([]string{fmt.Sprintf("--bs=%s", strings.Join(test.FlagArg, ","))}); err != nil { + t.Fatalf("flag parsing failed with error: %s\nparsing:\t%#v\nwant:\t\t%#v", + err, test.FlagArg, test.Want[i]) + } + + for j, b := range bs { + if b != test.Want[j] { + t.Fatalf("bad value parsed for test %d on bool %d:\nwant:\t%t\ngot:\t%t", i, j, test.Want[j], b) + } + } + } +} diff --git a/vendor/github.com/spf13/pflag/flag.go b/vendor/github.com/spf13/pflag/flag.go index fa815642e..746af6327 100644 --- a/vendor/github.com/spf13/pflag/flag.go +++ b/vendor/github.com/spf13/pflag/flag.go @@ -487,9 +487,76 @@ func UnquoteUsage(flag *Flag) (name string, usage string) { return } -// FlagUsages Returns a string containing the usage information for all flags in -// the FlagSet -func (f *FlagSet) FlagUsages() string { +// Splits the string `s` on whitespace into an initial substring up to +// `i` runes in length and the remainder. Will go `slop` over `i` if +// that encompasses the entire string (which allows the caller to +// avoid short orphan words on the final line). +func wrapN(i, slop int, s string) (string, string) { + if i+slop > len(s) { + return s, "" + } + + w := strings.LastIndexAny(s[:i], " \t") + if w <= 0 { + return s, "" + } + + return s[:w], s[w+1:] +} + +// Wraps the string `s` to a maximum width `w` with leading indent +// `i`. The first line is not indented (this is assumed to be done by +// caller). Pass `w` == 0 to do no wrapping +func wrap(i, w int, s string) string { + if w == 0 { + return s + } + + // space between indent i and end of line width w into which + // we should wrap the text. + wrap := w - i + + var r, l string + + // Not enough space for sensible wrapping. Wrap as a block on + // the next line instead. + if wrap < 24 { + i = 16 + wrap = w - i + r += "\n" + strings.Repeat(" ", i) + } + // If still not enough space then don't even try to wrap. + if wrap < 24 { + return s + } + + // Try to avoid short orphan words on the final line, by + // allowing wrapN to go a bit over if that would fit in the + // remainder of the line. + slop := 5 + wrap = wrap - slop + + // Handle first line, which is indented by the caller (or the + // special case above) + l, s = wrapN(wrap, slop, s) + r = r + l + + // Now wrap the rest + for s != "" { + var t string + + t, s = wrapN(wrap, slop, s) + r = r + "\n" + strings.Repeat(" ", i) + t + } + + return r + +} + +// FlagUsagesWrapped returns a string containing the usage information +// for all flags in the FlagSet. Wrapped to `cols` columns (0 for no +// wrapping) +func (f *FlagSet) FlagUsagesWrapped(cols int) string { x := new(bytes.Buffer) lines := make([]string, 0, len(f.formal)) @@ -546,12 +613,19 @@ func (f *FlagSet) FlagUsages() string { for _, line := range lines { sidx := strings.Index(line, "\x00") spacing := strings.Repeat(" ", maxlen-sidx) - fmt.Fprintln(x, line[:sidx], spacing, line[sidx+1:]) + // maxlen + 2 comes from + 1 for the \x00 and + 1 for the (deliberate) off-by-one in maxlen-sidx + fmt.Fprintln(x, line[:sidx], spacing, wrap(maxlen+2, cols, line[sidx+1:])) } return x.String() } +// FlagUsages returns a string containing the usage information for all flags in +// the FlagSet +func (f *FlagSet) FlagUsages() string { + return f.FlagUsagesWrapped(0) +} + // PrintDefaults prints to standard error the default values of all defined command-line flags. func PrintDefaults() { CommandLine.PrintDefaults() @@ -635,7 +709,7 @@ func (f *FlagSet) VarPF(value Value, name, shorthand, usage string) *Flag { // VarP is like Var, but accepts a shorthand letter that can be used after a single dash. func (f *FlagSet) VarP(value Value, name, shorthand, usage string) { - _ = f.VarPF(value, name, shorthand, usage) + f.VarPF(value, name, shorthand, usage) } // AddFlag will add the flag to the FlagSet @@ -752,7 +826,7 @@ func containsShorthand(arg, shorthand string) bool { return strings.Contains(arg, shorthand) } -func (f *FlagSet) parseLongArg(s string, args []string) (a []string, err error) { +func (f *FlagSet) parseLongArg(s string, args []string, fn parseFunc) (a []string, err error) { a = args name := s[2:] if len(name) == 0 || name[0] == '-' || name[0] == '=' { @@ -786,11 +860,11 @@ func (f *FlagSet) parseLongArg(s string, args []string) (a []string, err error) err = f.failf("flag needs an argument: %s", s) return } - err = f.setFlag(flag, value, s) + err = fn(flag, value, s) return } -func (f *FlagSet) parseSingleShortArg(shorthands string, args []string) (outShorts string, outArgs []string, err error) { +func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parseFunc) (outShorts string, outArgs []string, err error) { if strings.HasPrefix(shorthands, "test.") { return } @@ -825,16 +899,16 @@ func (f *FlagSet) parseSingleShortArg(shorthands string, args []string) (outShor err = f.failf("flag needs an argument: %q in -%s", c, shorthands) return } - err = f.setFlag(flag, value, shorthands) + err = fn(flag, value, shorthands) return } -func (f *FlagSet) parseShortArg(s string, args []string) (a []string, err error) { +func (f *FlagSet) parseShortArg(s string, args []string, fn parseFunc) (a []string, err error) { a = args shorthands := s[1:] for len(shorthands) > 0 { - shorthands, a, err = f.parseSingleShortArg(shorthands, args) + shorthands, a, err = f.parseSingleShortArg(shorthands, args, fn) if err != nil { return } @@ -843,7 +917,7 @@ func (f *FlagSet) parseShortArg(s string, args []string) (a []string, err error) return } -func (f *FlagSet) parseArgs(args []string) (err error) { +func (f *FlagSet) parseArgs(args []string, fn parseFunc) (err error) { for len(args) > 0 { s := args[0] args = args[1:] @@ -863,9 +937,9 @@ func (f *FlagSet) parseArgs(args []string) (err error) { f.args = append(f.args, args...) break } - args, err = f.parseLongArg(s, args) + args, err = f.parseLongArg(s, args, fn) } else { - args, err = f.parseShortArg(s, args) + args, err = f.parseShortArg(s, args, fn) } if err != nil { return @@ -881,7 +955,41 @@ func (f *FlagSet) parseArgs(args []string) (err error) { func (f *FlagSet) Parse(arguments []string) error { f.parsed = true f.args = make([]string, 0, len(arguments)) - err := f.parseArgs(arguments) + + assign := func(flag *Flag, value, origArg string) error { + return f.setFlag(flag, value, origArg) + } + + err := f.parseArgs(arguments, assign) + if err != nil { + switch f.errorHandling { + case ContinueOnError: + return err + case ExitOnError: + os.Exit(2) + case PanicOnError: + panic(err) + } + } + return nil +} + +type parseFunc func(flag *Flag, value, origArg string) error + +// ParseAll parses flag definitions from the argument list, which should not +// include the command name. The arguments for fn are flag and value. Must be +// called after all flags in the FlagSet are defined and before flags are +// accessed by the program. The return value will be ErrHelp if -help was set +// but not defined. +func (f *FlagSet) ParseAll(arguments []string, fn func(flag *Flag, value string) error) error { + f.parsed = true + f.args = make([]string, 0, len(arguments)) + + assign := func(flag *Flag, value, origArg string) error { + return fn(flag, value) + } + + err := f.parseArgs(arguments, assign) if err != nil { switch f.errorHandling { case ContinueOnError: @@ -907,6 +1015,14 @@ func Parse() { CommandLine.Parse(os.Args[1:]) } +// ParseAll parses the command-line flags from os.Args[1:] and called fn for each. +// The arguments for fn are flag and value. Must be called after all flags are +// defined and before flags are accessed by the program. +func ParseAll(fn func(flag *Flag, value string) error) { + // Ignore errors; CommandLine is set for ExitOnError. + CommandLine.ParseAll(os.Args[1:], fn) +} + // SetInterspersed sets whether to support interspersed option/non-option arguments. func SetInterspersed(interspersed bool) { CommandLine.SetInterspersed(interspersed) diff --git a/vendor/github.com/spf13/pflag/flag_test.go b/vendor/github.com/spf13/pflag/flag_test.go index b294fc768..b83a0ed6a 100644 --- a/vendor/github.com/spf13/pflag/flag_test.go +++ b/vendor/github.com/spf13/pflag/flag_test.go @@ -333,6 +333,59 @@ func testParse(f *FlagSet, t *testing.T) { } } +func testParseAll(f *FlagSet, t *testing.T) { + if f.Parsed() { + fmt.Errorf("f.Parse() = true before Parse") + } + f.BoolP("boola", "a", false, "bool value") + f.BoolP("boolb", "b", false, "bool2 value") + f.BoolP("boolc", "c", false, "bool3 value") + f.BoolP("boold", "d", false, "bool4 value") + f.StringP("stringa", "s", "0", "string value") + f.StringP("stringz", "z", "0", "string value") + f.StringP("stringx", "x", "0", "string value") + f.StringP("stringy", "y", "0", "string value") + f.Lookup("stringx").NoOptDefVal = "1" + args := []string{ + "-ab", + "-cs=xx", + "--stringz=something", + "-d=true", + "-x", + "-y", + "ee", + } + want := []string{ + "boola", "true", + "boolb", "true", + "boolc", "true", + "stringa", "xx", + "stringz", "something", + "boold", "true", + "stringx", "1", + "stringy", "ee", + } + got := []string{} + store := func(flag *Flag, value string) error { + got = append(got, flag.Name) + if len(value) > 0 { + got = append(got, value) + } + return nil + } + if err := f.ParseAll(args, store); err != nil { + t.Errorf("expected no error, got ", err) + } + if !f.Parsed() { + t.Errorf("f.Parse() = false after Parse") + } + if !reflect.DeepEqual(got, want) { + t.Errorf("f.ParseAll() fail to restore the args") + t.Errorf("Got: %v", got) + t.Errorf("Want: %v", want) + } +} + func TestShorthand(t *testing.T) { f := NewFlagSet("shorthand", ContinueOnError) if f.Parsed() { @@ -398,16 +451,21 @@ func TestParse(t *testing.T) { testParse(GetCommandLine(), t) } +func TestParseAll(t *testing.T) { + ResetForTesting(func() { t.Error("bad parse") }) + testParseAll(GetCommandLine(), t) +} + func TestFlagSetParse(t *testing.T) { testParse(NewFlagSet("test", ContinueOnError), t) } func TestChangedHelper(t *testing.T) { f := NewFlagSet("changedtest", ContinueOnError) - _ = f.Bool("changed", false, "changed bool") - _ = f.Bool("settrue", true, "true to true") - _ = f.Bool("setfalse", false, "false to false") - _ = f.Bool("unchanged", false, "unchanged bool") + f.Bool("changed", false, "changed bool") + f.Bool("settrue", true, "true to true") + f.Bool("setfalse", false, "false to false") + f.Bool("unchanged", false, "unchanged bool") args := []string{"--changed", "--settrue", "--setfalse=false"} if err := f.Parse(args); err != nil { diff --git a/vendor/github.com/spf13/pflag/golangflag.go b/vendor/github.com/spf13/pflag/golangflag.go index b056147fd..c4f47ebe5 100644 --- a/vendor/github.com/spf13/pflag/golangflag.go +++ b/vendor/github.com/spf13/pflag/golangflag.go @@ -6,13 +6,10 @@ package pflag import ( goflag "flag" - "fmt" "reflect" "strings" ) -var _ = fmt.Print - // flagValueWrapper implements pflag.Value around a flag.Value. The main // difference here is the addition of the Type method that returns a string // name of the type. As this is generally unknown, we approximate that with diff --git a/vendor/github.com/spf13/pflag/ip.go b/vendor/github.com/spf13/pflag/ip.go index 88a17430a..3d414ba69 100644 --- a/vendor/github.com/spf13/pflag/ip.go +++ b/vendor/github.com/spf13/pflag/ip.go @@ -6,8 +6,6 @@ import ( "strings" ) -var _ = strings.TrimSpace - // -- net.IP value type ipValue net.IP diff --git a/vendor/github.com/spf13/pflag/ip_slice.go b/vendor/github.com/spf13/pflag/ip_slice.go new file mode 100644 index 000000000..7dd196fe3 --- /dev/null +++ b/vendor/github.com/spf13/pflag/ip_slice.go @@ -0,0 +1,148 @@ +package pflag + +import ( + "fmt" + "io" + "net" + "strings" +) + +// -- ipSlice Value +type ipSliceValue struct { + value *[]net.IP + changed bool +} + +func newIPSliceValue(val []net.IP, p *[]net.IP) *ipSliceValue { + ipsv := new(ipSliceValue) + ipsv.value = p + *ipsv.value = val + return ipsv +} + +// Set converts, and assigns, the comma-separated IP argument string representation as the []net.IP value of this flag. +// If Set is called on a flag that already has a []net.IP assigned, the newly converted values will be appended. +func (s *ipSliceValue) Set(val string) error { + + // remove all quote characters + rmQuote := strings.NewReplacer(`"`, "", `'`, "", "`", "") + + // read flag arguments with CSV parser + ipStrSlice, err := readAsCSV(rmQuote.Replace(val)) + if err != nil && err != io.EOF { + return err + } + + // parse ip values into slice + out := make([]net.IP, 0, len(ipStrSlice)) + for _, ipStr := range ipStrSlice { + ip := net.ParseIP(strings.TrimSpace(ipStr)) + if ip == nil { + return fmt.Errorf("invalid string being converted to IP address: %s", ipStr) + } + out = append(out, ip) + } + + if !s.changed { + *s.value = out + } else { + *s.value = append(*s.value, out...) + } + + s.changed = true + + return nil +} + +// Type returns a string that uniquely represents this flag's type. +func (s *ipSliceValue) Type() string { + return "ipSlice" +} + +// String defines a "native" format for this net.IP slice flag value. +func (s *ipSliceValue) String() string { + + ipStrSlice := make([]string, len(*s.value)) + for i, ip := range *s.value { + ipStrSlice[i] = ip.String() + } + + out, _ := writeAsCSV(ipStrSlice) + + return "[" + out + "]" +} + +func ipSliceConv(val string) (interface{}, error) { + val = strings.Trim(val, "[]") + // Emtpy string would cause a slice with one (empty) entry + if len(val) == 0 { + return []net.IP{}, nil + } + ss := strings.Split(val, ",") + out := make([]net.IP, len(ss)) + for i, sval := range ss { + ip := net.ParseIP(strings.TrimSpace(sval)) + if ip == nil { + return nil, fmt.Errorf("invalid string being converted to IP address: %s", sval) + } + out[i] = ip + } + return out, nil +} + +// GetIPSlice returns the []net.IP value of a flag with the given name +func (f *FlagSet) GetIPSlice(name string) ([]net.IP, error) { + val, err := f.getFlagType(name, "ipSlice", ipSliceConv) + if err != nil { + return []net.IP{}, err + } + return val.([]net.IP), nil +} + +// IPSliceVar defines a ipSlice flag with specified name, default value, and usage string. +// The argument p points to a []net.IP variable in which to store the value of the flag. +func (f *FlagSet) IPSliceVar(p *[]net.IP, name string, value []net.IP, usage string) { + f.VarP(newIPSliceValue(value, p), name, "", usage) +} + +// IPSliceVarP is like IPSliceVar, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) IPSliceVarP(p *[]net.IP, name, shorthand string, value []net.IP, usage string) { + f.VarP(newIPSliceValue(value, p), name, shorthand, usage) +} + +// IPSliceVar defines a []net.IP flag with specified name, default value, and usage string. +// The argument p points to a []net.IP variable in which to store the value of the flag. +func IPSliceVar(p *[]net.IP, name string, value []net.IP, usage string) { + CommandLine.VarP(newIPSliceValue(value, p), name, "", usage) +} + +// IPSliceVarP is like IPSliceVar, but accepts a shorthand letter that can be used after a single dash. +func IPSliceVarP(p *[]net.IP, name, shorthand string, value []net.IP, usage string) { + CommandLine.VarP(newIPSliceValue(value, p), name, shorthand, usage) +} + +// IPSlice defines a []net.IP flag with specified name, default value, and usage string. +// The return value is the address of a []net.IP variable that stores the value of that flag. +func (f *FlagSet) IPSlice(name string, value []net.IP, usage string) *[]net.IP { + p := []net.IP{} + f.IPSliceVarP(&p, name, "", value, usage) + return &p +} + +// IPSliceP is like IPSlice, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) IPSliceP(name, shorthand string, value []net.IP, usage string) *[]net.IP { + p := []net.IP{} + f.IPSliceVarP(&p, name, shorthand, value, usage) + return &p +} + +// IPSlice defines a []net.IP flag with specified name, default value, and usage string. +// The return value is the address of a []net.IP variable that stores the value of the flag. +func IPSlice(name string, value []net.IP, usage string) *[]net.IP { + return CommandLine.IPSliceP(name, "", value, usage) +} + +// IPSliceP is like IPSlice, but accepts a shorthand letter that can be used after a single dash. +func IPSliceP(name, shorthand string, value []net.IP, usage string) *[]net.IP { + return CommandLine.IPSliceP(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/ip_slice_test.go b/vendor/github.com/spf13/pflag/ip_slice_test.go new file mode 100644 index 000000000..b0c681c5b --- /dev/null +++ b/vendor/github.com/spf13/pflag/ip_slice_test.go @@ -0,0 +1,222 @@ +package pflag + +import ( + "fmt" + "net" + "strings" + "testing" +) + +func setUpIPSFlagSet(ipsp *[]net.IP) *FlagSet { + f := NewFlagSet("test", ContinueOnError) + f.IPSliceVar(ipsp, "ips", []net.IP{}, "Command separated list!") + return f +} + +func setUpIPSFlagSetWithDefault(ipsp *[]net.IP) *FlagSet { + f := NewFlagSet("test", ContinueOnError) + f.IPSliceVar(ipsp, "ips", + []net.IP{ + net.ParseIP("192.168.1.1"), + net.ParseIP("0:0:0:0:0:0:0:1"), + }, + "Command separated list!") + return f +} + +func TestEmptyIP(t *testing.T) { + var ips []net.IP + f := setUpIPSFlagSet(&ips) + err := f.Parse([]string{}) + if err != nil { + t.Fatal("expected no error; got", err) + } + + getIPS, err := f.GetIPSlice("ips") + if err != nil { + t.Fatal("got an error from GetIPSlice():", err) + } + if len(getIPS) != 0 { + t.Fatalf("got ips %v with len=%d but expected length=0", getIPS, len(getIPS)) + } +} + +func TestIPS(t *testing.T) { + var ips []net.IP + f := setUpIPSFlagSet(&ips) + + vals := []string{"192.168.1.1", "10.0.0.1", "0:0:0:0:0:0:0:2"} + arg := fmt.Sprintf("--ips=%s", strings.Join(vals, ",")) + err := f.Parse([]string{arg}) + if err != nil { + t.Fatal("expected no error; got", err) + } + for i, v := range ips { + if ip := net.ParseIP(vals[i]); ip == nil { + t.Fatalf("invalid string being converted to IP address: %s", vals[i]) + } else if !ip.Equal(v) { + t.Fatalf("expected ips[%d] to be %s but got: %s from GetIPSlice", i, vals[i], v) + } + } +} + +func TestIPSDefault(t *testing.T) { + var ips []net.IP + f := setUpIPSFlagSetWithDefault(&ips) + + vals := []string{"192.168.1.1", "0:0:0:0:0:0:0:1"} + err := f.Parse([]string{}) + if err != nil { + t.Fatal("expected no error; got", err) + } + for i, v := range ips { + if ip := net.ParseIP(vals[i]); ip == nil { + t.Fatalf("invalid string being converted to IP address: %s", vals[i]) + } else if !ip.Equal(v) { + t.Fatalf("expected ips[%d] to be %s but got: %s", i, vals[i], v) + } + } + + getIPS, err := f.GetIPSlice("ips") + if err != nil { + t.Fatal("got an error from GetIPSlice") + } + for i, v := range getIPS { + if ip := net.ParseIP(vals[i]); ip == nil { + t.Fatalf("invalid string being converted to IP address: %s", vals[i]) + } else if !ip.Equal(v) { + t.Fatalf("expected ips[%d] to be %s but got: %s", i, vals[i], v) + } + } +} + +func TestIPSWithDefault(t *testing.T) { + var ips []net.IP + f := setUpIPSFlagSetWithDefault(&ips) + + vals := []string{"192.168.1.1", "0:0:0:0:0:0:0:1"} + arg := fmt.Sprintf("--ips=%s", strings.Join(vals, ",")) + err := f.Parse([]string{arg}) + if err != nil { + t.Fatal("expected no error; got", err) + } + for i, v := range ips { + if ip := net.ParseIP(vals[i]); ip == nil { + t.Fatalf("invalid string being converted to IP address: %s", vals[i]) + } else if !ip.Equal(v) { + t.Fatalf("expected ips[%d] to be %s but got: %s", i, vals[i], v) + } + } + + getIPS, err := f.GetIPSlice("ips") + if err != nil { + t.Fatal("got an error from GetIPSlice") + } + for i, v := range getIPS { + if ip := net.ParseIP(vals[i]); ip == nil { + t.Fatalf("invalid string being converted to IP address: %s", vals[i]) + } else if !ip.Equal(v) { + t.Fatalf("expected ips[%d] to be %s but got: %s", i, vals[i], v) + } + } +} + +func TestIPSCalledTwice(t *testing.T) { + var ips []net.IP + f := setUpIPSFlagSet(&ips) + + in := []string{"192.168.1.2,0:0:0:0:0:0:0:1", "10.0.0.1"} + expected := []net.IP{net.ParseIP("192.168.1.2"), net.ParseIP("0:0:0:0:0:0:0:1"), net.ParseIP("10.0.0.1")} + argfmt := "ips=%s" + arg1 := fmt.Sprintf(argfmt, in[0]) + arg2 := fmt.Sprintf(argfmt, in[1]) + err := f.Parse([]string{arg1, arg2}) + if err != nil { + t.Fatal("expected no error; got", err) + } + for i, v := range ips { + if !expected[i].Equal(v) { + t.Fatalf("expected ips[%d] to be %s but got: %s", i, expected[i], v) + } + } +} + +func TestIPSBadQuoting(t *testing.T) { + + tests := []struct { + Want []net.IP + FlagArg []string + }{ + { + Want: []net.IP{ + net.ParseIP("a4ab:61d:f03e:5d7d:fad7:d4c2:a1a5:568"), + net.ParseIP("203.107.49.208"), + net.ParseIP("14.57.204.90"), + }, + FlagArg: []string{ + "a4ab:61d:f03e:5d7d:fad7:d4c2:a1a5:568", + "203.107.49.208", + "14.57.204.90", + }, + }, + { + Want: []net.IP{ + net.ParseIP("204.228.73.195"), + net.ParseIP("86.141.15.94"), + }, + FlagArg: []string{ + "204.228.73.195", + "86.141.15.94", + }, + }, + { + Want: []net.IP{ + net.ParseIP("c70c:db36:3001:890f:c6ea:3f9b:7a39:cc3f"), + net.ParseIP("4d17:1d6e:e699:bd7a:88c5:5e7e:ac6a:4472"), + }, + FlagArg: []string{ + "c70c:db36:3001:890f:c6ea:3f9b:7a39:cc3f", + "4d17:1d6e:e699:bd7a:88c5:5e7e:ac6a:4472", + }, + }, + { + Want: []net.IP{ + net.ParseIP("5170:f971:cfac:7be3:512a:af37:952c:bc33"), + net.ParseIP("93.21.145.140"), + net.ParseIP("2cac:61d3:c5ff:6caf:73e0:1b1a:c336:c1ca"), + }, + FlagArg: []string{ + " 5170:f971:cfac:7be3:512a:af37:952c:bc33 , 93.21.145.140 ", + "2cac:61d3:c5ff:6caf:73e0:1b1a:c336:c1ca", + }, + }, + { + Want: []net.IP{ + net.ParseIP("2e5e:66b2:6441:848:5b74:76ea:574c:3a7b"), + net.ParseIP("2e5e:66b2:6441:848:5b74:76ea:574c:3a7b"), + net.ParseIP("2e5e:66b2:6441:848:5b74:76ea:574c:3a7b"), + net.ParseIP("2e5e:66b2:6441:848:5b74:76ea:574c:3a7b"), + }, + FlagArg: []string{ + `"2e5e:66b2:6441:848:5b74:76ea:574c:3a7b, 2e5e:66b2:6441:848:5b74:76ea:574c:3a7b,2e5e:66b2:6441:848:5b74:76ea:574c:3a7b "`, + " 2e5e:66b2:6441:848:5b74:76ea:574c:3a7b"}, + }, + } + + for i, test := range tests { + + var ips []net.IP + f := setUpIPSFlagSet(&ips) + + if err := f.Parse([]string{fmt.Sprintf("--ips=%s", strings.Join(test.FlagArg, ","))}); err != nil { + t.Fatalf("flag parsing failed with error: %s\nparsing:\t%#v\nwant:\t\t%s", + err, test.FlagArg, test.Want[i]) + } + + for j, b := range ips { + if !b.Equal(test.Want[j]) { + t.Fatalf("bad value parsed for test %d on net.IP %d:\nwant:\t%s\ngot:\t%s", i, j, test.Want[j], b) + } + } + } +} diff --git a/vendor/github.com/spf13/pflag/ipnet.go b/vendor/github.com/spf13/pflag/ipnet.go index 149b764b1..e2c1b8bcd 100644 --- a/vendor/github.com/spf13/pflag/ipnet.go +++ b/vendor/github.com/spf13/pflag/ipnet.go @@ -27,8 +27,6 @@ func (*ipNetValue) Type() string { return "ipNet" } -var _ = strings.TrimSpace - func newIPNetValue(val net.IPNet, p *net.IPNet) *ipNetValue { *p = val return (*ipNetValue)(p) diff --git a/vendor/github.com/spf13/pflag/string_array.go b/vendor/github.com/spf13/pflag/string_array.go index 93b4e4329..276b7ed49 100644 --- a/vendor/github.com/spf13/pflag/string_array.go +++ b/vendor/github.com/spf13/pflag/string_array.go @@ -1,11 +1,5 @@ package pflag -import ( - "fmt" -) - -var _ = fmt.Fprint - // -- stringArray Value type stringArrayValue struct { value *[]string diff --git a/vendor/github.com/spf13/pflag/string_slice.go b/vendor/github.com/spf13/pflag/string_slice.go index 7829cfafb..05eee7543 100644 --- a/vendor/github.com/spf13/pflag/string_slice.go +++ b/vendor/github.com/spf13/pflag/string_slice.go @@ -3,12 +3,9 @@ package pflag import ( "bytes" "encoding/csv" - "fmt" "strings" ) -var _ = fmt.Fprint - // -- stringSlice Value type stringSliceValue struct { value *[]string @@ -39,7 +36,7 @@ func writeAsCSV(vals []string) (string, error) { return "", err } w.Flush() - return strings.TrimSuffix(b.String(), fmt.Sprintln()), nil + return strings.TrimSuffix(b.String(), "\n"), nil } func (s *stringSliceValue) Set(val string) error { diff --git a/vendor/github.com/spf13/pflag/uint_slice.go b/vendor/github.com/spf13/pflag/uint_slice.go new file mode 100644 index 000000000..edd94c600 --- /dev/null +++ b/vendor/github.com/spf13/pflag/uint_slice.go @@ -0,0 +1,126 @@ +package pflag + +import ( + "fmt" + "strconv" + "strings" +) + +// -- uintSlice Value +type uintSliceValue struct { + value *[]uint + changed bool +} + +func newUintSliceValue(val []uint, p *[]uint) *uintSliceValue { + uisv := new(uintSliceValue) + uisv.value = p + *uisv.value = val + return uisv +} + +func (s *uintSliceValue) Set(val string) error { + ss := strings.Split(val, ",") + out := make([]uint, len(ss)) + for i, d := range ss { + u, err := strconv.ParseUint(d, 10, 0) + if err != nil { + return err + } + out[i] = uint(u) + } + if !s.changed { + *s.value = out + } else { + *s.value = append(*s.value, out...) + } + s.changed = true + return nil +} + +func (s *uintSliceValue) Type() string { + return "uintSlice" +} + +func (s *uintSliceValue) String() string { + out := make([]string, len(*s.value)) + for i, d := range *s.value { + out[i] = fmt.Sprintf("%d", d) + } + return "[" + strings.Join(out, ",") + "]" +} + +func uintSliceConv(val string) (interface{}, error) { + val = strings.Trim(val, "[]") + // Empty string would cause a slice with one (empty) entry + if len(val) == 0 { + return []uint{}, nil + } + ss := strings.Split(val, ",") + out := make([]uint, len(ss)) + for i, d := range ss { + u, err := strconv.ParseUint(d, 10, 0) + if err != nil { + return nil, err + } + out[i] = uint(u) + } + return out, nil +} + +// GetUintSlice returns the []uint value of a flag with the given name. +func (f *FlagSet) GetUintSlice(name string) ([]uint, error) { + val, err := f.getFlagType(name, "uintSlice", uintSliceConv) + if err != nil { + return []uint{}, err + } + return val.([]uint), nil +} + +// UintSliceVar defines a uintSlice flag with specified name, default value, and usage string. +// The argument p points to a []uint variable in which to store the value of the flag. +func (f *FlagSet) UintSliceVar(p *[]uint, name string, value []uint, usage string) { + f.VarP(newUintSliceValue(value, p), name, "", usage) +} + +// UintSliceVarP is like UintSliceVar, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) UintSliceVarP(p *[]uint, name, shorthand string, value []uint, usage string) { + f.VarP(newUintSliceValue(value, p), name, shorthand, usage) +} + +// UintSliceVar defines a uint[] flag with specified name, default value, and usage string. +// The argument p points to a uint[] variable in which to store the value of the flag. +func UintSliceVar(p *[]uint, name string, value []uint, usage string) { + CommandLine.VarP(newUintSliceValue(value, p), name, "", usage) +} + +// UintSliceVarP is like the UintSliceVar, but accepts a shorthand letter that can be used after a single dash. +func UintSliceVarP(p *[]uint, name, shorthand string, value []uint, usage string) { + CommandLine.VarP(newUintSliceValue(value, p), name, shorthand, usage) +} + +// UintSlice defines a []uint flag with specified name, default value, and usage string. +// The return value is the address of a []uint variable that stores the value of the flag. +func (f *FlagSet) UintSlice(name string, value []uint, usage string) *[]uint { + p := []uint{} + f.UintSliceVarP(&p, name, "", value, usage) + return &p +} + +// UintSliceP is like UintSlice, but accepts a shorthand letter that can be used after a single dash. +func (f *FlagSet) UintSliceP(name, shorthand string, value []uint, usage string) *[]uint { + p := []uint{} + f.UintSliceVarP(&p, name, shorthand, value, usage) + return &p +} + +// UintSlice defines a []uint flag with specified name, default value, and usage string. +// The return value is the address of a []uint variable that stores the value of the flag. +func UintSlice(name string, value []uint, usage string) *[]uint { + return CommandLine.UintSliceP(name, "", value, usage) +} + +// UintSliceP is like UintSlice, but accepts a shorthand letter that can be used after a single dash. +func UintSliceP(name, shorthand string, value []uint, usage string) *[]uint { + return CommandLine.UintSliceP(name, shorthand, value, usage) +} diff --git a/vendor/github.com/spf13/pflag/uint_slice_test.go b/vendor/github.com/spf13/pflag/uint_slice_test.go new file mode 100644 index 000000000..db1a19dc2 --- /dev/null +++ b/vendor/github.com/spf13/pflag/uint_slice_test.go @@ -0,0 +1,161 @@ +package pflag + +import ( + "fmt" + "strconv" + "strings" + "testing" +) + +func setUpUISFlagSet(uisp *[]uint) *FlagSet { + f := NewFlagSet("test", ContinueOnError) + f.UintSliceVar(uisp, "uis", []uint{}, "Command separated list!") + return f +} + +func setUpUISFlagSetWithDefault(uisp *[]uint) *FlagSet { + f := NewFlagSet("test", ContinueOnError) + f.UintSliceVar(uisp, "uis", []uint{0, 1}, "Command separated list!") + return f +} + +func TestEmptyUIS(t *testing.T) { + var uis []uint + f := setUpUISFlagSet(&uis) + err := f.Parse([]string{}) + if err != nil { + t.Fatal("expected no error; got", err) + } + + getUIS, err := f.GetUintSlice("uis") + if err != nil { + t.Fatal("got an error from GetUintSlice():", err) + } + if len(getUIS) != 0 { + t.Fatalf("got is %v with len=%d but expected length=0", getUIS, len(getUIS)) + } +} + +func TestUIS(t *testing.T) { + var uis []uint + f := setUpUISFlagSet(&uis) + + vals := []string{"1", "2", "4", "3"} + arg := fmt.Sprintf("--uis=%s", strings.Join(vals, ",")) + err := f.Parse([]string{arg}) + if err != nil { + t.Fatal("expected no error; got", err) + } + for i, v := range uis { + u, err := strconv.ParseUint(vals[i], 10, 0) + if err != nil { + t.Fatalf("got error: %v", err) + } + if uint(u) != v { + t.Fatalf("expected uis[%d] to be %s but got %d", i, vals[i], v) + } + } + getUIS, err := f.GetUintSlice("uis") + if err != nil { + t.Fatalf("got error: %v", err) + } + for i, v := range getUIS { + u, err := strconv.ParseUint(vals[i], 10, 0) + if err != nil { + t.Fatalf("got error: %v", err) + } + if uint(u) != v { + t.Fatalf("expected uis[%d] to be %s but got: %d from GetUintSlice", i, vals[i], v) + } + } +} + +func TestUISDefault(t *testing.T) { + var uis []uint + f := setUpUISFlagSetWithDefault(&uis) + + vals := []string{"0", "1"} + + err := f.Parse([]string{}) + if err != nil { + t.Fatal("expected no error; got", err) + } + for i, v := range uis { + u, err := strconv.ParseUint(vals[i], 10, 0) + if err != nil { + t.Fatalf("got error: %v", err) + } + if uint(u) != v { + t.Fatalf("expect uis[%d] to be %d but got: %d", i, u, v) + } + } + + getUIS, err := f.GetUintSlice("uis") + if err != nil { + t.Fatal("got an error from GetUintSlice():", err) + } + for i, v := range getUIS { + u, err := strconv.ParseUint(vals[i], 10, 0) + if err != nil { + t.Fatal("got an error from GetIntSlice():", err) + } + if uint(u) != v { + t.Fatalf("expected uis[%d] to be %d from GetUintSlice but got: %d", i, u, v) + } + } +} + +func TestUISWithDefault(t *testing.T) { + var uis []uint + f := setUpUISFlagSetWithDefault(&uis) + + vals := []string{"1", "2"} + arg := fmt.Sprintf("--uis=%s", strings.Join(vals, ",")) + err := f.Parse([]string{arg}) + if err != nil { + t.Fatal("expected no error; got", err) + } + for i, v := range uis { + u, err := strconv.ParseUint(vals[i], 10, 0) + if err != nil { + t.Fatalf("got error: %v", err) + } + if uint(u) != v { + t.Fatalf("expected uis[%d] to be %d from GetUintSlice but got: %d", i, u, v) + } + } + + getUIS, err := f.GetUintSlice("uis") + if err != nil { + t.Fatal("got an error from GetUintSlice():", err) + } + for i, v := range getUIS { + u, err := strconv.ParseUint(vals[i], 10, 0) + if err != nil { + t.Fatalf("got error: %v", err) + } + if uint(u) != v { + t.Fatalf("expected uis[%d] to be %d from GetUintSlice but got: %d", i, u, v) + } + } +} + +func TestUISCalledTwice(t *testing.T) { + var uis []uint + f := setUpUISFlagSet(&uis) + + in := []string{"1,2", "3"} + expected := []int{1, 2, 3} + argfmt := "--uis=%s" + arg1 := fmt.Sprintf(argfmt, in[0]) + arg2 := fmt.Sprintf(argfmt, in[1]) + err := f.Parse([]string{arg1, arg2}) + if err != nil { + t.Fatal("expected no error; got", err) + } + for i, v := range uis { + if uint(expected[i]) != v { + t.Fatalf("expected uis[%d] to be %d but got: %d", i, expected[i], v) + } + } +} |