summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Gopkg.lock18
-rw-r--r--Gopkg.toml10
-rw-r--r--config/common.go12
-rw-r--r--config/policy.go141
-rw-r--r--config/policy_test.go117
-rw-r--r--config/validation.go31
-rw-r--r--main.go52
-rw-r--r--policy.example.yaml5
-rw-r--r--vendor/github.com/pborman/getopt/AUTHORS1
-rw-r--r--vendor/github.com/pborman/getopt/CONTRIBUTING.md10
-rw-r--r--vendor/github.com/pborman/getopt/LICENSE27
-rw-r--r--vendor/github.com/pborman/getopt/README.md226
-rw-r--r--vendor/github.com/pborman/getopt/bool.go74
-rw-r--r--vendor/github.com/pborman/getopt/bool_test.go106
-rw-r--r--vendor/github.com/pborman/getopt/breakup_test.go34
-rw-r--r--vendor/github.com/pborman/getopt/counter.go81
-rw-r--r--vendor/github.com/pborman/getopt/counter_test.go91
-rw-r--r--vendor/github.com/pborman/getopt/duration.go56
-rw-r--r--vendor/github.com/pborman/getopt/duration_test.go73
-rw-r--r--vendor/github.com/pborman/getopt/enum.go73
-rw-r--r--vendor/github.com/pborman/getopt/enum_test.go66
-rw-r--r--vendor/github.com/pborman/getopt/error.go93
-rw-r--r--vendor/github.com/pborman/getopt/getopt.go537
-rw-r--r--vendor/github.com/pborman/getopt/int.go67
-rw-r--r--vendor/github.com/pborman/getopt/int16.go67
-rw-r--r--vendor/github.com/pborman/getopt/int16_test.go84
-rw-r--r--vendor/github.com/pborman/getopt/int32.go67
-rw-r--r--vendor/github.com/pborman/getopt/int32_test.go84
-rw-r--r--vendor/github.com/pborman/getopt/int64.go67
-rw-r--r--vendor/github.com/pborman/getopt/int64_test.go84
-rw-r--r--vendor/github.com/pborman/getopt/int_test.go84
-rw-r--r--vendor/github.com/pborman/getopt/list.go69
-rw-r--r--vendor/github.com/pborman/getopt/list_test.go99
-rw-r--r--vendor/github.com/pborman/getopt/option.go193
-rw-r--r--vendor/github.com/pborman/getopt/set.go268
-rw-r--r--vendor/github.com/pborman/getopt/signed.go110
-rw-r--r--vendor/github.com/pborman/getopt/signed_test.go97
-rw-r--r--vendor/github.com/pborman/getopt/string.go53
-rw-r--r--vendor/github.com/pborman/getopt/string_test.go77
-rw-r--r--vendor/github.com/pborman/getopt/uint.go67
-rw-r--r--vendor/github.com/pborman/getopt/uint16.go67
-rw-r--r--vendor/github.com/pborman/getopt/uint16_test.go84
-rw-r--r--vendor/github.com/pborman/getopt/uint32.go67
-rw-r--r--vendor/github.com/pborman/getopt/uint32_test.go84
-rw-r--r--vendor/github.com/pborman/getopt/uint64.go67
-rw-r--r--vendor/github.com/pborman/getopt/uint64_test.go84
-rw-r--r--vendor/github.com/pborman/getopt/uint_test.go84
-rw-r--r--vendor/github.com/pborman/getopt/unsigned.go111
-rw-r--r--vendor/github.com/pborman/getopt/unsigned_test.go97
-rw-r--r--vendor/github.com/pborman/getopt/util_test.go87
-rw-r--r--vendor/github.com/pborman/getopt/v2/bool.go36
-rw-r--r--vendor/github.com/pborman/getopt/v2/bool_test.go106
-rw-r--r--vendor/github.com/pborman/getopt/v2/breakup_test.go34
-rw-r--r--vendor/github.com/pborman/getopt/v2/counter.go69
-rw-r--r--vendor/github.com/pborman/getopt/v2/counter_test.go76
-rw-r--r--vendor/github.com/pborman/getopt/v2/duration.go28
-rw-r--r--vendor/github.com/pborman/getopt/v2/duration_test.go73
-rw-r--r--vendor/github.com/pborman/getopt/v2/enum.go79
-rw-r--r--vendor/github.com/pborman/getopt/v2/enum_test.go79
-rw-r--r--vendor/github.com/pborman/getopt/v2/error.go93
-rw-r--r--vendor/github.com/pborman/getopt/v2/generic.go237
-rw-r--r--vendor/github.com/pborman/getopt/v2/generic_test.go319
-rw-r--r--vendor/github.com/pborman/getopt/v2/getopt.go520
-rw-r--r--vendor/github.com/pborman/getopt/v2/int.go160
-rw-r--r--vendor/github.com/pborman/getopt/v2/int_test.go595
-rw-r--r--vendor/github.com/pborman/getopt/v2/list.go32
-rw-r--r--vendor/github.com/pborman/getopt/v2/list_test.go99
-rw-r--r--vendor/github.com/pborman/getopt/v2/option.go193
-rw-r--r--vendor/github.com/pborman/getopt/v2/set.go284
-rw-r--r--vendor/github.com/pborman/getopt/v2/signed.go110
-rw-r--r--vendor/github.com/pborman/getopt/v2/signed_test.go97
-rw-r--r--vendor/github.com/pborman/getopt/v2/string.go27
-rw-r--r--vendor/github.com/pborman/getopt/v2/string_test.go77
-rw-r--r--vendor/github.com/pborman/getopt/v2/unsigned.go111
-rw-r--r--vendor/github.com/pborman/getopt/v2/unsigned_test.go97
-rw-r--r--vendor/github.com/pborman/getopt/v2/util_test.go85
-rw-r--r--vendor/github.com/pborman/getopt/v2/var.go100
-rw-r--r--vendor/github.com/pborman/getopt/var.go63
-rw-r--r--vendor/github.com/utahta/go-openuri/openuri.go54
-rw-r--r--vendor/github.com/utahta/go-openuri/openuri_test.go74
-rw-r--r--vendor/gopkg.in/go-playground/validator.v9/README.md128
-rw-r--r--vendor/gopkg.in/go-playground/validator.v9/baked_in.go214
-rw-r--r--vendor/gopkg.in/go-playground/validator.v9/benchmarks_test.go24
-rw-r--r--vendor/gopkg.in/go-playground/validator.v9/cache.go27
-rw-r--r--vendor/gopkg.in/go-playground/validator.v9/doc.go36
-rw-r--r--vendor/gopkg.in/go-playground/validator.v9/regexes.go6
-rw-r--r--vendor/gopkg.in/go-playground/validator.v9/util.go2
-rw-r--r--vendor/gopkg.in/go-playground/validator.v9/validator.go35
-rw-r--r--vendor/gopkg.in/go-playground/validator.v9/validator_instance.go85
-rw-r--r--vendor/gopkg.in/go-playground/validator.v9/validator_test.go198
90 files changed, 8876 insertions, 289 deletions
diff --git a/Gopkg.lock b/Gopkg.lock
index 8a4aeee..65b35a4 100644
--- a/Gopkg.lock
+++ b/Gopkg.lock
@@ -26,6 +26,12 @@
version = "v0.16.0"
[[projects]]
+ branch = "v2"
+ name = "github.com/pborman/getopt"
+ packages = ["v2"]
+ revision = "0fd4e972e7f7285fbae5863470524ece4ae99d78"
+
+[[projects]]
name = "github.com/pmezard/go-difflib"
packages = ["difflib"]
revision = "792786c7400a136282c1664665ae0a8db921c6c2"
@@ -38,10 +44,16 @@
version = "v1.1.4"
[[projects]]
+ name = "github.com/utahta/go-openuri"
+ packages = ["."]
+ revision = "e3e1c475535dd7256d67286b1c8c223721aafa05"
+ version = "v0.1.0"
+
+[[projects]]
name = "gopkg.in/go-playground/validator.v9"
packages = ["."]
- revision = "61caf9d3038e1af346dbf5c2e16f6678e1548364"
- version = "v9.9.0"
+ revision = "1b8c8e19cd250435025214492d9a08411d760fdd"
+ version = "v9.12.0"
[[projects]]
branch = "v2"
@@ -52,6 +64,6 @@
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
- inputs-digest = "a207dfcd5255a9f7ed6e08d3982f8f3075d29d45b7d0bb7ad31709e04755a649"
+ inputs-digest = "8cdb40365412638a73ba10e3c82296098a85b4df74a25186aec4bd7b3a8c50e4"
solver-name = "gps-cdcl"
solver-version = 1
diff --git a/Gopkg.toml b/Gopkg.toml
index 467ae19..ab06d50 100644
--- a/Gopkg.toml
+++ b/Gopkg.toml
@@ -11,8 +11,16 @@
[[constraint]]
name = "gopkg.in/go-playground/validator.v9"
- version = "9.9.0"
+ version = "9.12.0"
[[constraint]]
branch = "v2"
name = "gopkg.in/yaml.v2"
+
+[[constraint]]
+ name = "github.com/utahta/go-openuri"
+ version = "0.1.0"
+
+[[constraint]]
+ branch = "v2"
+ name = "github.com/pborman/getopt"
diff --git a/config/common.go b/config/common.go
index a597a82..4cc300d 100644
--- a/config/common.go
+++ b/config/common.go
@@ -9,12 +9,12 @@ import (
//
type CommonConfig struct {
Base string `yaml:"base" validate:"omitempty,baseimage"` // name/path to base image
- Apt AptConfig `yaml:"apt"` // APT related configuration
- Node NodeConfig `yaml:"node"` // Node related configuration
- Python PythonConfig `yaml:"python"` // Python related configuration
- Lives LivesConfig `yaml:"lives"` // application owner/dir configuration
- Runs RunsConfig `yaml:"runs"` // runtime environment configuration
- SharedVolume Flag `yaml:"sharedvolume"` // define a volume for application
+ Apt AptConfig `yaml:"apt"` // APT related
+ Node NodeConfig `yaml:"node"` // Node related
+ Python PythonConfig `yaml:"python"` // Python related
+ Lives LivesConfig `yaml:"lives"` // application owner/dir
+ Runs RunsConfig `yaml:"runs"` // runtime environment
+ SharedVolume Flag `yaml:"sharedvolume"` // use volume for app
EntryPoint []string `yaml:"entrypoint"` // entry-point executable
}
diff --git a/config/policy.go b/config/policy.go
new file mode 100644
index 0000000..25fe02a
--- /dev/null
+++ b/config/policy.go
@@ -0,0 +1,141 @@
+package config
+
+import (
+ "errors"
+ "fmt"
+ "io/ioutil"
+ "reflect"
+ "strings"
+
+ "github.com/utahta/go-openuri"
+ "gopkg.in/yaml.v2"
+)
+
+// Policy validates a number of rules against a given configuration.
+//
+type Policy struct {
+ Enforcements []Enforcement `yaml:"enforcements"`
+}
+
+// Validate checks the given config against all policy enforcements.
+//
+func (pol Policy) Validate(config Config) error {
+ validate := NewValidator()
+
+ for _, enforcement := range pol.Enforcements {
+ cfg, err := ResolveYAMLPath(enforcement.Path, config)
+
+ if err != nil {
+ // If the path resolved nothing, there's nothing to enforce
+ continue
+ }
+
+ // Flags are a special case in which the True field should be compared
+ // against the validator, not the struct itself.
+ if flag, ok := cfg.(Flag); ok {
+ cfg = flag.True
+ }
+
+ err = validate.Var(cfg, enforcement.Rule)
+
+ if err != nil {
+ return fmt.Errorf(
+ `value for "%s" violates policy rule "%s"`,
+ enforcement.Path, enforcement.Rule,
+ )
+ }
+ }
+
+ return nil
+}
+
+// Enforcement represents a policy rule and config path on which to apply it.
+//
+type Enforcement struct {
+ Path string `yaml:"path"`
+ Rule string `yaml:"rule"`
+}
+
+// ReadPolicy unmarshals the given YAML bytes into a new Policy struct.
+//
+func ReadPolicy(data []byte) (*Policy, error) {
+ var policy Policy
+
+ err := yaml.Unmarshal(data, &policy)
+
+ if err != nil {
+ return nil, err
+ }
+
+ return &policy, err
+}
+
+// ReadPolicyFromURI fetches the policy file from the given URL or file path
+// and loads its contents with ReadPolicy.
+//
+func ReadPolicyFromURI(uri string) (*Policy, error) {
+ io, err := openuri.Open(uri)
+
+ if err != nil {
+ return nil, err
+ }
+
+ defer io.Close()
+
+ data, err := ioutil.ReadAll(io)
+
+ if err != nil {
+ return nil, err
+ }
+
+ return ReadPolicy(data)
+}
+
+// ResolveYAMLPath returns the config value found at the given YAML-ish
+// namespace/path (e.g. "variants.production.runs.as").
+//
+func ResolveYAMLPath(path string, cfg interface{}) (interface{}, error) {
+ parts := strings.SplitN(path, ".", 2)
+ name := parts[0]
+
+ v := reflect.ValueOf(cfg)
+ t := v.Type()
+
+ var subcfg interface{}
+
+ switch t.Kind() {
+ case reflect.Struct:
+ for i := 0; i < t.NumField(); i++ {
+ if t.Field(i).Anonymous {
+ if subsubcfg, err := ResolveYAMLPath(path, v.Field(i).Interface()); err == nil {
+ return subsubcfg, nil
+ }
+ }
+
+ if name == resolveYAMLTagName(t.Field(i)) {
+ subcfg = v.Field(i).Interface()
+ break
+ }
+ }
+
+ case reflect.Map:
+ if t.Key().Kind() == reflect.String {
+ for _, key := range v.MapKeys() {
+ if key.Interface().(string) == name {
+ subcfg = v.MapIndex(key).Interface()
+ break
+ }
+ }
+ }
+ }
+
+ if subcfg == nil {
+ return nil, errors.New("invalid path")
+ }
+
+ if len(parts) > 1 {
+ return ResolveYAMLPath(parts[1], subcfg)
+ }
+
+ return subcfg, nil
+}
diff --git a/config/policy_test.go b/config/policy_test.go
new file mode 100644
index 0000000..2d7a3a7
--- /dev/null
+++ b/config/policy_test.go
@@ -0,0 +1,117 @@
+package config_test
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+
+ "phabricator.wikimedia.org/source/blubber/config"
+)
+
+func TestPolicyRead(t *testing.T) {
+ policy, err := config.ReadPolicy([]byte(`---
+ enforcements:
+ - path: variants.production.runs.as
+ rule: ne=root
+ - path: base
+ rule: oneof=debian:jessie debian:stretch`))
+
+ if assert.NoError(t, err) {
+ if assert.Len(t, policy.Enforcements, 2) {
+ assert.Equal(t, "variants.production.runs.as", policy.Enforcements[0].Path)
+ assert.Equal(t, "ne=root", policy.Enforcements[0].Rule)
+
+ assert.Equal(t, "base", policy.Enforcements[1].Path)
+ assert.Equal(t, "oneof=debian:jessie debian:stretch", policy.Enforcements[1].Rule)
+ }
+ }
+}
+
+func TestPolicyValidate(t *testing.T) {
+ cfg := config.Config{
+ CommonConfig: config.CommonConfig{
+ Base: "foo:tag",
+ },
+ Variants: map[string]config.VariantConfig{
+ "foo": config.VariantConfig{
+ CommonConfig: config.CommonConfig{
+ Runs: config.RunsConfig{
+ UserConfig: config.UserConfig{
+ As: "root",
+ },
+ },
+ },
+ },
+ },
+ }
+
+ policy := config.Policy{
+ Enforcements: []config.Enforcement{
+ {Path: "variants.foo.runs.as", Rule: "ne=root"},
+ },
+ }
+
+ assert.EqualError(t,
+ policy.Validate(cfg),
+ `value for "variants.foo.runs.as" violates policy rule "ne=root"`,
+ )
+
+ policy = config.Policy{
+ Enforcements: []config.Enforcement{
+ {Path: "base", Rule: "oneof=debian:jessie debian:stretch"},
+ },
+ }
+
+ assert.EqualError(t,
+ policy.Validate(cfg),
+ `value for "base" violates policy rule "oneof=debian:jessie debian:stretch"`,
+ )
+}
+
+func TestEnforcementOnFlag(t *testing.T) {
+ cfg := config.Config{
+ Variants: map[string]config.VariantConfig{
+ "production": config.VariantConfig{
+ CommonConfig: config.CommonConfig{
+ Node: config.NodeConfig{
+ Dependencies: config.Flag{True: true},
+ },
+ },
+ },
+ },
+ }
+
+ policy := config.Policy{
+ Enforcements: []config.Enforcement{
+ {Path: "variants.production.node.dependencies", Rule: "isfalse"},
+ },
+ }
+
+ assert.Error(t,
+ policy.Validate(cfg),
+ `value for "variants.production.node.dependencies" violates policy rule "isfalse"`,
+ )
+
+}
+
+func TestResolveYAMLPath(t *testing.T) {
+ cfg := config.Config{
+ Variants: map[string]config.VariantConfig{
+ "foo": config.VariantConfig{
+ CommonConfig: config.CommonConfig{
+ Runs: config.RunsConfig{
+ UserConfig: config.UserConfig{
+ As: "root",
+ },
+ },
+ },
+ },
+ },
+ }
+
+ val, err := config.ResolveYAMLPath("variants.foo.runs.as", cfg)
+
+ if assert.NoError(t, err) {
+ assert.Equal(t, "root", val)
+ }
+}
diff --git a/config/validation.go b/config/validation.go
index 652a3c8..3359211 100644
--- a/config/validation.go
+++ b/config/validation.go
@@ -52,6 +52,8 @@ var (
"baseimage": isBaseImage,
"debianpackage": isDebianPackage,
"envvars": isEnvironmentVariables,
+ "isfalse": isFalse,
+ "istrue": isTrue,
"variantref": isVariantReference,
"variants": hasVariantNames,
}
@@ -61,11 +63,10 @@ type ctxKey uint8
const rootCfgCtx ctxKey = iota
-// Validate runs all validations defined for config fields against the given
-// Config value. If the returned error is not nil, it will contain a
-// user-friendly message describing all invalid field values.
+// NewValidator returns a validator instance for which our custom aliases and
+// functions are registered.
//
-func Validate(config Config) error {
+func NewValidator() *validator.Validate {
validate := validator.New()
validate.RegisterTagNameFunc(resolveYAMLTagName)
@@ -78,6 +79,16 @@ func Validate(config Config) error {
validate.RegisterValidationCtx(name, f)
}
+ return validate
+}
+
+// Validate runs all validations defined for config fields against the given
+// Config value. If the returned error is not nil, it will contain a
+// user-friendly message describing all invalid field values.
+//
+func Validate(config Config) error {
+ validate := NewValidator()
+
ctx := context.WithValue(context.Background(), rootCfgCtx, config)
return validate.StructCtx(ctx, config)
@@ -169,6 +180,18 @@ func isEnvironmentVariables(_ context.Context, fl validator.FieldLevel) bool {
return true
}
+func isFalse(_ context.Context, fl validator.FieldLevel) bool {
+ val, ok := fl.Field().Interface().(bool)
+
+ return ok && val == false
+}
+
+func isTrue(_ context.Context, fl validator.FieldLevel) bool {
+ val, ok := fl.Field().Interface().(bool)
+
+ return ok && val == true
+}
+
func isVariantReference(ctx context.Context, fl validator.FieldLevel) bool {
cfg := ctx.Value(rootCfgCtx).(Config)
ref := fl.Field().String()
diff --git a/main.go b/main.go
index 9257532..bb16b89 100644
--- a/main.go
+++ b/main.go
@@ -7,35 +7,73 @@ import (
"log"
"os"
+ "github.com/pborman/getopt/v2"
+
"phabricator.wikimedia.org/source/blubber/config"
"phabricator.wikimedia.org/source/blubber/docker"
"phabricator.wikimedia.org/source/blubber/meta"
)
+const parameters = "config.yaml variant"
+
+var (
+ showHelp *bool = getopt.BoolLong("help", 'h', "show help/usage")
+ showVersion *bool = getopt.BoolLong("version", 'v', "show version information")
+ policyURI *string = getopt.StringLong("policy", 'p', "", "policy file URI", "uri")
+)
+
func main() {
- if len(os.Args) > 1 && os.Args[1] == "--version" {
+ getopt.SetParameters(parameters)
+ getopt.Parse()
+
+ if *showHelp {
+ getopt.Usage()
+ os.Exit(1)
+ }
+
+ if *showVersion {
fmt.Println(meta.FullVersion())
os.Exit(0)
}
- if len(os.Args) < 3 {
- fmt.Println("Usage: blubber config.yaml variant")
+ args := getopt.Args()
+
+ if len(args) < 2 {
+ getopt.Usage()
os.Exit(1)
}
- cfg, err := config.ReadConfigFile(os.Args[1])
+ cfgPath, variant := args[0], args[1]
+
+ cfg, err := config.ReadConfigFile(cfgPath)
if err != nil {
if config.IsValidationError(err) {
- log.Printf("Your config is invalid:\n%v", config.HumanizeValidationError(err))
+ log.Printf("%s is invalid:\n%v", cfgPath, config.HumanizeValidationError(err))
os.Exit(4)
} else {
- log.Printf("Error reading config: %v\n", err)
+ log.Printf("Error reading %s: %v\n", cfgPath, err)
os.Exit(2)
}
}
- dockerFile, err := docker.Compile(cfg, os.Args[2])
+ if *policyURI != "" {
+ policy, err := config.ReadPolicyFromURI(*policyURI)
+
+ if err != nil {
+ log.Printf("Error loading policy from %s: %v\n", *policyURI, err)
+ os.Exit(5)
+ }
+
+ err = policy.Validate(*cfg)
+
+ if err != nil {
+ log.Printf("Configuration fails policy check against:\npolicy: %s\nviolation: %v\n", *policyURI, err)
+ os.Exit(6)
+ }
+ }
+
+ dockerFile, err := docker.Compile(cfg, variant)
if err != nil {
log.Printf("Error compiling config: %v\n", err)
diff --git a/policy.example.yaml b/policy.example.yaml
new file mode 100644
index 0000000..2ca553b
--- /dev/null
+++ b/policy.example.yaml
@@ -0,0 +1,5 @@
+enforcements:
+ - path: variants.production.base
+ rule: oneof=debian:jessie debian:jessie-slim
+ - path: variants.production.node.dependencies
+ rule: istrue
diff --git a/vendor/github.com/pborman/getopt/AUTHORS b/vendor/github.com/pborman/getopt/AUTHORS
new file mode 100644
index 0000000..2d70b04
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/AUTHORS
@@ -0,0 +1 @@
+Paul Borman <paul@borman.com>
diff --git a/vendor/github.com/pborman/getopt/CONTRIBUTING.md b/vendor/github.com/pborman/getopt/CONTRIBUTING.md
new file mode 100644
index 0000000..04fdf09
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/CONTRIBUTING.md
@@ -0,0 +1,10 @@
+# How to contribute
+
+We definitely welcome patches and contribution to this project!
+
+### Legal requirements
+
+In order to protect both you and ourselves, you will need to sign the
+[Contributor License Agreement](https://cla.developers.google.com/clas).
+
+You may have already signed it for other Google projects.
diff --git a/vendor/github.com/pborman/getopt/LICENSE b/vendor/github.com/pborman/getopt/LICENSE
new file mode 100644
index 0000000..a8181ec
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2017 Google Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google, nor the names of other
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/github.com/pborman/getopt/README.md b/vendor/github.com/pborman/getopt/README.md
new file mode 100644
index 0000000..2e1cf72
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/README.md
@@ -0,0 +1,226 @@
+# getopt
+
+Package getopt provides traditional getopt processing for implementing
+commands that use traditional command lines. The standard Go flag package
+cannot be used to write a program that parses flags the way ls or ssh does,
+for example. There are two versions, v1 and v2, both named getopt, that
+use the following import paths:
+
+```
+ "github.com/pborman/getopt" // version 1
+ "github.com/pborman/getopt/v2" // version 2
+```
+
+This README describes version 2 of the package, which has a simplified API.
+
+## Usage
+
+Getopt supports functionality found in both the standard BSD getopt as well
+as (one of the many versions of) the GNU getopt_long. Being a Go package,
+this package makes common usage easy, but still enables more controlled usage
+if needed.
+
+Typical usage:
+
+```
+ Declare flags and have getopt return pointers to the values.
+ helpFlag := getopt.Bool('?', "display help")
+ cmdFlag := getopt.StringLong("command", 'c', "default", "the command)
+
+ Declare flags against existing variables.
+ var {
+ fileName = "/the/default/path"
+ timeout = time.Second * 5
+ verbose bool
+ }
+ func init() {
+ getopt.Flag(&verbose, 'v', "be verbose")
+ getopt.FlagLong(&fileName, "path", 0, "the path")
+ getopt.FlagLong(&timeout, "timeout", 't', "some timeout")
+ }
+
+ func main() {
+ Parse the program arguments
+ getopt.Parse()
+ Get the remaining positional parameters
+ args := getopt.Args()
+ ...
+```
+
+If you don't want the program to exit on error, use getopt.Getopt:
+
+```
+ err := getopt.Getopt(nil)
+ if err != nil {
+ code to handle error
+ fmt.Fprintln(os.Stderr, err)
+ }
+```
+
+## Flag Syntax
+
+Support is provided for both short (-f) and long (--flag) options. A single
+option may have both a short and a long name. Each option may be a flag or a
+value. A value takes an argument.
+
+Declaring no long names causes this package to process arguments like the
+traditional BSD getopt.
+
+Short flags may be combined into a single parameter. For example, "-a -b -c"
+may also be expressed "-abc". Long flags must stand on their own "--alpha
+--beta"
+
+Values require an argument. For short options the argument may either be
+immediately following the short name or as the next argument. Only one short
+value may be combined with short flags in a single argument; the short value
+must be after all short flags. For example, if f is a flag and v is a value,
+then:
+
+```
+ -vvalue (sets v to "value")
+ -v value (sets v to "value")
+ -fvvalue (sets f, and sets v to "value")
+ -fv value (sets f, and sets v to "value")
+ -vf value (set v to "f" and value is the first parameter)
+```
+
+For the long value option val:
+
+```
+ --val value (sets val to "value")
+ --val=value (sets val to "value")
+ --valvalue (invalid option "valvalue")
+```
+
+Values with an optional value only set the value if the value is part of the
+same argument. In any event, the option count is increased and the option is
+marked as seen.
+
+```
+ -v -f (sets v and f as being seen)
+ -vvalue -f (sets v to "value" and sets f)
+ --val -f (sets v and f as being seen)
+ --val=value -f (sets v to "value" and sets f)
+```
+
+There is no convience function defined for making the value optional. The
+SetOptional method must be called on the actual Option.
+
+```
+ v := String("val", 'v', "", "the optional v")
+ Lookup("v").SetOptional()
+
+ var s string
+ FlagLong(&s, "val", 'v', "the optional v).SetOptional()
+```
+
+Parsing continues until the first non-option or "--" is encountered.
+
+The short name "-" can be used, but it either is specified as "-" or as part
+of a group of options, for example "-f-". If there are no long options
+specified then "--f" could also be used. If "-" is not declared as an option
+then the single "-" will also terminate the option processing but unlike
+"--", the "-" will be part of the remaining arguments.
+
+## Advanced Usage
+
+Normally the parsing is performed by calling the Parse function. If it is
+important to see the order of the options then the Getopt function should be
+used. The standard Parse function does the equivalent of:
+
+```
+func Parse() {
+ if err := getopt.Getopt(os.Args, nil); err != nil {
+ fmt.Fprintln(os.Stderr, err)
+ s.usage()
+ os.Exit(1)
+ }
+}
+```
+
+When calling Getopt it is the responsibility of the caller to print any
+errors.
+
+Normally the default option set, CommandLine, is used. Other option sets may
+be created with New.
+
+After parsing, the sets Args will contain the non-option arguments. If an
+error is encountered then Args will begin with argument that caused the
+error.
+
+It is valid to call a set's Parse a second time to amend the current set of
+flags or values. As an example:
+
+```
+ var a = getopt.Bool('a', "", "The a flag")
+ var b = getopt.Bool('b', "", "The a flag")
+ var cmd = ""
+
+ var opts = getopt.CommandLine
+
+ opts.Parse(os.Args)
+ if opts.NArgs() > 0 {
+ cmd = opts.Arg(0)
+ opts.Parse(opts.Args())
+ }
+```
+
+If called with set to { "prog", "-a", "cmd", "-b", "arg" } then both and and
+b would be set, cmd would be set to "cmd", and opts.Args() would return {
+"arg" }.
+
+Unless an option type explicitly prohibits it, an option may appear more than
+once in the arguments. The last value provided to the option is the value.
+
+## Builtin Types
+
+The Flag and FlagLong functions support most standard Go types. For the
+list, see the description of FlagLong below for a list of supported types.
+
+There are also helper routines to allow single line flag declarations. These
+types are: Bool, Counter, Duration, Enum, Int16, Int32, Int64, Int, List,
+Signed, String, Uint16, Uint32, Uint64, Uint, and Unsigned.
+
+Each comes in a short and long flavor, e.g., Bool and BoolLong and include
+functions to set the flags on the standard command line or for a specific Set
+of flags.
+
+Except for the Counter, Enum, Signed and Unsigned types, all of these types
+can be declared using Flag and FlagLong by passing in a pointer to the
+appropriate type.
+
+## Declaring New Flag Types
+
+A pointer to any type that implements the Value interface may be passed to
+Flag or FlagLong.
+
+## VALUEHELP
+
+All non-flag options are created with a "valuehelp" as the last parameter.
+Valuehelp should be 0, 1, or 2 strings. The first string, if provided, is
+the usage message for the option. If the second string, if provided, is the
+name to use for the value when displaying the usage. If not provided the
+term "value" is assumed.
+
+The usage message for the option created with
+
+```
+ StringLong("option", 'o', "defval", "a string of letters")
+```
+
+is
+
+```
+ -o, -option=value
+```
+while the usage message for the option created with
+
+```
+ StringLong("option", 'o', "defval", "a string of letters", "string")
+```
+
+is
+
+```
+ -o, -option=string
+```
diff --git a/vendor/github.com/pborman/getopt/bool.go b/vendor/github.com/pborman/getopt/bool.go
new file mode 100644
index 0000000..37ce019
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/bool.go
@@ -0,0 +1,74 @@
+// Copyright 2013 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package getopt
+
+import (
+ "fmt"
+ "strings"
+)
+
+type boolValue bool
+
+func (b *boolValue) Set(value string, opt Option) error {
+ switch strings.ToLower(value) {
+ case "", "1", "true", "on", "t":
+ *b = true
+ case "0", "false", "off", "f":
+ *b = false
+ default:
+ return fmt.Errorf("invalid value for bool %s: %q", opt.Name(), value)
+ }
+ return nil
+}
+
+func (b *boolValue) String() string {
+ if *b {
+ return "true"
+ }
+ return "false"
+}
+
+// Bool creates a flag option that is a bool. Bools normally do not take a
+// value however one can be assigned by using the long form of the option:
+//
+// --option=true
+// --o=false
+//
+// Its value is case insenstive and one of true, false, t, f, on, off, t and 0.
+func Bool(name rune, helpvalue ...string) *bool {
+ return CommandLine.Bool(name, helpvalue...)
+}
+
+func (s *Set) Bool(name rune, helpvalue ...string) *bool {
+ var p bool
+ s.BoolVarLong(&p, "", name, helpvalue...)
+ return &p
+}
+
+func BoolLong(name string, short rune, helpvalue ...string) *bool {
+ return CommandLine.BoolLong(name, short, helpvalue...)
+}
+
+func (s *Set) BoolLong(name string, short rune, helpvalue ...string) *bool {
+ var p bool
+ s.BoolVarLong(&p, name, short, helpvalue...)
+ return &p
+}
+
+func BoolVar(p *bool, name rune, helpvalue ...string) Option {
+ return CommandLine.BoolVar(p, name, helpvalue...)
+}
+
+func (s *Set) BoolVar(p *bool, name rune, helpvalue ...string) Option {
+ return s.BoolVarLong(p, "", name, helpvalue...)
+}
+
+func BoolVarLong(p *bool, name string, short rune, helpvalue ...string) Option {
+ return CommandLine.BoolVarLong(p, name, short, helpvalue...)
+}
+
+func (s *Set) BoolVarLong(p *bool, name string, short rune, helpvalue ...string) Option {
+ return s.VarLong((*boolValue)(p), name, short, helpvalue...).SetFlag()
+}
diff --git a/vendor/github.com/pborman/getopt/bool_test.go b/vendor/github.com/pborman/getopt/bool_test.go
new file mode 100644
index 0000000..b112161
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/bool_test.go
@@ -0,0 +1,106 @@
+// Copyright 2013 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package getopt
+
+import (
+ "fmt"
+ "strings"
+ "testing"
+)
+
+var boolTests = []struct {
+ where string
+ in []string
+ f bool
+ fc int
+ opt bool
+ optc int
+ err string
+}{
+ {
+ loc(),
+ []string{},
+ false, 0,
+ false, 0,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-f", "--opt"},
+ true, 1,
+ true, 1,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "--f", "--opt"},
+ true, 1,
+ true, 1,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-ff", "-f", "--opt", "--opt"},
+ true, 3,
+ true, 2,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "--opt", "--opt=false"},
+ false, 0,
+ false, 2,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-f", "false"},
+ true, 1,
+ false, 0,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-f=false"},
+ true, 1,
+ false, 0,
+ "test: unknown option: -=\n",
+ },
+ {
+ loc(),
+ []string{"test", "-f", "false"},
+ true, 1,
+ false, 0,
+ "",
+ },
+}
+
+func TestBool(t *testing.T) {
+ for x, tt := range boolTests {
+ reset()
+ f := Bool('f')
+ opt := BoolLong("opt", 0)
+ if strings.Index(tt.where, ":-") > 0 {
+ tt.where = fmt.Sprintf("#%d", x)
+ }
+
+ parse(tt.in)
+ if s := checkError(tt.err); s != "" {
+ t.Errorf("%s: %s", tt.where, s)
+ }
+ if got, want := *f, tt.f; got != want {
+ t.Errorf("%s: got %v, want %v", tt.where, got, want)
+ }
+ if got, want := *opt, tt.opt; got != want {
+ t.Errorf("%s: got %v, want %v", tt.where, got, want)
+ }
+ if got, want := GetCount('f'), tt.fc; got != want {
+ t.Errorf("%s: got %v, want %v", tt.where, got, want)
+ }
+ if got, want := GetCount("opt"), tt.optc; got != want {
+ t.Errorf("%s: got %v, want %v", tt.where, got, want)
+ }
+ }
+}
diff --git a/vendor/github.com/pborman/getopt/breakup_test.go b/vendor/github.com/pborman/getopt/breakup_test.go
new file mode 100644
index 0000000..c0ac148
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/breakup_test.go
@@ -0,0 +1,34 @@
+// Copyright 2013 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package getopt
+
+import (
+ "testing"
+)
+
+var breakupTests = []struct {
+ in string
+ max int
+ out []string
+}{
+ {"", 8, []string{}},
+ {"a fox", 8, []string{"a fox"}},
+ {"a foxhound is sly", 2, []string{"a", "foxhound", "is", "sly"}},
+ {"a foxhound is sly", 5, []string{"a", "foxhound", "is", "sly"}},
+ {"a foxhound is sly", 6, []string{"a", "foxhound", "is sly"}},
+ {"a foxhound is sly", 7, []string{"a", "foxhound", "is sly"}},
+ {"a foxhound is sly", 8, []string{"a", "foxhound", "is sly"}},
+ {"a foxhound is sly", 9, []string{"a", "foxhound", "is sly"}},
+ {"a foxhound is sly", 10, []string{"a foxhound", "is sly"}},
+}
+
+func TestBreakup(t *testing.T) {
+ for x, tt := range breakupTests {
+ out := breakup(tt.in, tt.max)
+ if badSlice(out, tt.out) {
+ t.Errorf("#%d: got %v, want %v", x, out, tt.out)
+ }
+ }
+}
diff --git a/vendor/github.com/pborman/getopt/counter.go b/vendor/github.com/pborman/getopt/counter.go
new file mode 100644
index 0000000..8b11ec1
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/counter.go
@@ -0,0 +1,81 @@
+// Copyright 2013 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package getopt
+
+import (
+ "fmt"
+ "strconv"
+)
+
+type counterValue int
+
+func (b *counterValue) Set(value string, opt Option) error {
+ if value == "" {
+ *b++
+ } else {
+ v, err := strconv.ParseInt(value, 0, strconv.IntSize)
+ if err != nil {
+ if e, ok := err.(*strconv.NumError); ok {
+ switch e.Err {
+ case strconv.ErrRange:
+ err = fmt.Errorf("value out of range: %s", value)
+ case strconv.ErrSyntax:
+ err = fmt.Errorf("not a valid number: %s", value)
+ }
+ }
+ return err
+ }
+ *b = counterValue(v)
+ }
+ return nil
+}
+
+func (b *counterValue) String() string {
+ return strconv.Itoa(int(*b))
+}
+
+// Counter creates a counting flag stored as an int. Each time the option
+// is seen while parsing the value is incremented. The value of the counter
+// may be explicitly set by using the long form:
+//
+// --counter=5
+// --c=5
+//
+// Further instances of the option will increment from the set value.
+func Counter(name rune, helpvalue ...string) *int {
+ return CommandLine.Counter(name, helpvalue...)
+}
+
+func (s *Set) Counter(name rune, helpvalue ...string) *int {
+ var p int
+ s.CounterVarLong(&p, "", name, helpvalue...)
+ return &p
+}
+
+func CounterLong(name string, short rune, helpvalue ...string) *int {
+ return CommandLine.CounterLong(name, short, helpvalue...)
+}
+
+func (s *Set) CounterLong(name string, short rune, helpvalue ...string) *int {
+ var p int
+ s.CounterVarLong(&p, name, short, helpvalue...)
+ return &p
+}
+
+func CounterVar(p *int, name rune, helpvalue ...string) Option {
+ return CommandLine.CounterVar(p, name, helpvalue...)
+}
+
+func (s *Set) CounterVar(p *int, name rune, helpvalue ...string) Option {
+ return s.CounterVarLong(p, "", name, helpvalue...)
+}
+
+func CounterVarLong(p *int, name string, short rune, helpvalue ...string) Option {
+ return CommandLine.CounterVarLong(p, name, short, helpvalue...)
+}
+
+func (s *Set) CounterVarLong(p *int, name string, short rune, helpvalue ...string) Option {
+ return s.VarLong((*counterValue)(p), name, short, helpvalue...).SetFlag()
+}
diff --git a/vendor/github.com/pborman/getopt/counter_test.go b/vendor/github.com/pborman/getopt/counter_test.go
new file mode 100644
index 0000000..4b4e0cb
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/counter_test.go
@@ -0,0 +1,91 @@
+// Copyright 2013 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package getopt
+
+import (
+ "fmt"
+ "strings"
+ "testing"
+)
+
+var counterTests = []struct {
+ where string
+ in []string
+ c int
+ cnt int
+ err string
+}{
+ {
+ loc(),
+ []string{},
+ 0,
+ 0,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-c", "--cnt"},
+ 1,
+ 1,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-cc", "-c", "--cnt", "--cnt"},
+ 3,
+ 2,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "--c=17", "--cnt=42"},
+ 17,
+ 42,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "--cnt=false"},
+ 0, 0,
+ "test: not a valid number: false\n",
+ },
+}
+
+func TestCounter(t *testing.T) {
+ for x, tt := range counterTests {
+ reset()
+ c := Counter('c')
+ cnt := CounterLong("cnt", 0)
+ if strings.Index(tt.where, ":-") > 0 {
+ tt.where = fmt.Sprintf("#%d", x)
+ }
+
+ parse(tt.in)
+ if s := checkError(tt.err); s != "" {
+ t.Errorf("%s: %s", tt.where, s)
+ }
+ if got, want := *c, tt.c; got != want {
+ t.Errorf("%s: got %v, want %v", tt.where, got, want)
+ }
+ if got, want := *cnt, tt.cnt; got != want {
+ t.Errorf("%s: got %v, want %v", tt.where, got, want)
+ }
+ }
+
+ reset()
+ c := 5
+ opt := CounterVar(&c, 'c')
+ parse([]string{"test", "-c"})
+ if c != 6 {
+ t.Errorf("got %d, want 6", c)
+ }
+ if opt.Count() != 1 {
+ t.Errorf("got %d, want 1", c)
+ }
+ Reset()
+ if c != 5 {
+ t.Errorf("got %d, want 5", c)
+ }
+}
diff --git a/vendor/github.com/pborman/getopt/duration.go b/vendor/github.com/pborman/getopt/duration.go
new file mode 100644
index 0000000..9061113
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/duration.go
@@ -0,0 +1,56 @@
+// Copyright 2015 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package getopt
+
+import "time"
+
+type durationValue time.Duration
+
+func (d *durationValue) Set(value string, opt Option) error {
+ v, err := time.ParseDuration(value)
+ if err != nil {
+ return err
+ }
+ *d = durationValue(v)
+ return nil
+}
+
+func (d *durationValue) String() string {
+ return time.Duration(*d).String()
+}
+
+// Duration creates an option that parses its value as a time.Duration.
+func Duration(name rune, value time.Duration, helpvalue ...string) *time.Duration {
+ return CommandLine.Duration(name, value, helpvalue...)
+}
+
+func (s *Set) Duration(name rune, value time.Duration, helpvalue ...string) *time.Duration {
+ return s.DurationLong("", name, value, helpvalue...)
+}
+
+func DurationLong(name string, short rune, value time.Duration, helpvalue ...string) *time.Duration {
+ return CommandLine.DurationLong(name, short, value, helpvalue...)
+}
+
+func (s *Set) DurationLong(name string, short rune, value time.Duration, helpvalue ...string) *time.Duration {
+ s.DurationVarLong(&value, name, short, helpvalue...)
+ return &value
+}
+
+func DurationVar(p *time.Duration, name rune, helpvalue ...string) Option {
+ return CommandLine.DurationVar(p, name, helpvalue...)
+}
+
+func (s *Set) DurationVar(p *time.Duration, name rune, helpvalue ...string) Option {
+ return s.DurationVarLong(p, "", name, helpvalue...)
+}
+
+func DurationVarLong(p *time.Duration, name string, short rune, helpvalue ...string) Option {
+ return CommandLine.DurationVarLong(p, name, short, helpvalue...)
+}
+
+func (s *Set) DurationVarLong(p *time.Duration, name string, short rune, helpvalue ...string) Option {
+ return s.VarLong((*durationValue)(p), name, short, helpvalue...)
+}
diff --git a/vendor/github.com/pborman/getopt/duration_test.go b/vendor/github.com/pborman/getopt/duration_test.go
new file mode 100644
index 0000000..fc4ded7
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/duration_test.go
@@ -0,0 +1,73 @@
+// Copyright 2013 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package getopt
+
+import (
+ "fmt"
+ "strings"
+ "testing"
+ "time"
+)
+
+var durationTests = []struct {
+ where string
+ in []string
+ d time.Duration
+ dur time.Duration
+ err string
+}{
+ {
+ loc(),
+ []string{},
+ 17, 42,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-d", "1s", "--duration", "2s"},
+ time.Second, 2 * time.Second,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-d1s", "-d2s"},
+ 2 * time.Second, 42,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-d1"},
+ 17, 42,
+ "test: time: missing unit in duration 1\n",
+ },
+ {
+ loc(),
+ []string{"test", "--duration", "foo"},
+ 17, 42,
+ "test: time: invalid duration foo\n",
+ },
+}
+
+func TestDuration(t *testing.T) {
+ for x, tt := range durationTests {
+ reset()
+ d := Duration('d', 17)
+ opt := DurationLong("duration", 0, 42)
+ if strings.Index(tt.where, ":-") > 0 {
+ tt.where = fmt.Sprintf("#%d", x)
+ }
+
+ parse(tt.in)
+ if s := checkError(tt.err); s != "" {
+ t.Errorf("%s: %s", tt.where, s)
+ }
+ if got, want := *d, tt.d; got != want {
+ t.Errorf("%s: got %v, want %v", tt.where, got, want)
+ }
+ if got, want := *opt, tt.dur; got != want {
+ t.Errorf("%s: got %v, want %v", tt.where, got, want)
+ }
+ }
+}
diff --git a/vendor/github.com/pborman/getopt/enum.go b/vendor/github.com/pborman/getopt/enum.go
new file mode 100644
index 0000000..ee4cf95
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/enum.go
@@ -0,0 +1,73 @@
+// Copyright 2013 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package getopt
+
+import "errors"
+
+type enumValue string
+
+var enumValues = make(map[*enumValue]map[string]struct{})
+
+func (s *enumValue) Set(value string, opt Option) error {
+ es, ok := enumValues[s]
+ if !ok || es == nil {
+ return errors.New("this option has no values")
+ }
+ if _, ok := es[value]; !ok {
+ return errors.New("invalid value: " + value)
+ }
+ *s = enumValue(value)
+ return nil
+}
+
+func (s *enumValue) String() string {
+ return string(*s)
+}
+
+// Enum creates an option that can only be set to one of the enumerated strings
+// passed in values. Passing nil or an empty slice results in an option that
+// will always fail.
+func Enum(name rune, values []string, helpvalue ...string) *string {
+ return CommandLine.Enum(name, values, helpvalue...)
+}
+
+func (s *Set) Enum(name rune, values []string, helpvalue ...string) *string {
+ var p string
+ s.EnumVarLong(&p, "", name, values, helpvalue...)
+ return &p
+}
+
+func EnumLong(name string, short rune, values []string, helpvalue ...string) *string {
+ return CommandLine.EnumLong(name, short, values, helpvalue...)
+}
+
+func (s *Set) EnumLong(name string, short rune, values []string, helpvalue ...string) *string {
+ var p string
+ s.EnumVarLong(&p, name, short, values, helpvalue...)
+ return &p
+}
+
+// EnumVar creates an enum option that defaults to the starting value of *p.
+// If *p is not found in values then a reset of this option will fail.
+func EnumVar(p *string, name rune, values []string, helpvalue ...string) Option {
+ return CommandLine.EnumVar(p, name, values, helpvalue...)
+}
+
+func (s *Set) EnumVar(p *string, name rune, values []string, helpvalue ...string) Option {
+ return s.EnumVarLong(p, "", name, values, helpvalue...)
+}
+
+func EnumVarLong(p *string, name string, short rune, values []string, helpvalue ...string) Option {
+ return CommandLine.EnumVarLong(p, name, short, values, helpvalue...)
+}
+
+func (s *Set) EnumVarLong(p *string, name string, short rune, values []string, helpvalue ...string) Option {
+ m := make(map[string]struct{})
+ for _, v := range values {
+ m[v] = struct{}{}
+ }
+ enumValues[(*enumValue)(p)] = m
+ return s.VarLong((*enumValue)(p), name, short, helpvalue...)
+}
diff --git a/vendor/github.com/pborman/getopt/enum_test.go b/vendor/github.com/pborman/getopt/enum_test.go
new file mode 100644
index 0000000..3c04ee8
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/enum_test.go
@@ -0,0 +1,66 @@
+// Copyright 2013 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package getopt
+
+import (
+ "fmt"
+ "strings"
+ "testing"
+)
+
+var enumTests = []struct {
+ where string
+ in []string
+ values []string
+ out string
+ err string
+}{
+ {
+ loc(),
+ nil,
+ []string{},
+ "",
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-e", "val1"},
+ []string{"val1", "val2"},
+ "val1",
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-e", "val1", "-e", "val2"},
+ []string{"val1", "val2"},
+ "val2",
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-e", "val3"},
+ []string{"val1", "val2"},
+ "",
+ "test: invalid value: val3\n",
+ },
+}
+
+func TestEnum(t *testing.T) {
+ for x, tt := range enumTests {
+ if strings.Index(tt.where, ":-") > 0 {
+ tt.where = fmt.Sprintf("#%d", x)
+ }
+
+ reset()
+ e := Enum('e', tt.values)
+ parse(tt.in)
+ if s := checkError(tt.err); s != "" {
+ t.Errorf("%s: %s", tt.where, s)
+ }
+ if *e != tt.out {
+ t.Errorf("%s: got %v, want %v", tt.where, *e, tt.out)
+ }
+ }
+}
diff --git a/vendor/github.com/pborman/getopt/error.go b/vendor/github.com/pborman/getopt/error.go
new file mode 100644
index 0000000..3de8e86
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/error.go
@@ -0,0 +1,93 @@
+// Copyright 2013 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package getopt
+
+import "fmt"
+
+// An Error is returned by Getopt when it encounters an error.
+type Error struct {
+ ErrorCode // General reason of failure.
+ Err error // The actual error.
+ Parameter string // Parameter passed to option, if any
+ Name string // Option that cause error, if any
+}
+
+// Error returns the error message, implementing the error interface.
+func (i *Error) Error() string { return i.Err.Error() }
+
+// An ErrorCode indicates what sort of error was encountered.
+type ErrorCode int
+
+const (
+ NoError = ErrorCode(iota)
+ UnknownOption // an invalid option was encountered
+ MissingParameter // the options parameter is missing
+ ExtraParameter // a value was set to a long flag
+ Invalid // attempt to set an invalid value
+)
+
+func (e ErrorCode) String() string {
+ switch e {
+ case UnknownOption:
+ return "unknow option"
+ case MissingParameter:
+ return "missing argument"
+ case ExtraParameter:
+ return "unxpected value"
+ case Invalid:
+ return "error setting value"
+ }
+ return "unknown error"
+}
+
+// unknownOption returns an Error indicating an unknown option was
+// encountered.
+func unknownOption(name interface{}) *Error {
+ i := &Error{ErrorCode: UnknownOption}
+ switch n := name.(type) {
+ case rune:
+ if n == '-' {
+ i.Name = "-"
+ } else {
+ i.Name = "-" + string(n)
+ }
+ case string:
+ i.Name = "--" + n
+ }
+ i.Err = fmt.Errorf("unknown option: %s", i.Name)
+ return i
+}
+
+// missingArg returns an Error inidicating option o was not passed
+// a required paramter.
+func missingArg(o Option) *Error {
+ return &Error{
+ ErrorCode: MissingParameter,
+ Name: o.Name(),
+ Err: fmt.Errorf("missing parameter for %s", o.Name()),
+ }
+}
+
+// extraArg returns an Error inidicating option o was passed the
+// unexpected paramter value.
+func extraArg(o Option, value string) *Error {
+ return &Error{
+ ErrorCode: ExtraParameter,
+ Name: o.Name(),
+ Parameter: value,
+ Err: fmt.Errorf("unexpected parameter passed to %s: %q", o.Name(), value),
+ }
+}
+
+// setError returns an Error inidicating option o and the specified
+// error while setting it to value.
+func setError(o Option, value string, err error) *Error {
+ return &Error{
+ ErrorCode: Invalid,
+ Name: o.Name(),
+ Parameter: value,
+ Err: err,
+ }
+}
diff --git a/vendor/github.com/pborman/getopt/getopt.go b/vendor/github.com/pborman/getopt/getopt.go
new file mode 100644
index 0000000..e3279ab
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/getopt.go
@@ -0,0 +1,537 @@
+// Copyright 2013 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package getopt (v1) provides traditional getopt processing for implementing
+// commands that use traditional command lines. The standard Go flag package
+// cannot be used to write a program that parses flags the way ls or ssh does,
+// for example.
+//
+// A new version of this package (v2) (whose package name is also getopt) is
+// available as:
+//
+// "github.com/pborman/getopt/v2"
+//
+// Getopt supports functionality found in both the standard BSD getopt as well
+// as (one of the many versions of) the GNU getopt_long. Being a Go package,
+// this package makes common usage easy, but still enables more controlled usage
+// if needed.
+//
+// Typical usage:
+//
+// // Declare the flags to be used
+// helpFlag := getopt.Bool('?', "display help")
+// cmdFlag := getopt.StringLong("command", 'c', "", "the command)
+//
+// func main() {
+// // Parse the program arguments
+// getopt.Parse()
+// // Get the remaining positional parameters
+// args := getopt.Args()
+//
+// If you don't want the program to exit on error, use getopt.Getopt:
+//
+// err := getopt.Getopt(nil)
+// if err != nil {
+// // code to handle error
+// fmt.Fprintln(os.Stderr, err)
+// }
+//
+// Support is provided for both short (-f) and long (--flag) options. A single
+// option may have both a short and a long name. Each option may be a flag or a
+// value. A value takes an argument.
+//
+// Declaring no long names causes this package to process arguments like the
+// traditional BSD getopt.
+//
+// Short flags may be combined into a single parameter. For example, "-a -b -c"
+// may also be expressed "-abc". Long flags must stand on their own "--alpha
+// --beta"
+//
+// Values require an argument. For short options the argument may either be
+// immediately following the short name or as the next argument. Only one short
+// value may be combined with short flags in a single argument; the short value
+// must be after all short flags. For example, if f is a flag and v is a value,
+// then:
+//
+// -vvalue (sets v to "value")
+// -v value (sets v to "value")
+// -fvvalue (sets f, and sets v to "value")
+// -fv value (sets f, and sets v to "value")
+// -vf value (set v to "f" and value is the first parameter)
+//
+// For the long value option val:
+//
+// --val value (sets val to "value")
+// --val=value (sets val to "value")
+// --valvalue (invalid option "valvalue")
+//
+// Values with an optional value only set the value if the value is part of the
+// same argument. In any event, the option count is increased and the option is
+// marked as seen.
+//
+// -v -f (sets v and f as being seen)
+// -vvalue -f (sets v to "value" and sets f)
+// --val -f (sets v and f as being seen)
+// --val=value -f (sets v to "value" and sets f)
+//
+// There is no convience function defined for making the value optional. The
+// SetOptional method must be called on the actual Option.
+//
+// v := String("val", 'v', "", "the optional v")
+// Lookup("v").SetOptional()
+//
+// var s string
+// StringVar(&s, "val", 'v', "the optional v).SetOptional()
+//
+// Parsing continues until the first non-option or "--" is encountered.
+//
+// The short name "-" can be used, but it either is specified as "-" or as part
+// of a group of options, for example "-f-". If there are no long options
+// specified then "--f" could also be used. If "-" is not declared as an option
+// then the single "-" will also terminate the option processing but unlike
+// "--", the "-" will be part of the remaining arguments.
+//
+// Normally the parsing is performed by calling the Parse function. If it is
+// important to see the order of the options then the Getopt function should be
+// used. The standard Parse function does the equivalent of:
+//
+// func Parse() {
+// if err := getopt.Getopt(os.Args, nil); err != nil {
+// fmt.Fprintln(os.Stderr, err)
+// s.usage()
+// os.Exit(1)
+// }
+//
+// When calling Getopt it is the responsibility of the caller to print any
+// errors.
+//
+// Normally the default option set, CommandLine, is used. Other option sets may
+// be created with New.
+//
+// After parsing, the sets Args will contain the non-option arguments. If an
+// error is encountered then Args will begin with argument that caused the
+// error.
+//
+// It is valid to call a set's Parse a second time to amend the current set of
+// flags or values. As an example:
+//
+// var a = getopt.Bool('a', "", "The a flag")
+// var b = getopt.Bool('b', "", "The a flag")
+// var cmd = ""
+//
+// var opts = getopt.CommandLine
+//
+// opts.Parse(os.Args)
+// if opts.NArgs() > 0 {
+// cmd = opts.Arg(0)
+// opts.Parse(opts.Args())
+// }
+//
+// If called with set to { "prog", "-a", "cmd", "-b", "arg" } then both and and
+// b would be set, cmd would be set to "cmd", and opts.Args() would return {
+// "arg" }.
+//
+// Unless an option type explicitly prohibits it, an option may appear more than
+// once in the arguments. The last value provided to the option is the value.
+//
+// SYNTAX
+//
+// For each option type there are an unfortunately large number of ways, 8, to
+// initialize the option. This number is derived from three attributes:
+//
+// 1) Short or Long name
+// 2) Normal vs Var
+// 3) Command Line vs Option Set
+//
+// The first two variations provide 4 signature:
+//
+// Option(name rune, [value type,] helpvalue... string)
+// OptionLong(name string, short rune, [value type,] helpvalue... string)
+// OptionVar(p *type, name rune, helpvalue... string)
+// OptionVarLong(p *type, name string, short rune, helpvalue... string)
+//
+// Foo can actually be expressed in terms of FooLong:
+//
+// func Foo(name rune, value type, helpvalue... string) *type {
+// return FooLong("", name, value, helpvalue...)
+// }
+//
+// Normally Foo is used, unless long options are needed. Setting short to 0
+// creates only a long option.
+//
+// The difference bentween Foo and FooVar is that you pass a pointer, p, to the
+// location of the value to FooVar. The default value is simply *p. The
+// initial value of *p is the defaut value of the option.
+//
+// Foo is actually a wrapper around FooVar:
+//
+// func Foo(name rune, value type, helpvalue... string) *type {
+// p := value
+// FooVar(&p, name, helpvalue... string)
+// return &p
+// }
+//
+//
+// The third variation provides a top-level function and a method on a Set:
+//
+// func Option(...)
+// func (s *Set) Option(...)
+//
+// The top-level function is simply:
+//
+// func Option(...) *type {
+// return CommandLine.Option(...) {
+// }
+//
+// To simplfy documentation, typically only the main top-level function is fully
+// documented. The others will have documentation when there is something
+// special about them.
+//
+// VALUEHELP
+//
+// All non-flag options are created with a "valuehelp" as the last parameter.
+// Valuehelp should be 0, 1, or 2 strings. The first string, if provided, is
+// the usage message for the option. If the second string, if provided, is the
+// name to use for the value when displaying the usage. If not provided the
+// term "value" is assumed.
+//
+// The usage message for the option created with
+//
+// StringLong("option", 'o', "defval", "a string of letters")
+//
+// is
+//
+// -o, -option=value
+//
+// StringLong("option", 'o', "defval", "a string of letters", "string")
+//
+// is
+//
+// -o, -option=string
+package getopt
+
+import (
+ "fmt"
+ "io"
+ "os"
+ "path"
+ "sort"
+ "strings"
+)
+
+// stderr allows tests to capture output to standard error.
+var stderr io.Writer = os.Stderr
+
+// exit allows tests to capture an os.Exit call
+var exit = os.Exit
+
+// DisplayWidth is used to determine where to split usage long lines.
+var DisplayWidth = 80
+
+// HelpColumn is the maximum column position that help strings start to display
+// at. If the option usage is too long then the help string will be displayed
+// on the next line. For example:
+//
+// -a this is the a flag
+// -u, --under=location
+// the u flag's usage is quite long
+var HelpColumn = 20
+
+// PrintUsage prints the usage of the program to w.
+func (s *Set) PrintUsage(w io.Writer) {
+ sort.Sort(s.options)
+ flags := ""
+
+ // Build up the list of short flag names and also compute
+ // how to display the option in the longer help listing.
+ // We also keep track of the longest option usage string
+ // that is no more than HelpColumn-3 bytes (at which point
+ // we use two lines to display the help). The three
+ // is for the leading space and the two spaces before the
+ // help string.
+ for _, opt := range s.options {
+ if opt.name == "" {
+ opt.name = "value"
+ }
+ if opt.uname == "" {
+ opt.uname = opt.usageName()
+ }
+ if opt.flag && opt.short != 0 && opt.short != '-' {
+ flags += string(opt.short)
+ }
+ }
+
+ var opts []string
+
+ // The short option - is special
+ if s.shortOptions['-'] != nil {
+ opts = append(opts, "-")
+ }
+
+ // If we have a bundle of flags, add them to the list
+ if flags != "" {
+ opts = append(opts, "-"+flags)
+ }
+
+ // Now append all the long options and options that require
+ // values.
+ for _, opt := range s.options {
+ if opt.flag {
+ if opt.short != 0 {
+ continue
+ }
+ flags = "--" + opt.long
+ } else if opt.short != 0 {
+ flags = "-" + string(opt.short) + " " + opt.name
+ } else {
+ flags = "--" + string(opt.long) + " " + opt.name
+ }
+ opts = append(opts, flags)
+ }
+ flags = strings.Join(opts, "] [")
+ if flags != "" {
+ flags = " [" + flags + "]"
+ }
+ if s.parameters != "" {
+ flags += " " + s.parameters
+ }
+ fmt.Fprintf(w, "Usage: %s%s\n", s.program, flags)
+ s.PrintOptions(w)
+}
+
+// PrintOptions prints the list of options in s to w.
+func (s *Set) PrintOptions(w io.Writer) {
+ sort.Sort(s.options)
+ max := 4
+ for _, opt := range s.options {
+ if opt.name == "" {
+ opt.name = "value"
+ }
+ if opt.uname == "" {
+ opt.uname = opt.usageName()
+ }
+ if max < len(opt.uname) && len(opt.uname) <= HelpColumn-3 {
+ max = len(opt.uname)
+ }
+ }
+ // Now print one or more usage lines per option.
+ for _, opt := range s.options {
+ if opt.uname != "" {
+ opt.help = strings.TrimSpace(opt.help)
+ if len(opt.help) == 0 {
+ fmt.Fprintf(w, " %s\n", opt.uname)
+ continue
+ }
+ help := strings.Split(opt.help, "\n")
+ // If they did not put in newlines then we will insert
+ // them to keep the help messages from wrapping.
+ if len(help) == 1 {
+ help = breakup(help[0], DisplayWidth-HelpColumn)
+ }
+ if len(opt.uname) <= max {
+ fmt.Fprintf(w, " %-*s %s\n", max, opt.uname, help[0])
+ help = help[1:]
+ } else {
+ fmt.Fprintf(w, " %s\n", opt.uname)
+ }
+ for _, s := range help {
+ fmt.Fprintf(w, " %-*s %s\n", max, " ", s)
+ }
+ }
+ }
+}
+
+// breakup breaks s up into strings no longer than max bytes.
+func breakup(s string, max int) []string {
+ var a []string
+
+ for {
+ // strip leading spaces
+ for len(s) > 0 && s[0] == ' ' {
+ s = s[1:]
+ }
+ // If the option is no longer than the max just return it
+ if len(s) <= max {
+ if len(s) != 0 {
+ a = append(a, s)
+ }
+ return a
+ }
+ x := max
+ for s[x] != ' ' {
+ // the first word is too long?!
+ if x == 0 {
+ x = max
+ for x < len(s) && s[x] != ' ' {
+ x++
+ }
+ if x == len(s) {
+ x--
+ }
+ break
+ }
+ x--
+ }
+ for s[x] == ' ' {
+ x--
+ }
+ a = append(a, s[:x+1])
+ s = s[x+1:]
+ }
+ panic("unreachable")
+}
+
+// Parse uses Getopt to parse args using the options set for s. The first
+// element of args is used to assign the program for s if it is not yet set. On
+// error, Parse displays the error message as well as a usage message on
+// standard error and then exits the program.
+func (s *Set) Parse(args []string) {
+ if err := s.Getopt(args, nil); err != nil {
+ fmt.Fprintln(stderr, err)
+ s.usage()
+ exit(1)
+ }
+}
+
+// Parse uses Getopt to parse args using the options set for s. The first
+// element of args is used to assign the program for s if it is not yet set.
+// Getop calls fn, if not nil, for each option parsed.
+//
+// Getopt returns nil when all options have been processed (a non-option
+// argument was encountered, "--" was encountered, or fn returned false).
+//
+// On error getopt returns a refernce to an InvalidOption (which implements
+// the error interface).
+func (s *Set) Getopt(args []string, fn func(Option) bool) (err error) {
+ s.State = InProgress
+ defer func() {
+ if s.State == InProgress {
+ switch {
+ case err != nil:
+ s.State = Failure
+ case len(s.args) == 0:
+ s.State = EndOfArguments
+ default:
+ s.State = Unknown
+ }
+ }
+ }()
+ if fn == nil {
+ fn = func(Option) bool { return true }
+ }
+ if len(args) == 0 {
+ return nil
+ }
+
+ if s.program == "" {
+ s.program = path.Base(args[0])
+ }
+ args = args[1:]
+Parsing:
+ for len(args) > 0 {
+ arg := args[0]
+ s.args = args
+ args = args[1:]
+
+ // end of options?
+ if arg == "" || arg[0] != '-' {
+ s.State = EndOfOptions
+ return nil
+ }
+
+ if arg == "-" {
+ goto ShortParsing
+ }
+
+ // explicitly request end of options?
+ if arg == "--" {
+ s.args = args
+ s.State = DashDash
+ return nil
+ }
+
+ // Long option processing
+ if len(s.longOptions) > 0 && arg[1] == '-' {
+ e := strings.IndexRune(arg, '=')
+ var value string
+ if e > 0 {
+ value = arg[e+1:]
+ arg = arg[:e]
+ }
+ opt := s.longOptions[arg[2:]]
+ // If we are processing long options then --f is -f
+ // if f is not defined as a long option.
+ // This lets you say --f=false
+ if opt == nil && len(arg[2:]) == 1 {
+ opt = s.shortOptions[rune(arg[2])]
+ }
+ if opt == nil {
+ return unknownOption(arg[2:])
+ }
+ opt.isLong = true
+ // If we require an option and did not have an =
+ // then use the next argument as an option.
+ if !opt.flag && e < 0 && !opt.optional {
+ if len(args) == 0 {
+ return missingArg(opt)
+ }
+ value = args[0]
+ args = args[1:]
+ }
+ opt.count++
+
+ if err := opt.value.Set(value, opt); err != nil {
+ return setError(opt, value, err)
+ }
+
+ if !fn(opt) {
+ s.State = Terminated
+ return nil
+ }
+ continue Parsing
+ }
+
+ // Short option processing
+ arg = arg[1:] // strip -
+ ShortParsing:
+ for i, c := range arg {
+ opt := s.shortOptions[c]
+ if opt == nil {
+ // In traditional getopt, if - is not registered
+ // as an option, a lone - is treated as
+ // if there were a -- in front of it.
+ if arg == "-" {
+ s.State = Dash
+ return nil
+ }
+ return unknownOption(c)
+ }
+ opt.isLong = false
+ opt.count++
+ var value string
+ if !opt.flag {
+ value = arg[1+i:]
+ if value == "" && !opt.optional {
+ if len(args) == 0 {
+ return missingArg(opt)
+ }
+ value = args[0]
+ args = args[1:]
+ }
+ }
+ if err := opt.value.Set(value, opt); err != nil {
+ return setError(opt, value, err)
+ }
+ if !fn(opt) {
+ s.State = Terminated
+ return nil
+ }
+ if !opt.flag {
+ continue Parsing
+ }
+ }
+ }
+ s.args = []string{}
+ return nil
+}
diff --git a/vendor/github.com/pborman/getopt/int.go b/vendor/github.com/pborman/getopt/int.go
new file mode 100644
index 0000000..3db5fd6
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/int.go
@@ -0,0 +1,67 @@
+// Copyright 2013 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package getopt
+
+import (
+ "fmt"
+ "strconv"
+)
+
+type intValue int
+
+func (i *intValue) Set(value string, opt Option) error {
+ v, err := strconv.ParseInt(value, 0, strconv.IntSize)
+ if err != nil {
+ if e, ok := err.(*strconv.NumError); ok {
+ switch e.Err {
+ case strconv.ErrRange:
+ err = fmt.Errorf("value out of range: %s", value)
+ case strconv.ErrSyntax:
+ err = fmt.Errorf("not a valid number: %s", value)
+ }
+ }
+ return err
+ }
+ *i = intValue(v)
+ return nil
+}
+
+func (i *intValue) String() string {
+ return strconv.FormatInt(int64(*i), 10)
+}
+
+// Int creates an option that parses its value as an integer.
+func Int(name rune, value int, helpvalue ...string) *int {
+ return CommandLine.Int(name, value, helpvalue...)
+}
+
+func (s *Set) Int(name rune, value int, helpvalue ...string) *int {
+ return s.IntLong("", name, value, helpvalue...)
+}
+
+func IntLong(name string, short rune, value int, helpvalue ...string) *int {
+ return CommandLine.IntLong(name, short, value, helpvalue...)
+}
+
+func (s *Set) IntLong(name string, short rune, value int, helpvalue ...string) *int {
+ s.IntVarLong(&value, name, short, helpvalue...)
+ return &value
+}
+
+func IntVar(p *int, name rune, helpvalue ...string) Option {
+ return CommandLine.IntVar(p, name, helpvalue...)
+}
+
+func (s *Set) IntVar(p *int, name rune, helpvalue ...string) Option {
+ return s.IntVarLong(p, "", name, helpvalue...)
+}
+
+func IntVarLong(p *int, name string, short rune, helpvalue ...string) Option {
+ return CommandLine.IntVarLong(p, name, short, helpvalue...)
+}
+
+func (s *Set) IntVarLong(p *int, name string, short rune, helpvalue ...string) Option {
+ return s.VarLong((*intValue)(p), name, short, helpvalue...)
+}
diff --git a/vendor/github.com/pborman/getopt/int16.go b/vendor/github.com/pborman/getopt/int16.go
new file mode 100644
index 0000000..2ece51f
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/int16.go
@@ -0,0 +1,67 @@
+// Copyright 2013 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package getopt
+
+import (
+ "fmt"
+ "strconv"
+)
+
+type int16Value int16
+
+func (i *int16Value) Set(value string, opt Option) error {
+ v, err := strconv.ParseInt(value, 0, 16)
+ if err != nil {
+ if e, ok := err.(*strconv.NumError); ok {
+ switch e.Err {
+ case strconv.ErrRange:
+ err = fmt.Errorf("value out of range: %s", value)
+ case strconv.ErrSyntax:
+ err = fmt.Errorf("not a valid number: %s", value)
+ }
+ }
+ return err
+ }
+ *i = int16Value(v)
+ return nil
+}
+
+func (i *int16Value) String() string {
+ return strconv.FormatInt(int64(*i), 10)
+}
+
+// Int16 creates an option that parses its value as an int16.
+func Int16(name rune, value int16, helpvalue ...string) *int16 {
+ return CommandLine.Int16(name, value, helpvalue...)
+}
+
+func (s *Set) Int16(name rune, value int16, helpvalue ...string) *int16 {
+ return s.Int16Long("", name, value, helpvalue...)
+}
+
+func Int16Long(name string, short rune, value int16, helpvalue ...string) *int16 {
+ return CommandLine.Int16Long(name, short, value, helpvalue...)
+}
+
+func (s *Set) Int16Long(name string, short rune, value int16, helpvalue ...string) *int16 {
+ s.Int16VarLong(&value, name, short, helpvalue...)
+ return &value
+}
+
+func Int16Var(p *int16, name rune, helpvalue ...string) Option {
+ return CommandLine.Int16Var(p, name, helpvalue...)
+}
+
+func (s *Set) Int16Var(p *int16, name rune, helpvalue ...string) Option {
+ return s.Int16VarLong(p, "", name, helpvalue...)
+}
+
+func Int16VarLong(p *int16, name string, short rune, helpvalue ...string) Option {
+ return CommandLine.Int16VarLong(p, name, short, helpvalue...)
+}
+
+func (s *Set) Int16VarLong(p *int16, name string, short rune, helpvalue ...string) Option {
+ return s.VarLong((*int16Value)(p), name, short, helpvalue...)
+}
diff --git a/vendor/github.com/pborman/getopt/int16_test.go b/vendor/github.com/pborman/getopt/int16_test.go
new file mode 100644
index 0000000..8b83c1e
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/int16_test.go
@@ -0,0 +1,84 @@
+// Copyright 2013 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package getopt
+
+import (
+ "fmt"
+ "strings"
+ "testing"
+)
+
+var int16Tests = []struct {
+ where string
+ in []string
+ i int16
+ int16 int16
+ err string
+}{
+ {
+ loc(),
+ []string{},
+ 17, 42,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i", "1", "--int16", "2"},
+ 1, 2,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i1", "--int16=2"},
+ 1, 2,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i1", "-i2"},
+ 2, 42,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i=1"},
+ 17, 42,
+ "test: not a valid number: =1\n",
+ },
+ {
+ loc(),
+ []string{"test", "-i0x20"},
+ 0x20, 42,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i010"},
+ 8, 42,
+ "",
+ },
+}
+
+func TestInt16(t *testing.T) {
+ for x, tt := range int16Tests {
+ reset()
+ i := Int16('i', 17)
+ opt := Int16Long("int16", 0, 42)
+ if strings.Index(tt.where, ":-") > 0 {
+ tt.where = fmt.Sprintf("#%d", x)
+ }
+
+ parse(tt.in)
+ if s := checkError(tt.err); s != "" {
+ t.Errorf("%s: %s", tt.where, s)
+ }
+ if got, want := *i, tt.i; got != want {
+ t.Errorf("%s: got %v, want %v", tt.where, got, want)
+ }
+ if got, want := *opt, tt.int16; got != want {
+ t.Errorf("%s: got %v, want %v", tt.where, got, want)
+ }
+ }
+}
diff --git a/vendor/github.com/pborman/getopt/int32.go b/vendor/github.com/pborman/getopt/int32.go
new file mode 100644
index 0000000..b8f3415
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/int32.go
@@ -0,0 +1,67 @@
+// Copyright 2013 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package getopt
+
+import (
+ "fmt"
+ "strconv"
+)
+
+type int32Value int32
+
+func (i *int32Value) Set(value string, opt Option) error {
+ v, err := strconv.ParseInt(value, 0, 32)
+ if err != nil {
+ if e, ok := err.(*strconv.NumError); ok {
+ switch e.Err {
+ case strconv.ErrRange:
+ err = fmt.Errorf("value out of range: %s", value)
+ case strconv.ErrSyntax:
+ err = fmt.Errorf("not a valid number: %s", value)
+ }
+ }
+ return err
+ }
+ *i = int32Value(v)
+ return nil
+}
+
+func (i *int32Value) String() string {
+ return strconv.FormatInt(int64(*i), 10)
+}
+
+// Int32 creates an option that parses its value as an int32.
+func Int32(name rune, value int32, helpvalue ...string) *int32 {
+ return CommandLine.Int32(name, value, helpvalue...)
+}
+
+func (s *Set) Int32(name rune, value int32, helpvalue ...string) *int32 {
+ return s.Int32Long("", name, value, helpvalue...)
+}
+
+func Int32Long(name string, short rune, value int32, helpvalue ...string) *int32 {
+ return CommandLine.Int32Long(name, short, value, helpvalue...)
+}
+
+func (s *Set) Int32Long(name string, short rune, value int32, helpvalue ...string) *int32 {
+ s.Int32VarLong(&value, name, short, helpvalue...)
+ return &value
+}
+
+func Int32Var(p *int32, name rune, helpvalue ...string) Option {
+ return CommandLine.Int32Var(p, name, helpvalue...)
+}
+
+func (s *Set) Int32Var(p *int32, name rune, helpvalue ...string) Option {
+ return s.Int32VarLong(p, "", name, helpvalue...)
+}
+
+func Int32VarLong(p *int32, name string, short rune, helpvalue ...string) Option {
+ return CommandLine.Int32VarLong(p, name, short, helpvalue...)
+}
+
+func (s *Set) Int32VarLong(p *int32, name string, short rune, helpvalue ...string) Option {
+ return s.VarLong((*int32Value)(p), name, short, helpvalue...)
+}
diff --git a/vendor/github.com/pborman/getopt/int32_test.go b/vendor/github.com/pborman/getopt/int32_test.go
new file mode 100644
index 0000000..9da9aeb
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/int32_test.go
@@ -0,0 +1,84 @@
+// Copyright 2013 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package getopt
+
+import (
+ "fmt"
+ "strings"
+ "testing"
+)
+
+var int32Tests = []struct {
+ where string
+ in []string
+ i int32
+ int32 int32
+ err string
+}{
+ {
+ loc(),
+ []string{},
+ 17, 42,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i", "1", "--int32", "2"},
+ 1, 2,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i1", "--int32=2"},
+ 1, 2,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i1", "-i2"},
+ 2, 42,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i=1"},
+ 17, 42,
+ "test: not a valid number: =1\n",
+ },
+ {
+ loc(),
+ []string{"test", "-i0x20"},
+ 0x20, 42,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i010"},
+ 8, 42,
+ "",
+ },
+}
+
+func TestInt32(t *testing.T) {
+ for x, tt := range int32Tests {
+ reset()
+ i := Int32('i', 17)
+ opt := Int32Long("int32", 0, 42)
+ if strings.Index(tt.where, ":-") > 0 {
+ tt.where = fmt.Sprintf("#%d", x)
+ }
+
+ parse(tt.in)
+ if s := checkError(tt.err); s != "" {
+ t.Errorf("%s: %s", tt.where, s)
+ }
+ if got, want := *i, tt.i; got != want {
+ t.Errorf("%s: got %v, want %v", tt.where, got, want)
+ }
+ if got, want := *opt, tt.int32; got != want {
+ t.Errorf("%s: got %v, want %v", tt.where, got, want)
+ }
+ }
+}
diff --git a/vendor/github.com/pborman/getopt/int64.go b/vendor/github.com/pborman/getopt/int64.go
new file mode 100644
index 0000000..d29e6b4
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/int64.go
@@ -0,0 +1,67 @@
+// Copyright 2013 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package getopt
+
+import (
+ "fmt"
+ "strconv"
+)
+
+type int64Value int64
+
+func (i *int64Value) Set(value string, opt Option) error {
+ v, err := strconv.ParseInt(value, 0, 64)
+ if err != nil {
+ if e, ok := err.(*strconv.NumError); ok {
+ switch e.Err {
+ case strconv.ErrRange:
+ err = fmt.Errorf("value out of range: %s", value)
+ case strconv.ErrSyntax:
+ err = fmt.Errorf("not a valid number: %s", value)
+ }
+ }
+ return err
+ }
+ *i = int64Value(v)
+ return nil
+}
+
+func (i *int64Value) String() string {
+ return strconv.FormatInt(int64(*i), 10)
+}
+
+// Int64 creates an option that parses its value as an int64.
+func Int64(name rune, value int64, helpvalue ...string) *int64 {
+ return CommandLine.Int64(name, value, helpvalue...)
+}
+
+func (s *Set) Int64(name rune, value int64, helpvalue ...string) *int64 {
+ return s.Int64Long("", name, value, helpvalue...)
+}
+
+func Int64Long(name string, short rune, value int64, helpvalue ...string) *int64 {
+ return CommandLine.Int64Long(name, short, value, helpvalue...)
+}
+
+func (s *Set) Int64Long(name string, short rune, value int64, helpvalue ...string) *int64 {
+ s.Int64VarLong(&value, name, short, helpvalue...)
+ return &value
+}
+
+func Int64Var(p *int64, name rune, helpvalue ...string) Option {
+ return CommandLine.Int64Var(p, name, helpvalue...)
+}
+
+func (s *Set) Int64Var(p *int64, name rune, helpvalue ...string) Option {
+ return s.Int64VarLong(p, "", name, helpvalue...)
+}
+
+func Int64VarLong(p *int64, name string, short rune, helpvalue ...string) Option {
+ return CommandLine.Int64VarLong(p, name, short, helpvalue...)
+}
+
+func (s *Set) Int64VarLong(p *int64, name string, short rune, helpvalue ...string) Option {
+ return s.VarLong((*int64Value)(p), name, short, helpvalue...)
+}
diff --git a/vendor/github.com/pborman/getopt/int64_test.go b/vendor/github.com/pborman/getopt/int64_test.go
new file mode 100644
index 0000000..7fa01b5
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/int64_test.go
@@ -0,0 +1,84 @@
+// Copyright 2013 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package getopt
+
+import (
+ "fmt"
+ "strings"
+ "testing"
+)
+
+var int64Tests = []struct {
+ where string
+ in []string
+ i int64
+ int64 int64
+ err string
+}{
+ {
+ loc(),
+ []string{},
+ 17, 42,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i", "1", "--int64", "2"},
+ 1, 2,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i1", "--int64=2"},
+ 1, 2,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i1", "-i2"},
+ 2, 42,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i=1"},
+ 17, 42,
+ "test: not a valid number: =1\n",
+ },
+ {
+ loc(),
+ []string{"test", "-i0x20"},
+ 0x20, 42,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i010"},
+ 8, 42,
+ "",
+ },
+}
+
+func TestInt64(t *testing.T) {
+ for x, tt := range int64Tests {
+ reset()
+ i := Int64('i', 17)
+ opt := Int64Long("int64", 0, 42)
+ if strings.Index(tt.where, ":-") > 0 {
+ tt.where = fmt.Sprintf("#%d", x)
+ }
+
+ parse(tt.in)
+ if s := checkError(tt.err); s != "" {
+ t.Errorf("%s: %s", tt.where, s)
+ }
+ if got, want := *i, tt.i; got != want {
+ t.Errorf("%s: got %v, want %v", tt.where, got, want)
+ }
+ if got, want := *opt, tt.int64; got != want {
+ t.Errorf("%s: got %v, want %v", tt.where, got, want)
+ }
+ }
+}
diff --git a/vendor/github.com/pborman/getopt/int_test.go b/vendor/github.com/pborman/getopt/int_test.go
new file mode 100644
index 0000000..f12af31
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/int_test.go
@@ -0,0 +1,84 @@
+// Copyright 2013 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package getopt
+
+import (
+ "fmt"
+ "strings"
+ "testing"
+)
+
+var intTests = []struct {
+ where string
+ in []string
+ i int
+ int int
+ err string
+}{
+ {
+ loc(),
+ []string{},
+ 17, 42,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i", "1", "--int", "2"},
+ 1, 2,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i1", "--int=2"},
+ 1, 2,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i1", "-i2"},
+ 2, 42,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i=1"},
+ 17, 42,
+ "test: not a valid number: =1\n",
+ },
+ {
+ loc(),
+ []string{"test", "-i0x20"},
+ 0x20, 42,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i010"},
+ 8, 42,
+ "",
+ },
+}
+
+func TestInt(t *testing.T) {
+ for x, tt := range intTests {
+ reset()
+ i := Int('i', 17)
+ opt := IntLong("int", 0, 42)
+ if strings.Index(tt.where, ":-") > 0 {
+ tt.where = fmt.Sprintf("#%d", x)
+ }
+
+ parse(tt.in)
+ if s := checkError(tt.err); s != "" {
+ t.Errorf("%s: %s", tt.where, s)
+ }
+ if got, want := *i, tt.i; got != want {
+ t.Errorf("%s: got %v, want %v", tt.where, got, want)
+ }
+ if got, want := *opt, tt.int; got != want {
+ t.Errorf("%s: got %v, want %v", tt.where, got, want)
+ }
+ }
+}
diff --git a/vendor/github.com/pborman/getopt/list.go b/vendor/github.com/pborman/getopt/list.go
new file mode 100644
index 0000000..b9d4267
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/list.go
@@ -0,0 +1,69 @@
+// Copyright 2013 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package getopt
+
+import "strings"
+
+type listValue []string
+
+func (s *listValue) Set(value string, opt Option) error {
+ a := strings.Split(value, ",")
+ // If this is the first time we are seen then nil out the
+ // default value.
+ if opt.Count() <= 1 {
+ *s = nil
+ }
+ *s = append(*s, a...)
+ return nil
+}
+
+func (s *listValue) String() string {
+ return strings.Join([]string(*s), ",")
+}
+
+// List creates an option that returns a slice of strings. The parameters
+// passed are converted from a comma seperated value list into a slice.
+// Subsequent occurrences append to the list.
+func List(name rune, helpvalue ...string) *[]string {
+ return CommandLine.List(name, helpvalue...)
+}
+
+func (s *Set) List(name rune, helpvalue ...string) *[]string {
+ p := []string{}
+ s.ListVar(&p, name, helpvalue...)
+ return &p
+}
+
+func ListLong(name string, short rune, helpvalue ...string) *[]string {
+ return CommandLine.ListLong(name, short, helpvalue...)
+}
+
+func (s *Set) ListLong(name string, short rune, helpvalue ...string) *[]string {
+ p := []string{}
+ s.ListVarLong(&p, name, short, helpvalue...)
+ return &p
+}
+
+// ListVar creats a list option and places the values in p. If p is pointing
+// to a list of values then those are considered the default values. The first
+// time name is seen in the options the list will be set to list specified by
+// the parameter to the option. Subsequent instances of the option will append
+// to the list.
+func ListVar(p *[]string, name rune, helpvalue ...string) Option {
+ return CommandLine.ListVar(p, name, helpvalue...)
+}
+
+func (s *Set) ListVar(p *[]string, name rune, helpvalue ...string) Option {
+ return s.ListVarLong(p, "", name, helpvalue...)
+}
+
+func ListVarLong(p *[]string, name string, short rune, helpvalue ...string) Option {
+ return CommandLine.ListVarLong(p, name, short, helpvalue...)
+}
+
+func (s *Set) ListVarLong(p *[]string, name string, short rune, helpvalue ...string) Option {
+ opt := s.VarLong((*listValue)(p), name, short, helpvalue...)
+ return opt
+}
diff --git a/vendor/github.com/pborman/getopt/list_test.go b/vendor/github.com/pborman/getopt/list_test.go
new file mode 100644
index 0000000..71f9c32
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/list_test.go
@@ -0,0 +1,99 @@
+// Copyright 2013 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package getopt
+
+import "testing"
+
+var listTests = []struct {
+ where string
+ in []string
+ l, list []string
+ err string
+}{
+ {
+ loc(),
+ []string{},
+ nil, nil,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-l", "one"},
+ []string{"one"}, nil,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-lone", "-ltwo"},
+ []string{"one", "two"}, nil,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "--list", "one"},
+ nil, []string{"one"},
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "--list=one", "--list=two"},
+ nil, []string{"one", "two"},
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "--list=one,two"},
+ nil, []string{"one", "two"},
+ "",
+ },
+}
+
+func TestList(t *testing.T) {
+ for _, tt := range listTests {
+ reset()
+ l := List('l')
+ list := ListLong("list", 0)
+
+ parse(tt.in)
+ if s := checkError(tt.err); s != "" {
+ t.Errorf("%s: %s", tt.where, s)
+ }
+ if badSlice(*l, tt.l) {
+ t.Errorf("%s: got s = %q, want %q", tt.where, *l, tt.l)
+ }
+ if badSlice(*list, tt.list) {
+ t.Errorf("%s: got s = %q, want %q", tt.where, *list, tt.list)
+ }
+ }
+}
+
+func TestDefaultList(t *testing.T) {
+ reset()
+ list := []string{"d1", "d2", "d3"}
+ ListVar(&list, 'l')
+ parse([]string{"test"})
+
+ want := []string{"d1", "d2", "d3"}
+ if badSlice(list, want) {
+ t.Errorf("got s = %q, want %q", list, want)
+ }
+
+ parse([]string{"test", "-l", "one"})
+ want = []string{"one"}
+ if badSlice(list, want) {
+ t.Errorf("got s = %q, want %q", list, want)
+ }
+
+ parse([]string{"test", "-l", "two"})
+ want = []string{"one", "two"}
+ if badSlice(list, want) {
+ t.Errorf("got s = %q, want %q", list, want)
+ }
+ Lookup('l').Reset()
+ want = []string{"d1", "d2", "d3"}
+ if badSlice(list, want) {
+ t.Errorf("got s = %q, want %q", list, want)
+ }
+}
diff --git a/vendor/github.com/pborman/getopt/option.go b/vendor/github.com/pborman/getopt/option.go
new file mode 100644
index 0000000..17dbe58
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/option.go
@@ -0,0 +1,193 @@
+// Copyright 2013 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package getopt
+
+import (
+ "fmt"
+ "strings"
+)
+
+// An Option can be either a Flag or a Value
+type Option interface {
+ // Name returns the name of the option. If the option has been seen
+ // then the last way it was referenced (short or long) is returned
+ // otherwise if there is a short name then this will be the short name
+ // as a string, else it will be the long name.
+ Name() string
+
+ // IsFlag returns true if Option is a flag.
+ IsFlag() bool
+
+ // Seen returns true if the flag was seen.
+ Seen() bool
+
+ // Count returns the number of times the flag was seen.
+ Count() int
+
+ // String returns the last value the option was set to.
+ String() string
+
+ // Value returns the Value of the option.
+ Value() Value
+
+ // SetOptional makes the value optional. The option and value are
+ // always a single argument. Either --option or --option=value. In
+ // the former case the value of the option does not change but the Set()
+ // will return true and the value returned by Count() is incremented.
+ // The short form is either -o or -ovalue. SetOptional returns
+ // the Option
+ SetOptional() Option
+
+ // SetFlag makes the value a flag. Flags are boolean values and
+ // normally do not taken a value. They are set to true when seen.
+ // If a value is passed in the long form then it must be on, case
+ // insenstive, one of "true", "false", "t", "f", "on", "off", "1", "0".
+ // SetFlag returns the Option
+ SetFlag() Option
+
+ // Reset resets the state of the option so it appears it has not
+ // yet been seen, including resetting the value of the option
+ // to its original default state.
+ Reset()
+}
+
+type option struct {
+ short rune // 0 means no short name
+ long string // "" means no long name
+ isLong bool // True if they used the long name
+ flag bool // true if a boolean flag
+ defval string // default value
+ optional bool // true if we take an optional value
+ help string // help message
+ where string // file where the option was defined
+ value Value // current value of option
+ count int // number of times we have seen this option
+ name string // name of the value (for usage)
+ uname string // name of the option (for usage)
+}
+
+// usageName returns the name of the option for printing usage lines in one
+// of the following forms:
+//
+// -f
+// --flag
+// -f, --flag
+// -s value
+// --set=value
+// -s, --set=value
+func (o *option) usageName() string {
+ // Don't print help messages if we have none and there is only one
+ // way to specify the option.
+ if o.help == "" && (o.short == 0 || o.long == "") {
+ return ""
+ }
+ n := ""
+
+ switch {
+ case o.short != 0 && o.long == "":
+ n = "-" + string(o.short)
+ case o.short == 0 && o.long != "":
+ n = " --" + o.long
+ case o.short != 0 && o.long != "":
+ n = "-" + string(o.short) + ", --" + o.long
+ }
+
+ switch {
+ case o.flag:
+ return n
+ case o.optional:
+ return n + "[=" + o.name + "]"
+ case o.long != "":
+ return n + "=" + o.name
+ }
+ return n + " " + o.name
+}
+
+// sortName returns the name to sort the option on.
+func (o *option) sortName() string {
+ if o.short != 0 {
+ return string(o.short) + o.long
+ }
+ return o.long[:1] + o.long
+}
+
+func (o *option) Seen() bool { return o.count > 0 }
+func (o *option) Count() int { return o.count }
+func (o *option) IsFlag() bool { return o.flag }
+func (o *option) String() string { return o.value.String() }
+func (o *option) SetOptional() Option { o.optional = true; return o }
+func (o *option) SetFlag() Option { o.flag = true; return o }
+
+func (o *option) Value() Value {
+ if o == nil {
+ return nil
+ }
+ return o.value
+}
+
+func (o *option) Name() string {
+ if !o.isLong && o.short != 0 {
+ return "-" + string(o.short)
+ }
+ return "--" + o.long
+}
+
+// Reset rests an option so that it appears it has not yet been seen.
+func (o *option) Reset() {
+ o.isLong = false
+ o.count = 0
+ o.value.Set(o.defval, o)
+}
+
+type optionList []*option
+
+func (ol optionList) Len() int { return len(ol) }
+func (ol optionList) Swap(i, j int) { ol[i], ol[j] = ol[j], ol[i] }
+func (ol optionList) Less(i, j int) bool {
+ // first check the short names (or the first letter of the long name)
+ // If they are not equal (case insensitive) then we have our answer
+ n1 := ol[i].sortName()
+ n2 := ol[j].sortName()
+ l1 := strings.ToLower(n1)
+ l2 := strings.ToLower(n2)
+ if l1 < l2 {
+ return true
+ }
+ if l2 < l1 {
+ return false
+ }
+ return n1 < n2
+}
+
+// AddOption add the option o to set CommandLine if o is not already in set
+// CommandLine.
+func AddOption(o Option) {
+ CommandLine.AddOption(o)
+}
+
+// AddOption add the option o to set s if o is not already in set s.
+func (s *Set) AddOption(o Option) {
+ opt := o.(*option)
+ for _, eopt := range s.options {
+ if opt == eopt {
+ return
+ }
+ }
+ if opt.short != 0 {
+ if oo, ok := s.shortOptions[opt.short]; ok {
+ fmt.Fprintf(stderr, "%s: -%c already declared at %s\n", opt.where, opt.short, oo.where)
+ exit(1)
+ }
+ s.shortOptions[opt.short] = opt
+ }
+ if opt.long != "" {
+ if oo, ok := s.longOptions[opt.long]; ok {
+ fmt.Fprintf(stderr, "%s: --%s already declared at %s\n", opt.where, opt.long, oo.where)
+ exit(1)
+ }
+ s.longOptions[opt.long] = opt
+ }
+ s.options = append(s.options, opt)
+}
diff --git a/vendor/github.com/pborman/getopt/set.go b/vendor/github.com/pborman/getopt/set.go
new file mode 100644
index 0000000..64d9ecf
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/set.go
@@ -0,0 +1,268 @@
+// Copyright 2013 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package getopt
+
+import (
+ "io"
+ "os"
+ "sort"
+)
+
+// A Termination says why Getopt returned.
+type State int
+
+const (
+ InProgress = State(iota) // Getopt is still running
+ Dash // Returned on "-"
+ DashDash // Returned on "--"
+ EndOfOptions // End of options reached
+ EndOfArguments // No more arguments
+ Terminated // Terminated by callback function
+ Failure // Terminated due to error
+ Unknown // Indicates internal error
+)
+
+type Set struct {
+ State // State of getopt
+
+ // args are the parameters remaining after parsing the optoins.
+ args []string
+
+ // program is the name of the program for usage and error messages.
+ // If not set it will automatically be set to the base name of the
+ // first argument passed to parse.
+ program string
+
+ // parameters is what is displayed on the usage line after displaying
+ // the various options.
+ parameters string
+
+ usage func() // usage should print the programs usage and exit.
+
+ shortOptions map[rune]*option
+ longOptions map[string]*option
+ options optionList
+}
+
+// New returns a newly created option set.
+func New() *Set {
+ s := &Set{
+ shortOptions: make(map[rune]*option),
+ longOptions: make(map[string]*option),
+ parameters: "[parameters ...]",
+ }
+
+ s.usage = func() {
+ s.PrintUsage(stderr)
+ }
+ return s
+}
+
+// The default set of command-line options.
+var CommandLine = New()
+
+// PrintUsage calls PrintUsage in the default option set.
+func PrintUsage(w io.Writer) { CommandLine.PrintUsage(w) }
+
+// Usage calls the usage function in the default option set.
+func Usage() { CommandLine.usage() }
+
+// Parse calls Parse in the default option set with the command line arguments
+// found in os.Args.
+func Parse() { CommandLine.Parse(os.Args) }
+
+// Getops returns the result of calling Getop in the default option set with the
+// command line arguments found in os.Args. The fn function, which may be nil,
+// is passed to Getopt.
+func Getopt(fn func(Option) bool) error { return CommandLine.Getopt(os.Args, fn) }
+
+// Arg returns the n'th command-line argument. Arg(0) is the first remaining
+// argument after options have been processed.
+func Arg(n int) string {
+ if n >= 0 && n < len(CommandLine.args) {
+ return CommandLine.args[n]
+ }
+ return ""
+}
+
+// Arg returns the n'th argument. Arg(0) is the first remaining
+// argument after options have been processed.
+func (s *Set) Arg(n int) string {
+ if n >= 0 && n < len(s.args) {
+ return s.args[n]
+ }
+ return ""
+}
+
+// Args returns the non-option command line arguments.
+func Args() []string {
+ return CommandLine.args
+}
+
+// Args returns the non-option arguments.
+func (s *Set) Args() []string {
+ return s.args
+}
+
+// NArgs returns the number of non-option command line arguments.
+func NArgs() int {
+ return len(CommandLine.args)
+}
+
+// NArgs returns the number of non-option arguments.
+func (s *Set) NArgs() int {
+ return len(s.args)
+}
+
+// SetParameters sets the parameters string for printing the command line
+// usage. It defaults to "[parameters ...]"
+func SetParameters(parameters string) {
+ CommandLine.parameters = parameters
+}
+
+// SetParameters sets the parameters string for printing the s's usage.
+// It defaults to "[parameters ...]"
+func (s *Set) SetParameters(parameters string) {
+ s.parameters = parameters
+}
+
+// SetProgram sets the program name to program. Nomrally it is determined
+// from the zeroth command line argument (see os.Args).
+func SetProgram(program string) {
+ CommandLine.program = program
+}
+
+// SetProgram sets s's program name to program. Nomrally it is determined
+// from the zeroth argument passed to Getopt or Parse.
+func (s *Set) SetProgram(program string) {
+ s.program = program
+}
+
+// SetUsage sets the function used by Parse to display the commands usage
+// on error. It defaults to calling PrintUsage(os.Stderr).
+func SetUsage(usage func()) {
+ CommandLine.usage = usage
+}
+
+// SetUsage sets the function used by Parse to display usage on error. It
+// defaults to calling f.PrintUsage(os.Stderr).
+func (s *Set) SetUsage(usage func()) {
+ s.usage = usage
+}
+
+// Lookup returns the Option associated with name. Name should either be
+// a rune (the short name) or a string (the long name).
+func Lookup(name interface{}) Option {
+ return CommandLine.Lookup(name)
+}
+
+// Lookup returns the Option associated with name in s. Name should either be
+// a rune (the short name) or a string (the long name).
+func (s *Set) Lookup(name interface{}) Option {
+ switch v := name.(type) {
+ case rune:
+ return s.shortOptions[v]
+ case int:
+ return s.shortOptions[rune(v)]
+ case string:
+ return s.longOptions[v]
+ }
+ return nil
+}
+
+// IsSet returns true if the Option associated with name was seen while
+// parsing the command line arguments. Name should either be a rune (the
+// short name) or a string (the long name).
+func IsSet(name interface{}) bool {
+ return CommandLine.IsSet(name)
+}
+
+// IsSet returns true if the Option associated with name was seen while
+// parsing s. Name should either be a rune (the short name) or a string (the
+// long name).
+func (s *Set) IsSet(name interface{}) bool {
+ if opt := s.Lookup(name); opt != nil {
+ return opt.Seen()
+ }
+ return false
+}
+
+// GetCount returns the number of times the Option associated with name has been
+// seen while parsing the command line arguments. Name should either be a rune
+// (the short name) or a string (the long name).
+func GetCount(name interface{}) int {
+ return CommandLine.GetCount(name)
+}
+
+// GetCount returns the number of times the Option associated with name has been
+// seen while parsing s's arguments. Name should either be a rune (the short
+// name) or a string (the long name).
+func (s *Set) GetCount(name interface{}) int {
+ if opt := s.Lookup(name); opt != nil {
+ return opt.Count()
+ }
+ return 0
+}
+
+// GetValue returns the final value set to the command-line Option with name.
+// If the option has not been seen while parsing s then the default value is
+// returned. Name should either be a rune (the short name) or a string (the
+// long name).
+func GetValue(name interface{}) string {
+ return CommandLine.GetValue(name)
+}
+
+// GetValue returns the final value set to the Option in s associated with name.
+// If the option has not been seen while parsing s then the default value is
+// returned. Name should either be a rune (the short name) or a string (the
+// long name).
+func (s *Set) GetValue(name interface{}) string {
+ if opt := s.Lookup(name); opt != nil {
+ return opt.String()
+ }
+ return ""
+}
+
+// Visit visits the command-line options in lexicographical order, calling fn
+// for each. It visits only those options that have been set.
+func Visit(fn func(Option)) { CommandLine.Visit(fn) }
+
+// Visit visits the options in s in lexicographical order, calling fn
+// for each. It visits only those options that have been set.
+func (s *Set) Visit(fn func(Option)) {
+ sort.Sort(s.options)
+ for _, opt := range s.options {
+ if opt.count > 0 {
+ fn(opt)
+ }
+ }
+}
+
+// VisitAll visits the options in s in lexicographical order, calling fn
+// for each. It visits all options, even those not set.
+func VisitAll(fn func(Option)) { CommandLine.VisitAll(fn) }
+
+// VisitAll visits the command-line flags in lexicographical order, calling fn
+// for each. It visits all flags, even those not set.
+func (s *Set) VisitAll(fn func(Option)) {
+ sort.Sort(s.options)
+ for _, opt := range s.options {
+ fn(opt)
+ }
+}
+
+// Reset resets all the command line options to the initial state so it
+// appears none of them have been seen.
+func Reset() {
+ CommandLine.Reset()
+}
+
+// Reset resets all the options in s to the initial state so it
+// appears none of them have been seen.
+func (s *Set) Reset() {
+ for _, opt := range s.options {
+ opt.Reset()
+ }
+}
diff --git a/vendor/github.com/pborman/getopt/signed.go b/vendor/github.com/pborman/getopt/signed.go
new file mode 100644
index 0000000..a0e059c
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/signed.go
@@ -0,0 +1,110 @@
+// Copyright 2013 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package getopt
+
+import (
+ "fmt"
+ "strconv"
+)
+
+type signed int64
+
+type SignedLimit struct {
+ Base int // Base for conversion as per strconv.ParseInt
+ Bits int // Number of bits as per strconv.ParseInt
+ Min int64 // Minimum allowed value if both Min and Max are not 0
+ Max int64 // Maximum allowed value if both Min and Max are not 0
+}
+
+var signedLimits = make(map[*signed]*SignedLimit)
+
+func (n *signed) Set(value string, opt Option) error {
+ l := signedLimits[n]
+ if l == nil {
+ return fmt.Errorf("no limits defined for %s", opt.Name())
+ }
+ v, err := strconv.ParseInt(value, l.Base, l.Bits)
+ if err != nil {
+ if e, ok := err.(*strconv.NumError); ok {
+ switch e.Err {
+ case strconv.ErrRange:
+ err = fmt.Errorf("value out of range: %s", value)
+ case strconv.ErrSyntax:
+ err = fmt.Errorf("not a valid number: %s", value)
+ }
+ }
+ return err
+ }
+ if l.Min != 0 || l.Max != 0 {
+ if v < l.Min {
+ return fmt.Errorf("value out of range (<%v): %s", l.Min, value)
+ }
+ if v > l.Max {
+ return fmt.Errorf("value out of range (>%v): %s", l.Max, value)
+ }
+ }
+ *n = signed(v)
+ return nil
+}
+
+func (n *signed) String() string {
+ l := signedLimits[n]
+ if l != nil && l.Base != 0 {
+ return strconv.FormatInt(int64(*n), l.Base)
+ }
+ return strconv.FormatInt(int64(*n), 10)
+}
+
+// Signed creates an option that is stored in an int64 and is constrained
+// by the limits pointed to by l. The Max and Min values are only used if
+// at least one of the values are not 0. If Base is 0, the base is implied by
+// the string's prefix: base 16 for "0x", base 8 for "0", and base 10 otherwise.
+func Signed(name rune, value int64, l *SignedLimit, helpvalue ...string) *int64 {
+ return CommandLine.Signed(name, value, l, helpvalue...)
+}
+
+func (s *Set) Signed(name rune, value int64, l *SignedLimit, helpvalue ...string) *int64 {
+ return s.SignedLong("", name, value, l, helpvalue...)
+}
+
+func SignedLong(name string, short rune, value int64, l *SignedLimit, helpvalue ...string) *int64 {
+ return CommandLine.SignedLong(name, short, value, l, helpvalue...)
+}
+
+func (s *Set) SignedLong(name string, short rune, value int64, l *SignedLimit, helpvalue ...string) *int64 {
+ s.SignedVarLong(&value, name, short, l, helpvalue...)
+ return &value
+}
+
+func SignedVar(p *int64, name rune, l *SignedLimit, helpvalue ...string) Option {
+ return CommandLine.SignedVar(p, name, l, helpvalue...)
+}
+
+func (s *Set) SignedVar(p *int64, name rune, l *SignedLimit, helpvalue ...string) Option {
+ return s.SignedVarLong(p, "", name, l, helpvalue...)
+}
+
+func SignedVarLong(p *int64, name string, short rune, l *SignedLimit, helpvalue ...string) Option {
+ return CommandLine.SignedVarLong(p, name, short, l, helpvalue...)
+}
+
+func (s *Set) SignedVarLong(p *int64, name string, short rune, l *SignedLimit, helpvalue ...string) Option {
+ opt := s.VarLong((*signed)(p), name, short, helpvalue...)
+ if l.Base > 36 || l.Base == 1 || l.Base < 0 {
+ fmt.Fprintf(stderr, "invalid base for %s: %d\n", opt.Name(), l.Base)
+ exit(1)
+ }
+ if l.Bits < 0 || l.Bits > 64 {
+ fmt.Fprintf(stderr, "invalid bit size for %s: %d\n", opt.Name(), l.Bits)
+ exit(1)
+ }
+ if l.Min > l.Max {
+ fmt.Fprintf(stderr, "min greater than max for %s\n", opt.Name())
+ exit(1)
+ }
+ lim := *l
+ signedLimits[(*signed)(p)] = &lim
+ return opt
+}
diff --git a/vendor/github.com/pborman/getopt/signed_test.go b/vendor/github.com/pborman/getopt/signed_test.go
new file mode 100644
index 0000000..2d0635a
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/signed_test.go
@@ -0,0 +1,97 @@
+// Copyright 2013 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package getopt
+
+import (
+ "fmt"
+ "strings"
+ "testing"
+)
+
+var signedNumberTests = []struct {
+ where string
+ in []string
+ l SignedLimit
+ out int64
+ err string
+}{
+ {
+ where: loc(),
+ },
+ {
+ loc(),
+ []string{"test", "-n", "1010"},
+ SignedLimit{Base: 2, Bits: 5},
+ 10,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-n", "1010"},
+ SignedLimit{Base: 2, Bits: 4},
+ 0,
+ "test: value out of range: 1010\n",
+ },
+ {
+ loc(),
+ []string{"test", "-n", "-1000"},
+ SignedLimit{Base: 2, Bits: 4},
+ -8,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-n", "3"},
+ SignedLimit{Min: 4, Max: 6},
+ 0,
+ "test: value out of range (<4): 3\n",
+ },
+ {
+ loc(),
+ []string{"test", "-n", "4"},
+ SignedLimit{Min: 4, Max: 6},
+ 4,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-n", "5"},
+ SignedLimit{Min: 4, Max: 6},
+ 5,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-n", "6"},
+ SignedLimit{Min: 4, Max: 6},
+ 6,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-n", "7"},
+ SignedLimit{Min: 4, Max: 6},
+ 0,
+ "test: value out of range (>6): 7\n",
+ },
+}
+
+func TestSigneds(t *testing.T) {
+ for x, tt := range signedNumberTests {
+ if strings.Index(tt.where, ":-") > 0 {
+ tt.where = fmt.Sprintf("#%d", x)
+ }
+
+ reset()
+ n := Signed('n', 0, &tt.l)
+ parse(tt.in)
+ if s := checkError(tt.err); s != "" {
+ t.Errorf("%s: %s", tt.where, s)
+ }
+ if *n != tt.out {
+ t.Errorf("%s: got %v, want %v", tt.where, *n, tt.out)
+ }
+ }
+}
diff --git a/vendor/github.com/pborman/getopt/string.go b/vendor/github.com/pborman/getopt/string.go
new file mode 100644
index 0000000..1121867
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/string.go
@@ -0,0 +1,53 @@
+// Copyright 2013 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package getopt
+
+type stringValue string
+
+func (s *stringValue) Set(value string, opt Option) error {
+ *s = stringValue(value)
+ return nil
+}
+
+func (s *stringValue) String() string {
+ return string(*s)
+}
+
+// String returns a value option that stores is value as a string. The
+// initial value of the string is passed in value.
+func String(name rune, value string, helpvalue ...string) *string {
+ return CommandLine.String(name, value, helpvalue...)
+}
+
+func (s *Set) String(name rune, value string, helpvalue ...string) *string {
+ p := value
+ s.StringVarLong(&p, "", name, helpvalue...)
+ return &p
+}
+
+func StringLong(name string, short rune, value string, helpvalue ...string) *string {
+ return CommandLine.StringLong(name, short, value, helpvalue...)
+}
+
+func (s *Set) StringLong(name string, short rune, value string, helpvalue ...string) *string {
+ s.StringVarLong(&value, name, short, helpvalue...)
+ return &value
+}
+
+func StringVar(p *string, name rune, helpvalue ...string) Option {
+ return CommandLine.StringVar(p, name, helpvalue...)
+}
+
+func (s *Set) StringVar(p *string, name rune, helpvalue ...string) Option {
+ return s.VarLong((*stringValue)(p), "", name, helpvalue...)
+}
+
+func StringVarLong(p *string, name string, short rune, helpvalue ...string) Option {
+ return CommandLine.StringVarLong(p, name, short, helpvalue...)
+}
+
+func (s *Set) StringVarLong(p *string, name string, short rune, helpvalue ...string) Option {
+ return s.VarLong((*stringValue)(p), name, short, helpvalue...)
+}
diff --git a/vendor/github.com/pborman/getopt/string_test.go b/vendor/github.com/pborman/getopt/string_test.go
new file mode 100644
index 0000000..c39a56c
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/string_test.go
@@ -0,0 +1,77 @@
+// Copyright 2013 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package getopt
+
+import "testing"
+
+var stringTests = []struct {
+ where string
+ in []string
+ sout string
+ optout string
+ err string
+}{
+ {
+ loc(),
+ []string{},
+ "one",
+ "two",
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-s"},
+ "one",
+ "two",
+ "test: missing parameter for -s\n",
+ },
+ {
+ loc(),
+ []string{"test", "--opt"},
+ "one",
+ "two",
+ "test: missing parameter for --opt\n",
+ },
+ {
+ loc(),
+ []string{"test", "-svalue", "--opt=option"},
+ "value",
+ "option",
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-s", "value", "--opt", "option"},
+ "value",
+ "option",
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-swrong", "--opt=wrong", "-s", "value", "--opt", "option"},
+ "value",
+ "option",
+ "",
+ },
+}
+
+func TestString(t *testing.T) {
+ for _, tt := range stringTests {
+ reset()
+ s := String('s', "one")
+ opt := StringLong("opt", 0, "two")
+
+ parse(tt.in)
+ if s := checkError(tt.err); s != "" {
+ t.Errorf("%s: %s", tt.where, s)
+ }
+ if *s != tt.sout {
+ t.Errorf("%s: got s = %q, want %q", tt.where, *s, tt.sout)
+ }
+ if *opt != tt.optout {
+ t.Errorf("%s: got opt = %q, want %q", tt.where, *opt, tt.optout)
+ }
+ }
+}
diff --git a/vendor/github.com/pborman/getopt/uint.go b/vendor/github.com/pborman/getopt/uint.go
new file mode 100644
index 0000000..bdb82b4
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/uint.go
@@ -0,0 +1,67 @@
+// Copyright 2013 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package getopt
+
+import (
+ "fmt"
+ "strconv"
+)
+
+type uintValue uint
+
+func (i *uintValue) Set(value string, opt Option) error {
+ v, err := strconv.ParseUint(value, 0, strconv.IntSize)
+ if err != nil {
+ if e, ok := err.(*strconv.NumError); ok {
+ switch e.Err {
+ case strconv.ErrRange:
+ err = fmt.Errorf("value out of range: %s", value)
+ case strconv.ErrSyntax:
+ err = fmt.Errorf("not a valid number: %s", value)
+ }
+ }
+ return err
+ }
+ *i = uintValue(v)
+ return nil
+}
+
+func (i *uintValue) String() string {
+ return strconv.FormatUint(uint64(*i), 10)
+}
+
+// Uint creates an option that parses its value as an unsigned integer.
+func Uint(name rune, value uint, helpvalue ...string) *uint {
+ return CommandLine.Uint(name, value, helpvalue...)
+}
+
+func (s *Set) Uint(name rune, value uint, helpvalue ...string) *uint {
+ return s.UintLong("", name, value, helpvalue...)
+}
+
+func UintLong(name string, short rune, value uint, helpvalue ...string) *uint {
+ return CommandLine.UintLong(name, short, value, helpvalue...)
+}
+
+func (s *Set) UintLong(name string, short rune, value uint, helpvalue ...string) *uint {
+ s.UintVarLong(&value, name, short, helpvalue...)
+ return &value
+}
+
+func UintVar(p *uint, name rune, helpvalue ...string) Option {
+ return CommandLine.UintVar(p, name, helpvalue...)
+}
+
+func (s *Set) UintVar(p *uint, name rune, helpvalue ...string) Option {
+ return s.UintVarLong(p, "", name, helpvalue...)
+}
+
+func UintVarLong(p *uint, name string, short rune, helpvalue ...string) Option {
+ return CommandLine.UintVarLong(p, name, short, helpvalue...)
+}
+
+func (s *Set) UintVarLong(p *uint, name string, short rune, helpvalue ...string) Option {
+ return s.VarLong((*uintValue)(p), name, short, helpvalue...)
+}
diff --git a/vendor/github.com/pborman/getopt/uint16.go b/vendor/github.com/pborman/getopt/uint16.go
new file mode 100644
index 0000000..92013e0
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/uint16.go
@@ -0,0 +1,67 @@
+// Copyright 2013 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package getopt
+
+import (
+ "fmt"
+ "strconv"
+)
+
+type uint16Value uint16
+
+func (i *uint16Value) Set(value string, opt Option) error {
+ v, err := strconv.ParseUint(value, 0, 16)
+ if err != nil {
+ if e, ok := err.(*strconv.NumError); ok {
+ switch e.Err {
+ case strconv.ErrRange:
+ err = fmt.Errorf("value out of range: %s", value)
+ case strconv.ErrSyntax:
+ err = fmt.Errorf("not a valid number: %s", value)
+ }
+ }
+ return err
+ }
+ *i = uint16Value(v)
+ return nil
+}
+
+func (i *uint16Value) String() string {
+ return strconv.FormatUint(uint64(*i), 10)
+}
+
+// Uint16 creates an option that parses its value as an uint16.
+func Uint16(name rune, value uint16, helpvalue ...string) *uint16 {
+ return CommandLine.Uint16(name, value, helpvalue...)
+}
+
+func (s *Set) Uint16(name rune, value uint16, helpvalue ...string) *uint16 {
+ return s.Uint16Long("", name, value, helpvalue...)
+}
+
+func Uint16Long(name string, short rune, value uint16, helpvalue ...string) *uint16 {
+ return CommandLine.Uint16Long(name, short, value, helpvalue...)
+}
+
+func (s *Set) Uint16Long(name string, short rune, value uint16, helpvalue ...string) *uint16 {
+ s.Uint16VarLong(&value, name, short, helpvalue...)
+ return &value
+}
+
+func Uint16Var(p *uint16, name rune, helpvalue ...string) Option {
+ return CommandLine.Uint16Var(p, name, helpvalue...)
+}
+
+func (s *Set) Uint16Var(p *uint16, name rune, helpvalue ...string) Option {
+ return s.Uint16VarLong(p, "", name, helpvalue...)
+}
+
+func Uint16VarLong(p *uint16, name string, short rune, helpvalue ...string) Option {
+ return CommandLine.Uint16VarLong(p, name, short, helpvalue...)
+}
+
+func (s *Set) Uint16VarLong(p *uint16, name string, short rune, helpvalue ...string) Option {
+ return s.VarLong((*uint16Value)(p), name, short, helpvalue...)
+}
diff --git a/vendor/github.com/pborman/getopt/uint16_test.go b/vendor/github.com/pborman/getopt/uint16_test.go
new file mode 100644
index 0000000..5363a0c
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/uint16_test.go
@@ -0,0 +1,84 @@
+// Copyright 2013 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package getopt
+
+import (
+ "fmt"
+ "strings"
+ "testing"
+)
+
+var uint16Tests = []struct {
+ where string
+ in []string
+ i uint16
+ uint16 uint16
+ err string
+}{
+ {
+ loc(),
+ []string{},
+ 17, 42,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i", "1", "--uint16", "2"},
+ 1, 2,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i1", "--uint16=2"},
+ 1, 2,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i1", "-i2"},
+ 2, 42,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i=1"},
+ 17, 42,
+ "test: not a valid number: =1\n",
+ },
+ {
+ loc(),
+ []string{"test", "-i0x20"},
+ 0x20, 42,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i010"},
+ 8, 42,
+ "",
+ },
+}
+
+func TestUint16(t *testing.T) {
+ for x, tt := range uint16Tests {
+ reset()
+ i := Uint16('i', 17)
+ opt := Uint16Long("uint16", 0, 42)
+ if strings.Index(tt.where, ":-") > 0 {
+ tt.where = fmt.Sprintf("#%d", x)
+ }
+
+ parse(tt.in)
+ if s := checkError(tt.err); s != "" {
+ t.Errorf("%s: %s", tt.where, s)
+ }
+ if got, want := *i, tt.i; got != want {
+ t.Errorf("%s: got %v, want %v", tt.where, got, want)
+ }
+ if got, want := *opt, tt.uint16; got != want {
+ t.Errorf("%s: got %v, want %v", tt.where, got, want)
+ }
+ }
+}
diff --git a/vendor/github.com/pborman/getopt/uint32.go b/vendor/github.com/pborman/getopt/uint32.go
new file mode 100644
index 0000000..abe911d
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/uint32.go
@@ -0,0 +1,67 @@
+// Copyright 2013 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package getopt
+
+import (
+ "fmt"
+ "strconv"
+)
+
+type uint32Value uint32
+
+func (i *uint32Value) Set(value string, opt Option) error {
+ v, err := strconv.ParseUint(value, 0, 32)
+ if err != nil {
+ if e, ok := err.(*strconv.NumError); ok {
+ switch e.Err {
+ case strconv.ErrRange:
+ err = fmt.Errorf("value out of range: %s", value)
+ case strconv.ErrSyntax:
+ err = fmt.Errorf("not a valid number: %s", value)
+ }
+ }
+ return err
+ }
+ *i = uint32Value(v)
+ return nil
+}
+
+func (i *uint32Value) String() string {
+ return strconv.FormatUint(uint64(*i), 10)
+}
+
+// Uint32 creates an option that parses its value as an uint32.
+func Uint32(name rune, value uint32, helpvalue ...string) *uint32 {
+ return CommandLine.Uint32(name, value, helpvalue...)
+}
+
+func (s *Set) Uint32(name rune, value uint32, helpvalue ...string) *uint32 {
+ return s.Uint32Long("", name, value, helpvalue...)
+}
+
+func Uint32Long(name string, short rune, value uint32, helpvalue ...string) *uint32 {
+ return CommandLine.Uint32Long(name, short, value, helpvalue...)
+}
+
+func (s *Set) Uint32Long(name string, short rune, value uint32, helpvalue ...string) *uint32 {
+ s.Uint32VarLong(&value, name, short, helpvalue...)
+ return &value
+}
+
+func Uint32Var(p *uint32, name rune, helpvalue ...string) Option {
+ return CommandLine.Uint32Var(p, name, helpvalue...)
+}
+
+func (s *Set) Uint32Var(p *uint32, name rune, helpvalue ...string) Option {
+ return s.Uint32VarLong(p, "", name, helpvalue...)
+}
+
+func Uint32VarLong(p *uint32, name string, short rune, helpvalue ...string) Option {
+ return CommandLine.Uint32VarLong(p, name, short, helpvalue...)
+}
+
+func (s *Set) Uint32VarLong(p *uint32, name string, short rune, helpvalue ...string) Option {
+ return s.VarLong((*uint32Value)(p), name, short, helpvalue...)
+}
diff --git a/vendor/github.com/pborman/getopt/uint32_test.go b/vendor/github.com/pborman/getopt/uint32_test.go
new file mode 100644
index 0000000..80b4d11
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/uint32_test.go
@@ -0,0 +1,84 @@
+// Copyright 2013 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package getopt
+
+import (
+ "fmt"
+ "strings"
+ "testing"
+)
+
+var uint32Tests = []struct {
+ where string
+ in []string
+ i uint32
+ uint32 uint32
+ err string
+}{
+ {
+ loc(),
+ []string{},
+ 17, 42,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i", "1", "--uint32", "2"},
+ 1, 2,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i1", "--uint32=2"},
+ 1, 2,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i1", "-i2"},
+ 2, 42,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i=1"},
+ 17, 42,
+ "test: not a valid number: =1\n",
+ },
+ {
+ loc(),
+ []string{"test", "-i0x20"},
+ 0x20, 42,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i010"},
+ 8, 42,
+ "",
+ },
+}
+
+func TestUint32(t *testing.T) {
+ for x, tt := range uint32Tests {
+ reset()
+ i := Uint32('i', 17)
+ opt := Uint32Long("uint32", 0, 42)
+ if strings.Index(tt.where, ":-") > 0 {
+ tt.where = fmt.Sprintf("#%d", x)
+ }
+
+ parse(tt.in)
+ if s := checkError(tt.err); s != "" {
+ t.Errorf("%s: %s", tt.where, s)
+ }
+ if got, want := *i, tt.i; got != want {
+ t.Errorf("%s: got %v, want %v", tt.where, got, want)
+ }
+ if got, want := *opt, tt.uint32; got != want {
+ t.Errorf("%s: got %v, want %v", tt.where, got, want)
+ }
+ }
+}
diff --git a/vendor/github.com/pborman/getopt/uint64.go b/vendor/github.com/pborman/getopt/uint64.go
new file mode 100644
index 0000000..788e97f
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/uint64.go
@@ -0,0 +1,67 @@
+// Copyright 2013 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package getopt
+
+import (
+ "fmt"
+ "strconv"
+)
+
+type uint64Value uint64
+
+func (i *uint64Value) Set(value string, opt Option) error {
+ v, err := strconv.ParseUint(value, 0, 64)
+ if err != nil {
+ if e, ok := err.(*strconv.NumError); ok {
+ switch e.Err {
+ case strconv.ErrRange:
+ err = fmt.Errorf("value out of range: %s", value)
+ case strconv.ErrSyntax:
+ err = fmt.Errorf("not a valid number: %s", value)
+ }
+ }
+ return err
+ }
+ *i = uint64Value(v)
+ return nil
+}
+
+func (i *uint64Value) String() string {
+ return strconv.FormatUint(uint64(*i), 10)
+}
+
+// Uint64 creates an option that parses its value as a uint64.
+func Uint64(name rune, value uint64, helpvalue ...string) *uint64 {
+ return CommandLine.Uint64(name, value, helpvalue...)
+}
+
+func (s *Set) Uint64(name rune, value uint64, helpvalue ...string) *uint64 {
+ return s.Uint64Long("", name, value, helpvalue...)
+}
+
+func Uint64Long(name string, short rune, value uint64, helpvalue ...string) *uint64 {
+ return CommandLine.Uint64Long(name, short, value, helpvalue...)
+}
+
+func (s *Set) Uint64Long(name string, short rune, value uint64, helpvalue ...string) *uint64 {
+ s.Uint64VarLong(&value, name, short, helpvalue...)
+ return &value
+}
+
+func Uint64Var(p *uint64, name rune, helpvalue ...string) Option {
+ return CommandLine.Uint64Var(p, name, helpvalue...)
+}
+
+func (s *Set) Uint64Var(p *uint64, name rune, helpvalue ...string) Option {
+ return s.Uint64VarLong(p, "", name, helpvalue...)
+}
+
+func Uint64VarLong(p *uint64, name string, short rune, helpvalue ...string) Option {
+ return CommandLine.Uint64VarLong(p, name, short, helpvalue...)
+}
+
+func (s *Set) Uint64VarLong(p *uint64, name string, short rune, helpvalue ...string) Option {
+ return s.VarLong((*uint64Value)(p), name, short, helpvalue...)
+}
diff --git a/vendor/github.com/pborman/getopt/uint64_test.go b/vendor/github.com/pborman/getopt/uint64_test.go
new file mode 100644
index 0000000..962d369
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/uint64_test.go
@@ -0,0 +1,84 @@
+// Copyright 2013 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package getopt
+
+import (
+ "fmt"
+ "strings"
+ "testing"
+)
+
+var uint64Tests = []struct {
+ where string
+ in []string
+ i uint64
+ uint64 uint64
+ err string
+}{
+ {
+ loc(),
+ []string{},
+ 17, 42,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i", "1", "--uint64", "2"},
+ 1, 2,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i1", "--uint64=2"},
+ 1, 2,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i1", "-i2"},
+ 2, 42,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i=1"},
+ 17, 42,
+ "test: not a valid number: =1\n",
+ },
+ {
+ loc(),
+ []string{"test", "-i0x20"},
+ 0x20, 42,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i010"},
+ 8, 42,
+ "",
+ },
+}
+
+func TestUint64(t *testing.T) {
+ for x, tt := range uint64Tests {
+ reset()
+ i := Uint64('i', 17)
+ opt := Uint64Long("uint64", 0, 42)
+ if strings.Index(tt.where, ":-") > 0 {
+ tt.where = fmt.Sprintf("#%d", x)
+ }
+
+ parse(tt.in)
+ if s := checkError(tt.err); s != "" {
+ t.Errorf("%s: %s", tt.where, s)
+ }
+ if got, want := *i, tt.i; got != want {
+ t.Errorf("%s: got %v, want %v", tt.where, got, want)
+ }
+ if got, want := *opt, tt.uint64; got != want {
+ t.Errorf("%s: got %v, want %v", tt.where, got, want)
+ }
+ }
+}
diff --git a/vendor/github.com/pborman/getopt/uint_test.go b/vendor/github.com/pborman/getopt/uint_test.go
new file mode 100644
index 0000000..48c38cb
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/uint_test.go
@@ -0,0 +1,84 @@
+// Copyright 2013 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package getopt
+
+import (
+ "fmt"
+ "strings"
+ "testing"
+)
+
+var uintTests = []struct {
+ where string
+ in []string
+ i uint
+ uint uint
+ err string
+}{
+ {
+ loc(),
+ []string{},
+ 17, 42,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i", "1", "--uint", "2"},
+ 1, 2,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i1", "--uint=2"},
+ 1, 2,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i1", "-i2"},
+ 2, 42,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i=1"},
+ 17, 42,
+ "test: not a valid number: =1\n",
+ },
+ {
+ loc(),
+ []string{"test", "-i0x20"},
+ 0x20, 42,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i010"},
+ 8, 42,
+ "",
+ },
+}
+
+func TestUint(t *testing.T) {
+ for x, tt := range uintTests {
+ reset()
+ i := Uint('i', 17)
+ opt := UintLong("uint", 0, 42)
+ if strings.Index(tt.where, ":-") > 0 {
+ tt.where = fmt.Sprintf("#%d", x)
+ }
+
+ parse(tt.in)
+ if s := checkError(tt.err); s != "" {
+ t.Errorf("%s: %s", tt.where, s)
+ }
+ if got, want := *i, tt.i; got != want {
+ t.Errorf("%s: got %v, want %v", tt.where, got, want)
+ }
+ if got, want := *opt, tt.uint; got != want {
+ t.Errorf("%s: got %v, want %v", tt.where, got, want)
+ }
+ }
+}
diff --git a/vendor/github.com/pborman/getopt/unsigned.go b/vendor/github.com/pborman/getopt/unsigned.go
new file mode 100644
index 0000000..3ded0e7
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/unsigned.go
@@ -0,0 +1,111 @@
+// Copyright 2013 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package getopt
+
+import (
+ "fmt"
+ "strconv"
+)
+
+type unsigned uint64
+
+type UnsignedLimit struct {
+ Base int // Base for conversion as per strconv.ParseInt
+ Bits int // Number of bits as per strconv.ParseInt
+ Min uint64 // Minimum allowed value if both Min and Max are not 0
+ Max uint64 // Maximum allowed value if both Min and Max are not 0
+}
+
+var unsignedLimits = make(map[*unsigned]*UnsignedLimit)
+
+func (n *unsigned) Set(value string, opt Option) error {
+ l := unsignedLimits[n]
+ if l == nil {
+ return fmt.Errorf("no limits defined for %s", opt.Name())
+ }
+ v, err := strconv.ParseUint(value, l.Base, l.Bits)
+ if err != nil {
+ if e, ok := err.(*strconv.NumError); ok {
+ switch e.Err {
+ case strconv.ErrRange:
+ err = fmt.Errorf("value out of range: %s", value)
+ case strconv.ErrSyntax:
+ err = fmt.Errorf("not a valid number: %s", value)
+ }
+ }
+ return err
+ }
+ if l.Min != 0 || l.Max != 0 {
+ if v < l.Min {
+ return fmt.Errorf("value out of range (<%v): %s", l.Min, value)
+ }
+ if v > l.Max {
+ return fmt.Errorf("value out of range (>%v): %s", l.Max, value)
+ }
+ }
+ *n = unsigned(v)
+ return nil
+}
+
+func (n *unsigned) String() string {
+ l := unsignedLimits[n]
+ if l != nil && l.Base != 0 {
+ return strconv.FormatUint(uint64(*n), l.Base)
+ }
+ return strconv.FormatUint(uint64(*n), 10)
+}
+
+// Unsigned creates an option that is stored in a uint64 and is
+// constrained by the limits pointed to by l. The Max and Min values are only
+// used if at least one of the values are not 0. If Base is 0, the base is
+// implied by the string's prefix: base 16 for "0x", base 8 for "0", and base
+// 10 otherwise.
+func Unsigned(name rune, value uint64, l *UnsignedLimit, helpvalue ...string) *uint64 {
+ return CommandLine.Unsigned(name, value, l, helpvalue...)
+}
+
+func (s *Set) Unsigned(name rune, value uint64, l *UnsignedLimit, helpvalue ...string) *uint64 {
+ return s.UnsignedLong("", name, value, l, helpvalue...)
+}
+
+func UnsignedLong(name string, short rune, value uint64, l *UnsignedLimit, helpvalue ...string) *uint64 {
+ return CommandLine.UnsignedLong(name, short, value, l, helpvalue...)
+}
+
+func (s *Set) UnsignedLong(name string, short rune, value uint64, l *UnsignedLimit, helpvalue ...string) *uint64 {
+ s.UnsignedVarLong(&value, name, short, l, helpvalue...)
+ return &value
+}
+
+func UnsignedVar(p *uint64, name rune, l *UnsignedLimit, helpvalue ...string) Option {
+ return CommandLine.UnsignedVar(p, name, l, helpvalue...)
+}
+
+func (s *Set) UnsignedVar(p *uint64, name rune, l *UnsignedLimit, helpvalue ...string) Option {
+ return s.UnsignedVarLong(p, "", name, l, helpvalue...)
+}
+
+func UnsignedVarLong(p *uint64, name string, short rune, l *UnsignedLimit, helpvalue ...string) Option {
+ return CommandLine.UnsignedVarLong(p, name, short, l, helpvalue...)
+}
+
+func (s *Set) UnsignedVarLong(p *uint64, name string, short rune, l *UnsignedLimit, helpvalue ...string) Option {
+ opt := s.VarLong((*unsigned)(p), name, short, helpvalue...)
+ if l.Base > 36 || l.Base == 1 || l.Base < 0 {
+ fmt.Fprintf(stderr, "invalid base for %s: %d\n", opt.Name(), l.Base)
+ exit(1)
+ }
+ if l.Bits < 0 || l.Bits > 64 {
+ fmt.Fprintf(stderr, "invalid bit size for %s: %d\n", opt.Name(), l.Bits)
+ exit(1)
+ }
+ if l.Min > l.Max {
+ fmt.Fprintf(stderr, "min greater than max for %s\n", opt.Name())
+ exit(1)
+ }
+ lim := *l
+ unsignedLimits[(*unsigned)(p)] = &lim
+ return opt
+}
diff --git a/vendor/github.com/pborman/getopt/unsigned_test.go b/vendor/github.com/pborman/getopt/unsigned_test.go
new file mode 100644
index 0000000..0fd60d4
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/unsigned_test.go
@@ -0,0 +1,97 @@
+// Copyright 2013 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package getopt
+
+import (
+ "fmt"
+ "strings"
+ "testing"
+)
+
+var unsignedTests = []struct {
+ where string
+ in []string
+ l UnsignedLimit
+ out uint64
+ err string
+}{
+ {
+ where: loc(),
+ },
+ {
+ loc(),
+ []string{"test", "-n", "1010"},
+ UnsignedLimit{Base: 2, Bits: 5},
+ 10,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-n", "1010"},
+ UnsignedLimit{Base: 2, Bits: 4},
+ 10,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-n", "1010"},
+ UnsignedLimit{Base: 2, Bits: 3},
+ 0,
+ "test: value out of range: 1010\n",
+ },
+ {
+ loc(),
+ []string{"test", "-n", "3"},
+ UnsignedLimit{Min: 4, Max: 6},
+ 0,
+ "test: value out of range (<4): 3\n",
+ },
+ {
+ loc(),
+ []string{"test", "-n", "4"},
+ UnsignedLimit{Min: 4, Max: 6},
+ 4,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-n", "5"},
+ UnsignedLimit{Min: 4, Max: 6},
+ 5,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-n", "6"},
+ UnsignedLimit{Min: 4, Max: 6},
+ 6,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-n", "7"},
+ UnsignedLimit{Min: 4, Max: 6},
+ 0,
+ "test: value out of range (>6): 7\n",
+ },
+}
+
+func TestUnsigneds(t *testing.T) {
+ for x, tt := range unsignedTests {
+ if strings.Index(tt.where, ":-") > 0 {
+ tt.where = fmt.Sprintf("#%d", x)
+ }
+
+ reset()
+ n := Unsigned('n', 0, &tt.l)
+ parse(tt.in)
+ if s := checkError(tt.err); s != "" {
+ t.Errorf("%s: %s", tt.where, s)
+ }
+ if *n != tt.out {
+ t.Errorf("%s: got %v, want %v", tt.where, *n, tt.out)
+ }
+ }
+}
diff --git a/vendor/github.com/pborman/getopt/util_test.go b/vendor/github.com/pborman/getopt/util_test.go
new file mode 100644
index 0000000..79a732a
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/util_test.go
@@ -0,0 +1,87 @@
+// Copyright 2013 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package getopt
+
+import (
+ "bytes"
+ "fmt"
+ "path"
+ "reflect"
+ "runtime"
+ "strings"
+)
+
+var errorString string
+
+func reset() {
+ CommandLine.shortOptions = make(map[rune]*option)
+ CommandLine.longOptions = make(map[string]*option)
+ CommandLine.options = nil
+ CommandLine.args = nil
+ CommandLine.program = ""
+ errorString = ""
+}
+
+func parse(args []string) {
+ err := CommandLine.Getopt(args, nil)
+ if err != nil {
+ b := &bytes.Buffer{}
+
+ fmt.Fprintln(b, CommandLine.program+": "+err.Error())
+ CommandLine.PrintUsage(b)
+ errorString = b.String()
+ }
+}
+
+func badSlice(a, b []string) bool {
+ if len(a) != len(b) {
+ return true
+ }
+ for x, v := range a {
+ if b[x] != v {
+ return true
+ }
+ }
+ return false
+}
+
+func loc() string {
+ _, file, line, _ := runtime.Caller(1)
+ return fmt.Sprintf("%s:%d", path.Base(file), line)
+}
+
+func (o *option) Equal(opt *option) bool {
+ if o.value != nil && opt.value == nil {
+ return false
+ }
+ if o.value == nil && opt.value != nil {
+ return false
+ }
+ if o.value != nil && o.value.String() != opt.value.String() {
+ return false
+ }
+
+ oc := *o
+ optc := *opt
+ oc.value = nil
+ optc.value = nil
+ return reflect.DeepEqual(&oc, &optc)
+}
+
+func newStringValue(s string) *stringValue { return (*stringValue)(&s) }
+
+func checkError(err string) string {
+ switch {
+ case err == errorString:
+ return ""
+ case err == "":
+ return fmt.Sprintf("unexpected error %q", errorString)
+ case errorString == "":
+ return fmt.Sprintf("did not get expected error %q", err)
+ case !strings.HasPrefix(errorString, err):
+ return fmt.Sprintf("got error %q, want %q", errorString, err)
+ }
+ return ""
+}
diff --git a/vendor/github.com/pborman/getopt/v2/bool.go b/vendor/github.com/pborman/getopt/v2/bool.go
new file mode 100644
index 0000000..2899bee
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/v2/bool.go
@@ -0,0 +1,36 @@
+// Copyright 2017 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package getopt
+
+// Bool creates a flag option that is a bool. Bools normally do not take a
+// value however one can be assigned by using the long form of the option:
+//
+// --option=true
+// --o=false
+//
+// The value is case insensitive and one of true, false, t, f, on, off, t and 0.
+func Bool(name rune, helpvalue ...string) *bool {
+ var b bool
+ CommandLine.Flag(&b, name, helpvalue...)
+ return &b
+}
+
+func BoolLong(name string, short rune, helpvalue ...string) *bool {
+ var p bool
+ CommandLine.FlagLong(&p, name, short, helpvalue...)
+ return &p
+}
+
+func (s *Set) Bool(name rune, helpvalue ...string) *bool {
+ var b bool
+ s.Flag(&b, name, helpvalue...)
+ return &b
+}
+
+func (s *Set) BoolLong(name string, short rune, helpvalue ...string) *bool {
+ var p bool
+ s.FlagLong(&p, name, short, helpvalue...)
+ return &p
+}
diff --git a/vendor/github.com/pborman/getopt/v2/bool_test.go b/vendor/github.com/pborman/getopt/v2/bool_test.go
new file mode 100644
index 0000000..0a90d96
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/v2/bool_test.go
@@ -0,0 +1,106 @@
+// Copyright 2017 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package getopt
+
+import (
+ "fmt"
+ "strings"
+ "testing"
+)
+
+var boolTests = []struct {
+ where string
+ in []string
+ f bool
+ fc int
+ opt bool
+ optc int
+ err string
+}{
+ {
+ loc(),
+ []string{},
+ false, 0,
+ false, 0,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-f", "--opt"},
+ true, 1,
+ true, 1,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "--f", "--opt"},
+ true, 1,
+ true, 1,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-ff", "-f", "--opt", "--opt"},
+ true, 3,
+ true, 2,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "--opt", "--opt=false"},
+ false, 0,
+ false, 2,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-f", "false"},
+ true, 1,
+ false, 0,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-f=false"},
+ true, 1,
+ false, 0,
+ "test: unknown option: -=\n",
+ },
+ {
+ loc(),
+ []string{"test", "-f", "false"},
+ true, 1,
+ false, 0,
+ "",
+ },
+}
+
+func TestBool(t *testing.T) {
+ for x, tt := range boolTests {
+ reset()
+ f := Bool('f')
+ opt := BoolLong("opt", 0)
+ if strings.Index(tt.where, ":-") > 0 {
+ tt.where = fmt.Sprintf("#%d", x)
+ }
+
+ parse(tt.in)
+ if s := checkError(tt.err); s != "" {
+ t.Errorf("%s: %s", tt.where, s)
+ }
+ if got, want := *f, tt.f; got != want {
+ t.Errorf("%s: got %v, want %v", tt.where, got, want)
+ }
+ if got, want := *opt, tt.opt; got != want {
+ t.Errorf("%s: got %v, want %v", tt.where, got, want)
+ }
+ if got, want := GetCount('f'), tt.fc; got != want {
+ t.Errorf("%s: got %v, want %v", tt.where, got, want)
+ }
+ if got, want := GetCount("opt"), tt.optc; got != want {
+ t.Errorf("%s: got %v, want %v", tt.where, got, want)
+ }
+ }
+}
diff --git a/vendor/github.com/pborman/getopt/v2/breakup_test.go b/vendor/github.com/pborman/getopt/v2/breakup_test.go
new file mode 100644
index 0000000..5609e50
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/v2/breakup_test.go
@@ -0,0 +1,34 @@
+// Copyright 2017 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package getopt
+
+import (
+ "testing"
+)
+
+var breakupTests = []struct {
+ in string
+ max int
+ out []string
+}{
+ {"", 8, []string{}},
+ {"a fox", 8, []string{"a fox"}},
+ {"a foxhound is sly", 2, []string{"a", "foxhound", "is", "sly"}},
+ {"a foxhound is sly", 5, []string{"a", "foxhound", "is", "sly"}},
+ {"a foxhound is sly", 6, []string{"a", "foxhound", "is sly"}},
+ {"a foxhound is sly", 7, []string{"a", "foxhound", "is sly"}},
+ {"a foxhound is sly", 8, []string{"a", "foxhound", "is sly"}},
+ {"a foxhound is sly", 9, []string{"a", "foxhound", "is sly"}},
+ {"a foxhound is sly", 10, []string{"a foxhound", "is sly"}},
+}
+
+func TestBreakup(t *testing.T) {
+ for x, tt := range breakupTests {
+ out := breakup(tt.in, tt.max)
+ if badSlice(out, tt.out) {
+ t.Errorf("#%d: got %v, want %v", x, out, tt.out)
+ }
+ }
+}
diff --git a/vendor/github.com/pborman/getopt/v2/counter.go b/vendor/github.com/pborman/getopt/v2/counter.go
new file mode 100644
index 0000000..ab10bc7
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/v2/counter.go
@@ -0,0 +1,69 @@
+// Copyright 2017 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package getopt
+
+import (
+ "fmt"
+ "strconv"
+)
+
+type counterValue int
+
+func (b *counterValue) Set(value string, opt Option) error {
+ if value == "" {
+ *b++
+ } else {
+ v, err := strconv.ParseInt(value, 0, strconv.IntSize)
+ if err != nil {
+ if e, ok := err.(*strconv.NumError); ok {
+ switch e.Err {
+ case strconv.ErrRange:
+ err = fmt.Errorf("value out of range: %s", value)
+ case strconv.ErrSyntax:
+ err = fmt.Errorf("not a valid number: %s", value)
+ }
+ }
+ return err
+ }
+ *b = counterValue(v)
+ }
+ return nil
+}
+
+func (b *counterValue) String() string {
+ return strconv.Itoa(int(*b))
+}
+
+// Counter creates a counting flag stored as an int. Each time the option
+// is seen while parsing the value is incremented. The value of the counter
+// may be explicitly set by using the long form:
+//
+// --counter=5
+// --c=5
+//
+// Further instances of the option will increment from the set value.
+func Counter(name rune, helpvalue ...string) *int {
+ var p int
+ CommandLine.FlagLong((*counterValue)(&p), "", name, helpvalue...).SetFlag()
+ return &p
+}
+
+func (s *Set) Counter(name rune, helpvalue ...string) *int {
+ var p int
+ s.FlagLong((*counterValue)(&p), "", name, helpvalue...).SetFlag()
+ return &p
+}
+
+func CounterLong(name string, short rune, helpvalue ...string) *int {
+ var p int
+ CommandLine.FlagLong((*counterValue)(&p), name, short, helpvalue...).SetFlag()
+ return &p
+}
+
+func (s *Set) CounterLong(name string, short rune, helpvalue ...string) *int {
+ var p int
+ s.FlagLong((*counterValue)(&p), name, short, helpvalue...).SetFlag()
+ return &p
+}
diff --git a/vendor/github.com/pborman/getopt/v2/counter_test.go b/vendor/github.com/pborman/getopt/v2/counter_test.go
new file mode 100644
index 0000000..b85a26d
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/v2/counter_test.go
@@ -0,0 +1,76 @@
+// Copyright 2017 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package getopt
+
+import (
+ "fmt"
+ "strings"
+ "testing"
+)
+
+var counterTests = []struct {
+ where string
+ in []string
+ c int
+ cnt int
+ err string
+}{
+ {
+ loc(),
+ []string{},
+ 0,
+ 0,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-c", "--cnt"},
+ 1,
+ 1,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-cc", "-c", "--cnt", "--cnt"},
+ 3,
+ 2,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "--c=17", "--cnt=42"},
+ 17,
+ 42,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "--cnt=false"},
+ 0, 0,
+ "test: not a valid number: false\n",
+ },
+}
+
+func TestCounter(t *testing.T) {
+ for x, tt := range counterTests {
+ reset()
+ c := Counter('c')
+ cnt := CounterLong("cnt", 0)
+ if strings.Index(tt.where, ":-") > 0 {
+ tt.where = fmt.Sprintf("#%d", x)
+ }
+
+ parse(tt.in)
+ if s := checkError(tt.err); s != "" {
+ t.Errorf("%s: %s", tt.where, s)
+ }
+ if got, want := *c, tt.c; got != want {
+ t.Errorf("%s: got %v, want %v", tt.where, got, want)
+ }
+ if got, want := *cnt, tt.cnt; got != want {
+ t.Errorf("%s: got %v, want %v", tt.where, got, want)
+ }
+ }
+}
diff --git a/vendor/github.com/pborman/getopt/v2/duration.go b/vendor/github.com/pborman/getopt/v2/duration.go
new file mode 100644
index 0000000..7607815
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/v2/duration.go
@@ -0,0 +1,28 @@
+// Copyright 2017 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package getopt
+
+import "time"
+
+// Duration creates an option that parses its value as a time.Duration.
+func Duration(name rune, value time.Duration, helpvalue ...string) *time.Duration {
+ CommandLine.FlagLong(&value, "", name, helpvalue...)
+ return &value
+}
+
+func (s *Set) Duration(name rune, value time.Duration, helpvalue ...string) *time.Duration {
+ s.FlagLong(&value, "", name, helpvalue...)
+ return &value
+}
+
+func DurationLong(name string, short rune, value time.Duration, helpvalue ...string) *time.Duration {
+ CommandLine.FlagLong(&value, name, short, helpvalue...)
+ return &value
+}
+
+func (s *Set) DurationLong(name string, short rune, value time.Duration, helpvalue ...string) *time.Duration {
+ s.FlagLong(&value, name, short, helpvalue...)
+ return &value
+}
diff --git a/vendor/github.com/pborman/getopt/v2/duration_test.go b/vendor/github.com/pborman/getopt/v2/duration_test.go
new file mode 100644
index 0000000..ffee177
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/v2/duration_test.go
@@ -0,0 +1,73 @@
+// Copyright 2017 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package getopt
+
+import (
+ "fmt"
+ "strings"
+ "testing"
+ "time"
+)
+
+var durationTests = []struct {
+ where string
+ in []string
+ d time.Duration
+ dur time.Duration
+ err string
+}{
+ {
+ loc(),
+ []string{},
+ 17, 42,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-d", "1s", "--duration", "2s"},
+ time.Second, 2 * time.Second,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-d1s", "-d2s"},
+ 2 * time.Second, 42,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-d1"},
+ 17, 42,
+ "test: time: missing unit in duration 1\n",
+ },
+ {
+ loc(),
+ []string{"test", "--duration", "foo"},
+ 17, 42,
+ "test: time: invalid duration foo\n",
+ },
+}
+
+func TestDuration(t *testing.T) {
+ for x, tt := range durationTests {
+ reset()
+ d := Duration('d', 17)
+ opt := DurationLong("duration", 0, 42)
+ if strings.Index(tt.where, ":-") > 0 {
+ tt.where = fmt.Sprintf("#%d", x)
+ }
+
+ parse(tt.in)
+ if s := checkError(tt.err); s != "" {
+ t.Errorf("%s: %s", tt.where, s)
+ }
+ if got, want := *d, tt.d; got != want {
+ t.Errorf("%s: got %v, want %v", tt.where, got, want)
+ }
+ if got, want := *opt, tt.dur; got != want {
+ t.Errorf("%s: got %v, want %v", tt.where, got, want)
+ }
+ }
+}
diff --git a/vendor/github.com/pborman/getopt/v2/enum.go b/vendor/github.com/pborman/getopt/v2/enum.go
new file mode 100644
index 0000000..1ca6ff9
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/v2/enum.go
@@ -0,0 +1,79 @@
+// Copyright 2017 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package getopt
+
+import (
+ "errors"
+ "fmt"
+ "sync"
+)
+
+type enumValue string
+
+var (
+ enumValuesMu sync.Mutex
+ enumValues = make(map[*enumValue]map[string]struct{})
+)
+
+func (s *enumValue) Set(value string, opt Option) error {
+ enumValuesMu.Lock()
+ es, ok := enumValues[s]
+ enumValuesMu.Unlock()
+ if !ok || es == nil {
+ return errors.New("this option has no values")
+ }
+ if _, ok := es[value]; !ok {
+ return errors.New("invalid value: " + value)
+ }
+ *s = enumValue(value)
+ return nil
+}
+
+func (s *enumValue) String() string {
+ return string(*s)
+}
+
+// Enum creates an option that can only be set to one of the enumerated strings
+// passed in values. Passing nil or an empty slice results in an option that
+// will always fail. If not "", value is the default value of the enum. If
+// value is not listed in values then Enum will produce an error on standard
+// error and then exit the program with a status of 1.
+func Enum(name rune, values []string, value string, helpvalue ...string) *string {
+ return CommandLine.Enum(name, values, value, helpvalue...)
+}
+
+func (s *Set) Enum(name rune, values []string, value string, helpvalue ...string) *string {
+ var p enumValue
+ p.define(values, value, &option{short: name})
+ s.FlagLong(&p, "", name, helpvalue...)
+ return (*string)(&p)
+}
+
+func EnumLong(name string, short rune, values []string, value string, helpvalue ...string) *string {
+ return CommandLine.EnumLong(name, short, values, value, helpvalue...)
+}
+
+func (s *Set) EnumLong(name string, short rune, values []string, value string, helpvalue ...string) *string {
+ var p enumValue
+ p.define(values, value, &option{short: short, long: name})
+ s.FlagLong(&p, name, short, helpvalue...)
+ return (*string)(&p)
+}
+
+func (e *enumValue) define(values []string, def string, opt Option) {
+ m := make(map[string]struct{})
+ for _, v := range values {
+ m[v] = struct{}{}
+ }
+ enumValuesMu.Lock()
+ enumValues[e] = m
+ enumValuesMu.Unlock()
+ if def != "" {
+ if err := e.Set(def, nil); err != nil {
+ fmt.Fprintf(stderr, "setting default for %s: %v\n", opt.Name(), err)
+ exit(1)
+ }
+ }
+}
diff --git a/vendor/github.com/pborman/getopt/v2/enum_test.go b/vendor/github.com/pborman/getopt/v2/enum_test.go
new file mode 100644
index 0000000..c854015
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/v2/enum_test.go
@@ -0,0 +1,79 @@
+// Copyright 2017 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package getopt
+
+import (
+ "fmt"
+ "strings"
+ "testing"
+)
+
+var enumTests = []struct {
+ where string
+ in []string
+ values []string
+ def string
+ out string
+ err string
+}{
+ {
+ loc(),
+ nil,
+ []string{},
+ "",
+ "",
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-e", "val1"},
+ []string{"val1", "val2"},
+ "",
+ "val1",
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-e", "val1", "-e", "val2"},
+ []string{"val1", "val2"},
+ "",
+ "val2",
+ "",
+ },
+ {
+ loc(),
+ []string{"test"},
+ []string{"val1", "val2"},
+ "val2",
+ "val2",
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-e", "val3"},
+ []string{"val1", "val2"},
+ "",
+ "",
+ "test: invalid value: val3\n",
+ },
+}
+
+func TestEnum(t *testing.T) {
+ for x, tt := range enumTests {
+ if strings.Index(tt.where, ":-") > 0 {
+ tt.where = fmt.Sprintf("#%d", x)
+ }
+
+ reset()
+ e := Enum('e', tt.values, tt.def)
+ parse(tt.in)
+ if s := checkError(tt.err); s != "" {
+ t.Errorf("%s: %s", tt.where, s)
+ }
+ if *e != tt.out {
+ t.Errorf("%s: got %v, want %v", tt.where, *e, tt.out)
+ }
+ }
+}
diff --git a/vendor/github.com/pborman/getopt/v2/error.go b/vendor/github.com/pborman/getopt/v2/error.go
new file mode 100644
index 0000000..6f668a3
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/v2/error.go
@@ -0,0 +1,93 @@
+// Copyright 2017 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package getopt
+
+import "fmt"
+
+// An Error is returned by Getopt when it encounters an error.
+type Error struct {
+ ErrorCode // General reason of failure.
+ Err error // The actual error.
+ Parameter string // Parameter passed to option, if any
+ Name string // Option that cause error, if any
+}
+
+// Error returns the error message, implementing the error interface.
+func (i *Error) Error() string { return i.Err.Error() }
+
+// An ErrorCode indicates what sort of error was encountered.
+type ErrorCode int
+
+const (
+ NoError = ErrorCode(iota)
+ UnknownOption // an invalid option was encountered
+ MissingParameter // the options parameter is missing
+ ExtraParameter // a value was set to a long flag
+ Invalid // attempt to set an invalid value
+)
+
+func (e ErrorCode) String() string {
+ switch e {
+ case UnknownOption:
+ return "unknow option"
+ case MissingParameter:
+ return "missing argument"
+ case ExtraParameter:
+ return "unxpected value"
+ case Invalid:
+ return "error setting value"
+ }
+ return "unknown error"
+}
+
+// unknownOption returns an Error indicating an unknown option was
+// encountered.
+func unknownOption(name interface{}) *Error {
+ i := &Error{ErrorCode: UnknownOption}
+ switch n := name.(type) {
+ case rune:
+ if n == '-' {
+ i.Name = "-"
+ } else {
+ i.Name = "-" + string(n)
+ }
+ case string:
+ i.Name = "--" + n
+ }
+ i.Err = fmt.Errorf("unknown option: %s", i.Name)
+ return i
+}
+
+// missingArg returns an Error inidicating option o was not passed
+// a required paramter.
+func missingArg(o Option) *Error {
+ return &Error{
+ ErrorCode: MissingParameter,
+ Name: o.Name(),
+ Err: fmt.Errorf("missing parameter for %s", o.Name()),
+ }
+}
+
+// extraArg returns an Error inidicating option o was passed the
+// unexpected paramter value.
+func extraArg(o Option, value string) *Error {
+ return &Error{
+ ErrorCode: ExtraParameter,
+ Name: o.Name(),
+ Parameter: value,
+ Err: fmt.Errorf("unexpected parameter passed to %s: %q", o.Name(), value),
+ }
+}
+
+// setError returns an Error inidicating option o and the specified
+// error while setting it to value.
+func setError(o Option, value string, err error) *Error {
+ return &Error{
+ ErrorCode: Invalid,
+ Name: o.Name(),
+ Parameter: value,
+ Err: err,
+ }
+}
diff --git a/vendor/github.com/pborman/getopt/v2/generic.go b/vendor/github.com/pborman/getopt/v2/generic.go
new file mode 100644
index 0000000..913f63b
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/v2/generic.go
@@ -0,0 +1,237 @@
+// Copyright 2017 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+package getopt
+
+import (
+ "fmt"
+ "strconv"
+ "strings"
+ "time"
+)
+
+type generic struct {
+ p interface{}
+}
+
+// Flag is shorthand for CommandLine.Flag.
+func Flag(v interface{}, short rune, helpvalue ...string) Option {
+ return CommandLine.long(v, "", short, helpvalue...)
+}
+
+// FlagLong is shorthand for CommandLine.LongFlag.
+func FlagLong(v interface{}, long string, short rune, helpvalue ...string) Option {
+ return CommandLine.long(v, long, short, helpvalue...)
+}
+
+// Flag calls FlagLong with only a short flag name.
+func (s *Set) Flag(v interface{}, short rune, helpvalue ...string) Option {
+ return s.long(v, "", short, helpvalue...)
+}
+
+// FlagLong returns an Option in Set s for setting v. If long is not "" then
+// the option has a long name, and if short is not 0, the option has a short
+// name. v must either be of type getopt.Value or a pointer to one of the
+// supported builtin types:
+//
+// bool, string, []string
+// int, int8, int16, int32, int64
+// uint, uint8, uint16, uint32, uint64
+// float32, float64
+// time.Duration
+//
+// FlagLong will panic if v is not a getopt.Value or one of the supported
+// builtin types.
+//
+// The default value of the flag is the value of v at the time FlagLong is
+// called.
+func (s *Set) FlagLong(v interface{}, long string, short rune, helpvalue ...string) Option {
+ return s.long(v, long, short, helpvalue...)
+}
+
+func (s *Set) long(v interface{}, long string, short rune, helpvalue ...string) (opt Option) {
+ // Fix up our location when we return.
+ if where := calledFrom(); where != "" {
+ defer func() {
+ if opt, ok := opt.(*option); ok {
+ opt.where = where
+ }
+ }()
+ }
+ switch p := v.(type) {
+ case Value:
+ return s.addFlag(p, long, short, helpvalue...)
+ case *bool:
+ return s.addFlag(&generic{v}, long, short, helpvalue...).SetFlag()
+ case *string, *[]string:
+ return s.addFlag(&generic{v}, long, short, helpvalue...)
+ case *int, *int8, *int16, *int32, *int64:
+ return s.addFlag(&generic{v}, long, short, helpvalue...)
+ case *uint, *uint8, *uint16, *uint32, *uint64:
+ return s.addFlag(&generic{v}, long, short, helpvalue...)
+ case *float32, *float64:
+ return s.addFlag(&generic{v}, long, short, helpvalue...)
+ case *time.Duration:
+ return s.addFlag(&generic{v}, long, short, helpvalue...)
+ default:
+ panic(fmt.Sprintf("unsupported flag type: %T", v))
+ }
+}
+
+func (g *generic) Set(value string, opt Option) error {
+ strconvErr := func(err error) error {
+ if e, ok := err.(*strconv.NumError); ok {
+ switch e.Err {
+ case strconv.ErrRange:
+ err = fmt.Errorf("value out of range: %s", value)
+ case strconv.ErrSyntax:
+ err = fmt.Errorf("not a valid number: %s", value)
+ }
+ }
+ return err
+ }
+ switch p := g.p.(type) {
+ case *bool:
+ switch strings.ToLower(value) {
+ case "", "1", "true", "on", "t":
+ *p = true
+ case "0", "false", "off", "f":
+ *p = false
+ default:
+ return fmt.Errorf("invalid value for bool %s: %q", opt.Name(), value)
+ }
+ return nil
+ case *string:
+ *p = value
+ return nil
+ case *[]string:
+ a := strings.Split(value, ",")
+ // If this is the first time we are seen then nil out the
+ // default value.
+ if opt.Count() <= 1 {
+ *p = nil
+ }
+ *p = append(*p, a...)
+ return nil
+ case *int:
+ i64, err := strconv.ParseInt(value, 0, strconv.IntSize)
+ if err == nil {
+ *p = int(i64)
+ }
+ return strconvErr(err)
+ case *int8:
+ i64, err := strconv.ParseInt(value, 0, 8)
+ if err == nil {
+ *p = int8(i64)
+ }
+ return strconvErr(err)
+ case *int16:
+ i64, err := strconv.ParseInt(value, 0, 16)
+ if err == nil {
+ *p = int16(i64)
+ }
+ return strconvErr(err)
+ case *int32:
+ i64, err := strconv.ParseInt(value, 0, 32)
+ if err == nil {
+ *p = int32(i64)
+ }
+ return strconvErr(err)
+ case *int64:
+ i64, err := strconv.ParseInt(value, 0, 64)
+ if err == nil {
+ *p = i64
+ }
+ return strconvErr(err)
+ case *uint:
+ u64, err := strconv.ParseUint(value, 0, strconv.IntSize)
+ if err == nil {
+ *p = uint(u64)
+ }
+ return strconvErr(err)
+ case *uint8:
+ u64, err := strconv.ParseUint(value, 0, 8)
+ if err == nil {
+ *p = uint8(u64)
+ }
+ return strconvErr(err)
+ case *uint16:
+ u64, err := strconv.ParseUint(value, 0, 16)
+ if err == nil {
+ *p = uint16(u64)
+ }
+ return strconvErr(err)
+ case *uint32:
+ u64, err := strconv.ParseUint(value, 0, 32)
+ if err == nil {
+ *p = uint32(u64)
+ }
+ return strconvErr(err)
+ case *uint64:
+ u64, err := strconv.ParseUint(value, 0, 64)
+ if err == nil {
+ *p = u64
+ }
+ return strconvErr(err)
+ case *float32:
+ f64, err := strconv.ParseFloat(value, 32)
+ if err == nil {
+ *p = float32(f64)
+ }
+ return strconvErr(err)
+ case *float64:
+ f64, err := strconv.ParseFloat(value, 64)
+ if err == nil {
+ *p = f64
+ }
+ return strconvErr(err)
+ case *time.Duration:
+ v, err := time.ParseDuration(value)
+ if err == nil {
+ *p = v
+ }
+ return err
+ }
+ panic("internal error")
+}
+
+func (g *generic) String() string {
+ switch p := g.p.(type) {
+ case *bool:
+ if *p {
+ return "true"
+ }
+ return "false"
+ case *string:
+ return *p
+ case *[]string:
+ return strings.Join([]string(*p), ",")
+ case *int:
+ return strconv.FormatInt(int64(*p), 10)
+ case *int8:
+ return strconv.FormatInt(int64(*p), 10)
+ case *int16:
+ return strconv.FormatInt(int64(*p), 10)
+ case *int32:
+ return strconv.FormatInt(int64(*p), 10)
+ case *int64:
+ return strconv.FormatInt(*p, 10)
+ case *uint:
+ return strconv.FormatUint(uint64(*p), 10)
+ case *uint8:
+ return strconv.FormatUint(uint64(*p), 10)
+ case *uint16:
+ return strconv.FormatUint(uint64(*p), 10)
+ case *uint32:
+ return strconv.FormatUint(uint64(*p), 10)
+ case *uint64:
+ return strconv.FormatUint(*p, 10)
+ case *float32:
+ return strconv.FormatFloat(float64(*p), 'g', -1, 32)
+ case *float64:
+ return strconv.FormatFloat(*p, 'g', -1, 64)
+ case *time.Duration:
+ return p.String()
+ }
+ panic("internal error")
+}
diff --git a/vendor/github.com/pborman/getopt/v2/generic_test.go b/vendor/github.com/pborman/getopt/v2/generic_test.go
new file mode 100644
index 0000000..9a247ec
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/v2/generic_test.go
@@ -0,0 +1,319 @@
+// Copyright 2017 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package getopt
+
+import (
+ "bytes"
+ "fmt"
+ "os"
+ "reflect"
+ "runtime"
+ "strings"
+ "testing"
+ "time"
+)
+
+func TestGeneric(t *testing.T) {
+ const (
+ shortTest = iota
+ longTest
+ bothTest
+ )
+ for _, tt := range []struct {
+ where string
+ kind int
+ val interface{}
+ str string
+ def interface{}
+ in []string
+ err string
+ }{
+ // Do all four tests for string, the rest can mostly just use
+ // shortTest (the 0 value).
+ {
+ where: loc(),
+ kind: shortTest,
+ val: "42",
+ str: "42",
+ in: []string{"test", "-s", "42"},
+ },
+ {
+ where: loc(),
+ kind: longTest,
+ val: "42",
+ str: "42",
+ in: []string{"test", "--long", "42"},
+ },
+ {
+ where: loc(),
+ kind: bothTest,
+ val: "42",
+ str: "42",
+ in: []string{"test", "--both", "42"},
+ },
+ {
+ where: loc(),
+ kind: bothTest,
+ val: "42",
+ str: "42",
+ in: []string{"test", "-b", "42"},
+ },
+ {
+ where: loc(),
+ val: "42",
+ def: "42",
+ str: "42",
+ in: []string{"test"},
+ },
+ {
+ where: loc(),
+ val: "42",
+ def: "43",
+ str: "42",
+ in: []string{"test", "-s", "42"},
+ },
+
+ {
+ where: loc(),
+ val: true,
+ str: "true",
+ in: []string{"test", "-s"},
+ },
+ {
+ where: loc(),
+ val: true,
+ def: true,
+ str: "true",
+ in: []string{"test"},
+ },
+ {
+ where: loc(),
+ kind: longTest,
+ val: false,
+ str: "false",
+ in: []string{"test", "--long=false"},
+ },
+ {
+ where: loc(),
+ kind: longTest,
+ val: false,
+ def: true,
+ str: "false",
+ in: []string{"test", "--long=false"},
+ },
+
+ {
+ where: loc(),
+ val: int(42),
+ str: "42",
+ in: []string{"test", "-s", "42"},
+ },
+ {
+ where: loc(),
+ val: int8(42),
+ str: "42",
+ in: []string{"test", "-s", "42"},
+ },
+ {
+ where: loc(),
+ val: int16(42),
+ str: "42",
+ in: []string{"test", "-s", "42"},
+ },
+ {
+ where: loc(),
+ val: int32(42),
+ str: "42",
+ in: []string{"test", "-s", "42"},
+ },
+ {
+ where: loc(),
+ val: int64(42),
+ str: "42",
+ in: []string{"test", "-s", "42"},
+ },
+
+ {
+ where: loc(),
+ val: uint(42),
+ str: "42",
+ in: []string{"test", "-s", "42"},
+ },
+ {
+ where: loc(),
+ val: uint8(42),
+ str: "42",
+ in: []string{"test", "-s", "42"},
+ },
+ {
+ where: loc(),
+ val: uint16(42),
+ str: "42",
+ in: []string{"test", "-s", "42"},
+ },
+ {
+ where: loc(),
+ val: uint32(42),
+ str: "42",
+ in: []string{"test", "-s", "42"},
+ },
+ {
+ where: loc(),
+ val: uint64(42),
+ str: "42",
+ in: []string{"test", "-s", "42"},
+ },
+
+ {
+ where: loc(),
+ val: float32(4.2),
+ str: "4.2",
+ in: []string{"test", "-s", "4.2"},
+ },
+ {
+ where: loc(),
+ val: float64(4.2),
+ str: "4.2",
+ in: []string{"test", "-s", "4.2"},
+ },
+
+ {
+ where: loc(),
+ val: time.Duration(time.Second * 42),
+ def: time.Second * 2,
+ str: "42s",
+ in: []string{"test", "-s", "42s"},
+ },
+ {
+ where: loc(),
+ val: time.Duration(time.Second * 42),
+ def: time.Second * 2,
+ str: "42s",
+ in: []string{"test", "-s42s"},
+ },
+ {
+ where: loc(),
+ val: time.Duration(time.Second * 2),
+ def: time.Second * 2,
+ in: []string{"test", "-s42"},
+ str: "2s",
+ err: "test: time: missing unit in duration 42",
+ },
+
+ {
+ where: loc(),
+ val: []string{"42", "."},
+ str: "42,.",
+ def: []string{"one", "two", "three"},
+ in: []string{"test", "-s42", "-s."},
+ },
+ {
+ where: loc(),
+ val: []string{"42", "."},
+ str: "42,.",
+ def: []string{"one", "two", "three"},
+ in: []string{"test", "-s42,."},
+ },
+ {
+ where: loc(),
+ val: []string{"one", "two", "three"},
+ def: []string{"one", "two", "three"},
+ str: "one,two,three",
+ in: []string{"test"},
+ },
+ } {
+ reset()
+ var opt Option
+ val := reflect.New(reflect.TypeOf(tt.val)).Interface()
+ if tt.def != nil {
+ reflect.ValueOf(val).Elem().Set(reflect.ValueOf(tt.def))
+ }
+ switch tt.kind {
+ case shortTest:
+ opt = Flag(val, 's')
+ case longTest:
+ opt = FlagLong(val, "long", 0)
+ case bothTest:
+ opt = FlagLong(val, "both", 'b')
+ }
+ _ = opt
+ parse(tt.in)
+ if s := checkError(tt.err); s != "" {
+ t.Errorf("%s: %s", tt.where, s)
+ continue
+ }
+ got := reflect.ValueOf(val).Elem().Interface()
+ want := reflect.ValueOf(tt.val).Interface()
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("%s: got %v, want %v", tt.where, got, want)
+ }
+ if str := opt.String(); str != tt.str {
+ t.Errorf("%s: got string %q, want %q", tt.where, str, tt.str)
+ }
+ }
+}
+
+func TestGenericDup(t *testing.T) {
+ defer func() {
+ stderr = os.Stderr
+ exit = os.Exit
+ }()
+
+ reset()
+ var v1, v2 string
+ type myPanic struct{}
+ var errbuf bytes.Buffer
+ stderr = &errbuf
+ _, file, line, _ := runtime.Caller(0)
+ Flag(&v1, 's')
+ line++ // line is now the line number of the first call to Flag.
+
+ exit = func(i int) { panic(myPanic{}) }
+ defer func() {
+ p := recover()
+ if _, ok := p.(myPanic); ok {
+ err := errbuf.String()
+ if !strings.Contains(err, "-s already declared") || !strings.Contains(err, fmt.Sprintf("%s:%d", file, line)) {
+ t.Errorf("unexpected error: %q\nshould contain \"-s already declared\" and \"%s:%d\"", err, file, line)
+ }
+ } else if p == nil {
+ t.Errorf("Second call to Flag did not fail")
+ } else {
+ t.Errorf("panic %v", p)
+ }
+ }()
+ Flag(&v2, 's')
+}
+
+func TestGenericDupNested(t *testing.T) {
+ defer func() {
+ stderr = os.Stderr
+ exit = os.Exit
+ }()
+
+ reset()
+ type myPanic struct{}
+ var errbuf bytes.Buffer
+ stderr = &errbuf
+ _, file, line, _ := runtime.Caller(0)
+ String('s', "default")
+ line++ // line is now the line number of the first call to Flag.
+
+ exit = func(i int) { panic(myPanic{}) }
+ defer func() {
+ p := recover()
+ if _, ok := p.(myPanic); ok {
+ err := errbuf.String()
+ if !strings.Contains(err, "-s already declared") || !strings.Contains(err, fmt.Sprintf("%s:%d", file, line)) {
+ t.Errorf("unexpected error: %q\nshould contain \"-s already declared\" and \"%s:%d\"", err, file, line)
+ }
+ } else if p == nil {
+ t.Errorf("Second call to Flag did not fail")
+ } else {
+ t.Errorf("panic %v", p)
+ }
+ }()
+ String('s', "default")
+}
diff --git a/vendor/github.com/pborman/getopt/v2/getopt.go b/vendor/github.com/pborman/getopt/v2/getopt.go
new file mode 100644
index 0000000..cbab895
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/v2/getopt.go
@@ -0,0 +1,520 @@
+// Copyright 2017 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package getopt (v2) provides traditional getopt processing for implementing
+// commands that use traditional command lines. The standard Go flag package
+// cannot be used to write a program that parses flags the way ls or ssh does,
+// for example. Version 2 of this package has a simplified API.
+//
+// USAGE
+//
+// Getopt supports functionality found in both the standard BSD getopt as well
+// as (one of the many versions of) the GNU getopt_long. Being a Go package,
+// this package makes common usage easy, but still enables more controlled usage
+// if needed.
+//
+// Typical usage:
+//
+// // Declare flags and have getopt return pointers to the values.
+// helpFlag := getopt.Bool('?', "display help")
+// cmdFlag := getopt.StringLong("command", 'c', "default", "the command)
+//
+// // Declare flags against existing variables.
+// var {
+// fileName = "/the/default/path"
+// timeout = time.Second * 5
+// verbose bool
+// }
+// func init() {
+// getopt.Flag(&verbose, 'v', "be verbose")
+// getopt.FlagLong(&fileName, "path", 0, "the path")
+// getopt.FlagLong(&timeout, "timeout", 't', "some timeout")
+// }
+//
+// func main() {
+// // Parse the program arguments
+// getopt.Parse()
+// // Get the remaining positional parameters
+// args := getopt.Args()
+// ...
+//
+// If you don't want the program to exit on error, use getopt.Getopt:
+//
+// err := getopt.Getopt(nil)
+// if err != nil {
+// // code to handle error
+// fmt.Fprintln(os.Stderr, err)
+// }
+//
+// FLAG SYNTAX
+//
+// Support is provided for both short (-f) and long (--flag) options. A single
+// option may have both a short and a long name. Each option may be a flag or a
+// value. A value takes an argument.
+//
+// Declaring no long names causes this package to process arguments like the
+// traditional BSD getopt.
+//
+// Short flags may be combined into a single parameter. For example, "-a -b -c"
+// may also be expressed "-abc". Long flags must stand on their own "--alpha
+// --beta"
+//
+// Values require an argument. For short options the argument may either be
+// immediately following the short name or as the next argument. Only one short
+// value may be combined with short flags in a single argument; the short value
+// must be after all short flags. For example, if f is a flag and v is a value,
+// then:
+//
+// -vvalue (sets v to "value")
+// -v value (sets v to "value")
+// -fvvalue (sets f, and sets v to "value")
+// -fv value (sets f, and sets v to "value")
+// -vf value (set v to "f" and value is the first parameter)
+//
+// For the long value option val:
+//
+// --val value (sets val to "value")
+// --val=value (sets val to "value")
+// --valvalue (invalid option "valvalue")
+//
+// Values with an optional value only set the value if the value is part of the
+// same argument. In any event, the option count is increased and the option is
+// marked as seen.
+//
+// -v -f (sets v and f as being seen)
+// -vvalue -f (sets v to "value" and sets f)
+// --val -f (sets v and f as being seen)
+// --val=value -f (sets v to "value" and sets f)
+//
+// There is no convenience function defined for making the value optional. The
+// SetOptional method must be called on the actual Option.
+//
+// v := String("val", 'v', "", "the optional v")
+// Lookup("v").SetOptional()
+//
+// var s string
+// FlagLong(&s, "val", 'v', "the optional v).SetOptional()
+//
+// Parsing continues until the first non-option or "--" is encountered.
+//
+// The short name "-" can be used, but it either is specified as "-" or as part
+// of a group of options, for example "-f-". If there are no long options
+// specified then "--f" could also be used. If "-" is not declared as an option
+// then the single "-" will also terminate the option processing but unlike
+// "--", the "-" will be part of the remaining arguments.
+//
+// ADVANCED USAGE
+//
+// Normally the parsing is performed by calling the Parse function. If it is
+// important to see the order of the options then the Getopt function should be
+// used. The standard Parse function does the equivalent of:
+//
+// func Parse() {
+// if err := getopt.Getopt(os.Args, nil); err != nil {
+// fmt.Fprintln(os.Stderr, err)
+// s.usage()
+// os.Exit(1)
+// }
+//
+// When calling Getopt it is the responsibility of the caller to print any
+// errors.
+//
+// Normally the default option set, CommandLine, is used. Other option sets may
+// be created with New.
+//
+// After parsing, the sets Args will contain the non-option arguments. If an
+// error is encountered then Args will begin with argument that caused the
+// error.
+//
+// It is valid to call a set's Parse a second time to amen flags or values. As
+// an example:
+//
+// var a = getopt.Bool('a', "", "The a flag")
+// var b = getopt.Bool('b', "", "The a flag")
+// var cmd = ""
+//
+// var opts = getopt.CommandLine
+//
+// opts.Parse(os.Args)
+// if opts.NArgs() > 0 {
+// cmd = opts.Arg(0)
+// opts.Parse(opts.Args())
+// }
+//
+// If called with set to { "prog", "-a", "cmd", "-b", "arg" } then both and and
+// b would be set, cmd would be set to "cmd", and opts.Args() would return {
+// "arg" }.
+//
+// Unless an option type explicitly prohibits it, an option may appear more than
+// once in the arguments. The last value provided to the option is the value.
+//
+// BUILTIN TYPES
+//
+// The Flag and FlagLong functions support most standard Go types. For the
+// list, see the description of FlagLong below for a list of supported types.
+//
+// There are also helper routines to allow single line flag declarations. These
+// types are: Bool, Counter, Duration, Enum, Int16, Int32, Int64, Int, List,
+// Signed, String, Uint16, Uint32, Uint64, Uint, and Unsigned.
+//
+// Each comes in a short and long flavor, e.g., Bool and BoolLong and include
+// functions to set the flags on the standard command line or for a specific Set
+// of flags.
+//
+// Except for the Counter, Enum, Signed and Unsigned types, all of these types
+// can be declared using Flag and FlagLong by passing in a pointer to the
+// appropriate type.
+//
+// DECLARING NEW FLAG TYPES
+//
+// A pointer to any type that implements the Value interface may be passed to
+// Flag or FlagLong.
+//
+// VALUEHELP
+//
+// All non-flag options are created with a "valuehelp" as the last parameter.
+// Valuehelp should be 0, 1, or 2 strings. The first string, if provided, is
+// the usage message for the option. If the second string, if provided, is the
+// name to use for the value when displaying the usage. If not provided the
+// term "value" is assumed.
+//
+// The usage message for the option created with
+//
+// StringLong("option", 'o', "defval", "a string of letters")
+//
+// is
+//
+// -o, -option=value
+//
+// StringLong("option", 'o', "defval", "a string of letters", "string")
+//
+// is
+//
+// -o, -option=string
+package getopt
+
+import (
+ "fmt"
+ "io"
+ "os"
+ "path"
+ "sort"
+ "strings"
+)
+
+// stderr allows tests to capture output to standard error.
+var stderr io.Writer = os.Stderr
+
+// exit allows tests to capture an os.Exit call
+var exit = os.Exit
+
+// DisplayWidth is used to determine where to split usage long lines.
+var DisplayWidth = 80
+
+// HelpColumn is the maximum column position that help strings start to display
+// at. If the option usage is too long then the help string will be displayed
+// on the next line. For example:
+//
+// -a this is the a flag
+// -u, --under=location
+// the u flag's usage is quite long
+var HelpColumn = 20
+
+// PrintUsage prints the usage of the program to w.
+func (s *Set) PrintUsage(w io.Writer) {
+ sort.Sort(s.options)
+ flags := ""
+
+ // Build up the list of short flag names and also compute
+ // how to display the option in the longer help listing.
+ // We also keep track of the longest option usage string
+ // that is no more than HelpColumn-3 bytes (at which point
+ // we use two lines to display the help). The three
+ // is for the leading space and the two spaces before the
+ // help string.
+ for _, opt := range s.options {
+ if opt.name == "" {
+ opt.name = "value"
+ }
+ if opt.uname == "" {
+ opt.uname = opt.usageName()
+ }
+ if opt.flag && opt.short != 0 && opt.short != '-' {
+ flags += string(opt.short)
+ }
+ }
+
+ var opts []string
+
+ // The short option - is special
+ if s.shortOptions['-'] != nil {
+ opts = append(opts, "-")
+ }
+
+ // If we have a bundle of flags, add them to the list
+ if flags != "" {
+ opts = append(opts, "-"+flags)
+ }
+
+ // Now append all the long options and options that require
+ // values.
+ for _, opt := range s.options {
+ if opt.flag {
+ if opt.short != 0 {
+ continue
+ }
+ flags = "--" + opt.long
+ } else if opt.short != 0 {
+ flags = "-" + string(opt.short) + " " + opt.name
+ } else {
+ flags = "--" + string(opt.long) + " " + opt.name
+ }
+ opts = append(opts, flags)
+ }
+ flags = strings.Join(opts, "] [")
+ if flags != "" {
+ flags = " [" + flags + "]"
+ }
+ if s.parameters != "" {
+ flags += " " + s.parameters
+ }
+ fmt.Fprintf(w, "Usage: %s%s\n", s.program, flags)
+ s.PrintOptions(w)
+}
+
+// PrintOptions prints the list of options in s to w.
+func (s *Set) PrintOptions(w io.Writer) {
+ sort.Sort(s.options)
+ max := 4
+ for _, opt := range s.options {
+ if opt.name == "" {
+ opt.name = "value"
+ }
+ if opt.uname == "" {
+ opt.uname = opt.usageName()
+ }
+ if max < len(opt.uname) && len(opt.uname) <= HelpColumn-3 {
+ max = len(opt.uname)
+ }
+ }
+ // Now print one or more usage lines per option.
+ for _, opt := range s.options {
+ if opt.uname != "" {
+ opt.help = strings.TrimSpace(opt.help)
+ if len(opt.help) == 0 {
+ fmt.Fprintf(w, " %s\n", opt.uname)
+ continue
+ }
+ help := strings.Split(opt.help, "\n")
+ // If they did not put in newlines then we will insert
+ // them to keep the help messages from wrapping.
+ if len(help) == 1 {
+ help = breakup(help[0], DisplayWidth-HelpColumn)
+ }
+ if len(opt.uname) <= max {
+ fmt.Fprintf(w, " %-*s %s\n", max, opt.uname, help[0])
+ help = help[1:]
+ } else {
+ fmt.Fprintf(w, " %s\n", opt.uname)
+ }
+ for _, s := range help {
+ fmt.Fprintf(w, " %-*s %s\n", max, " ", s)
+ }
+ }
+ }
+}
+
+// breakup breaks s up into strings no longer than max bytes.
+func breakup(s string, max int) []string {
+ var a []string
+
+ for {
+ // strip leading spaces
+ for len(s) > 0 && s[0] == ' ' {
+ s = s[1:]
+ }
+ // If the option is no longer than the max just return it
+ if len(s) <= max {
+ if len(s) != 0 {
+ a = append(a, s)
+ }
+ return a
+ }
+ x := max
+ for s[x] != ' ' {
+ // the first word is too long?!
+ if x == 0 {
+ x = max
+ for x < len(s) && s[x] != ' ' {
+ x++
+ }
+ if x == len(s) {
+ x--
+ }
+ break
+ }
+ x--
+ }
+ for s[x] == ' ' {
+ x--
+ }
+ a = append(a, s[:x+1])
+ s = s[x+1:]
+ }
+ panic("unreachable")
+}
+
+// Parse uses Getopt to parse args using the options set for s. The first
+// element of args is used to assign the program for s if it is not yet set. On
+// error, Parse displays the error message as well as a usage message on
+// standard error and then exits the program.
+func (s *Set) Parse(args []string) {
+ if err := s.Getopt(args, nil); err != nil {
+ fmt.Fprintln(stderr, err)
+ s.usage()
+ exit(1)
+ }
+}
+
+// Parse uses Getopt to parse args using the options set for s. The first
+// element of args is used to assign the program for s if it is not yet set.
+// Getop calls fn, if not nil, for each option parsed.
+//
+// Getopt returns nil when all options have been processed (a non-option
+// argument was encountered, "--" was encountered, or fn returned false).
+//
+// On error getopt returns a reference to an InvalidOption (which implements the
+// error interface).
+func (s *Set) Getopt(args []string, fn func(Option) bool) (err error) {
+ s.setState(InProgress)
+ defer func() {
+ if s.State() == InProgress {
+ switch {
+ case err != nil:
+ s.setState(Failure)
+ case len(s.args) == 0:
+ s.setState(EndOfArguments)
+ default:
+ s.setState(Unknown)
+ }
+ }
+ }()
+ if fn == nil {
+ fn = func(Option) bool { return true }
+ }
+ if len(args) == 0 {
+ return nil
+ }
+
+ if s.program == "" {
+ s.program = path.Base(args[0])
+ }
+ args = args[1:]
+Parsing:
+ for len(args) > 0 {
+ arg := args[0]
+ s.args = args
+ args = args[1:]
+
+ // end of options?
+ if arg == "" || arg[0] != '-' {
+ s.setState(EndOfOptions)
+ return nil
+ }
+
+ if arg == "-" {
+ goto ShortParsing
+ }
+
+ // explicitly request end of options?
+ if arg == "--" {
+ s.args = args
+ s.setState(DashDash)
+ return nil
+ }
+
+ // Long option processing
+ if len(s.longOptions) > 0 && arg[1] == '-' {
+ e := strings.IndexRune(arg, '=')
+ var value string
+ if e > 0 {
+ value = arg[e+1:]
+ arg = arg[:e]
+ }
+ opt := s.longOptions[arg[2:]]
+ // If we are processing long options then --f is -f
+ // if f is not defined as a long option.
+ // This lets you say --f=false
+ if opt == nil && len(arg[2:]) == 1 {
+ opt = s.shortOptions[rune(arg[2])]
+ }
+ if opt == nil {
+ return unknownOption(arg[2:])
+ }
+ opt.isLong = true
+ // If we require an option and did not have an =
+ // then use the next argument as an option.
+ if !opt.flag && e < 0 && !opt.optional {
+ if len(args) == 0 {
+ return missingArg(opt)
+ }
+ value = args[0]
+ args = args[1:]
+ }
+ opt.count++
+
+ if err := opt.value.Set(value, opt); err != nil {
+ return setError(opt, value, err)
+ }
+
+ if !fn(opt) {
+ s.setState(Terminated)
+ return nil
+ }
+ continue Parsing
+ }
+
+ // Short option processing
+ arg = arg[1:] // strip -
+ ShortParsing:
+ for i, c := range arg {
+ opt := s.shortOptions[c]
+ if opt == nil {
+ // In traditional getopt, if - is not registered
+ // as an option, a lone - is treated as
+ // if there were a -- in front of it.
+ if arg == "-" {
+ s.setState(Dash)
+ return nil
+ }
+ return unknownOption(c)
+ }
+ opt.isLong = false
+ opt.count++
+ var value string
+ if !opt.flag {
+ value = arg[1+i:]
+ if value == "" && !opt.optional {
+ if len(args) == 0 {
+ return missingArg(opt)
+ }
+ value = args[0]
+ args = args[1:]
+ }
+ }
+ if err := opt.value.Set(value, opt); err != nil {
+ return setError(opt, value, err)
+ }
+ if !fn(opt) {
+ s.setState(Terminated)
+ return nil
+ }
+ if !opt.flag {
+ continue Parsing
+ }
+ }
+ }
+ s.args = []string{}
+ return nil
+}
diff --git a/vendor/github.com/pborman/getopt/v2/int.go b/vendor/github.com/pborman/getopt/v2/int.go
new file mode 100644
index 0000000..b4c27bf
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/v2/int.go
@@ -0,0 +1,160 @@
+// Copyright 2017 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package getopt
+
+// Int creates an option that parses its value as an integer.
+func Int(name rune, value int, helpvalue ...string) *int {
+ return CommandLine.Int(name, value, helpvalue...)
+}
+
+func (s *Set) Int(name rune, value int, helpvalue ...string) *int {
+ s.Flag(&value, name, helpvalue...)
+ return &value
+}
+
+func IntLong(name string, short rune, value int, helpvalue ...string) *int {
+ return CommandLine.IntLong(name, short, value, helpvalue...)
+}
+
+func (s *Set) IntLong(name string, short rune, value int, helpvalue ...string) *int {
+ s.FlagLong(&value, name, short, helpvalue...)
+ return &value
+}
+
+// Int16 creates an option that parses its value as a 16 bit integer.
+func Int16(name rune, value int16, helpvalue ...string) *int16 {
+ return CommandLine.Int16(name, value, helpvalue...)
+}
+
+func (s *Set) Int16(name rune, value int16, helpvalue ...string) *int16 {
+ s.Flag(&value, name, helpvalue...)
+ return &value
+}
+
+func Int16Long(name string, short rune, value int16, helpvalue ...string) *int16 {
+ return CommandLine.Int16Long(name, short, value, helpvalue...)
+}
+
+func (s *Set) Int16Long(name string, short rune, value int16, helpvalue ...string) *int16 {
+ s.FlagLong(&value, name, short, helpvalue...)
+ return &value
+}
+
+// Int32 creates an option that parses its value as a 32 bit integer.
+func Int32(name rune, value int32, helpvalue ...string) *int32 {
+ return CommandLine.Int32(name, value, helpvalue...)
+}
+
+func (s *Set) Int32(name rune, value int32, helpvalue ...string) *int32 {
+ s.Flag(&value, name, helpvalue...)
+ return &value
+}
+
+func Int32Long(name string, short rune, value int32, helpvalue ...string) *int32 {
+ return CommandLine.Int32Long(name, short, value, helpvalue...)
+}
+
+func (s *Set) Int32Long(name string, short rune, value int32, helpvalue ...string) *int32 {
+ s.FlagLong(&value, name, short, helpvalue...)
+ return &value
+}
+
+// Int64 creates an option that parses its value as a 64 bit integer.
+func Int64(name rune, value int64, helpvalue ...string) *int64 {
+ return CommandLine.Int64(name, value, helpvalue...)
+}
+
+func (s *Set) Int64(name rune, value int64, helpvalue ...string) *int64 {
+ s.Flag(&value, name, helpvalue...)
+ return &value
+}
+
+func Int64Long(name string, short rune, value int64, helpvalue ...string) *int64 {
+ return CommandLine.Int64Long(name, short, value, helpvalue...)
+}
+
+func (s *Set) Int64Long(name string, short rune, value int64, helpvalue ...string) *int64 {
+ s.FlagLong(&value, name, short, helpvalue...)
+ return &value
+}
+
+// Uint creates an option that parses its value as an unsigned integer.
+func Uint(name rune, value uint, helpvalue ...string) *uint {
+ return CommandLine.Uint(name, value, helpvalue...)
+}
+
+func (s *Set) Uint(name rune, value uint, helpvalue ...string) *uint {
+ s.Flag(&value, name, helpvalue...)
+ return &value
+}
+
+func UintLong(name string, short rune, value uint, helpvalue ...string) *uint {
+ return CommandLine.UintLong(name, short, value, helpvalue...)
+}
+
+func (s *Set) UintLong(name string, short rune, value uint, helpvalue ...string) *uint {
+ s.FlagLong(&value, name, short, helpvalue...)
+ return &value
+}
+
+// Uint16 creates an option that parses its value as a 16 bit unsigned integer.
+func Uint16(name rune, value uint16, helpvalue ...string) *uint16 {
+ return CommandLine.Uint16(name, value, helpvalue...)
+ return &value
+}
+
+func (s *Set) Uint16(name rune, value uint16, helpvalue ...string) *uint16 {
+ s.Flag(&value, name, helpvalue...)
+ return &value
+}
+
+func Uint16Long(name string, short rune, value uint16, helpvalue ...string) *uint16 {
+ return CommandLine.Uint16Long(name, short, value, helpvalue...)
+}
+
+func (s *Set) Uint16Long(name string, short rune, value uint16, helpvalue ...string) *uint16 {
+ s.FlagLong(&value, name, short, helpvalue...)
+ return &value
+}
+
+// Uint32 creates an option that parses its value as a 32 bit unsigned integer.
+func Uint32(name rune, value uint32, helpvalue ...string) *uint32 {
+ return CommandLine.Uint32(name, value, helpvalue...)
+ return &value
+}
+
+func (s *Set) Uint32(name rune, value uint32, helpvalue ...string) *uint32 {
+ s.Flag(&value, name, helpvalue...)
+ return &value
+}
+
+func Uint32Long(name string, short rune, value uint32, helpvalue ...string) *uint32 {
+ return CommandLine.Uint32Long(name, short, value, helpvalue...)
+}
+
+func (s *Set) Uint32Long(name string, short rune, value uint32, helpvalue ...string) *uint32 {
+ s.FlagLong(&value, name, short, helpvalue...)
+ return &value
+}
+
+// Uint64 creates an option that parses its value as a 64 bit unsigned integer.
+func Uint64(name rune, value uint64, helpvalue ...string) *uint64 {
+ return CommandLine.Uint64(name, value, helpvalue...)
+ return &value
+}
+
+func (s *Set) Uint64(name rune, value uint64, helpvalue ...string) *uint64 {
+ s.Flag(&value, name, helpvalue...)
+ return &value
+}
+
+func Uint64Long(name string, short rune, value uint64, helpvalue ...string) *uint64 {
+ return CommandLine.Uint64Long(name, short, value, helpvalue...)
+}
+
+func (s *Set) Uint64Long(name string, short rune, value uint64, helpvalue ...string) *uint64 {
+ s.FlagLong(&value, name, short, helpvalue...)
+ return &value
+}
diff --git a/vendor/github.com/pborman/getopt/v2/int_test.go b/vendor/github.com/pborman/getopt/v2/int_test.go
new file mode 100644
index 0000000..57175fd
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/v2/int_test.go
@@ -0,0 +1,595 @@
+// Copyright 2017 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package getopt
+
+import (
+ "fmt"
+ "strings"
+ "testing"
+)
+
+var intTests = []struct {
+ where string
+ in []string
+ i int
+ int int
+ err string
+}{
+ {
+ loc(),
+ []string{},
+ 17, 42,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i", "1", "--int", "2"},
+ 1, 2,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i1", "--int=2"},
+ 1, 2,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i1", "-i2"},
+ 2, 42,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i=1"},
+ 17, 42,
+ "test: not a valid number: =1\n",
+ },
+ {
+ loc(),
+ []string{"test", "-i0x20"},
+ 0x20, 42,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i010"},
+ 8, 42,
+ "",
+ },
+}
+
+func TestInt(t *testing.T) {
+ for x, tt := range intTests {
+ reset()
+ i := Int('i', 17)
+ opt := IntLong("int", 0, 42)
+ if strings.Index(tt.where, ":-") > 0 {
+ tt.where = fmt.Sprintf("#%d", x)
+ }
+
+ parse(tt.in)
+ if s := checkError(tt.err); s != "" {
+ t.Errorf("%s: %s", tt.where, s)
+ }
+ if got, want := *i, tt.i; got != want {
+ t.Errorf("%s: got %v, want %v", tt.where, got, want)
+ }
+ if got, want := *opt, tt.int; got != want {
+ t.Errorf("%s: got %v, want %v", tt.where, got, want)
+ }
+ }
+}
+
+var int16Tests = []struct {
+ where string
+ in []string
+ i int16
+ int16 int16
+ err string
+}{
+ {
+ loc(),
+ []string{},
+ 17, 42,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i", "1", "--int16", "2"},
+ 1, 2,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i1", "--int16=2"},
+ 1, 2,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i1", "-i2"},
+ 2, 42,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i=1"},
+ 17, 42,
+ "test: not a valid number: =1\n",
+ },
+ {
+ loc(),
+ []string{"test", "-i0x20"},
+ 0x20, 42,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i010"},
+ 8, 42,
+ "",
+ },
+}
+
+func TestInt16(t *testing.T) {
+ for x, tt := range int16Tests {
+ reset()
+ i := Int16('i', 17)
+ opt := Int16Long("int16", 0, 42)
+ if strings.Index(tt.where, ":-") > 0 {
+ tt.where = fmt.Sprintf("#%d", x)
+ }
+
+ parse(tt.in)
+ if s := checkError(tt.err); s != "" {
+ t.Errorf("%s: %s", tt.where, s)
+ }
+ if got, want := *i, tt.i; got != want {
+ t.Errorf("%s: got %v, want %v", tt.where, got, want)
+ }
+ if got, want := *opt, tt.int16; got != want {
+ t.Errorf("%s: got %v, want %v", tt.where, got, want)
+ }
+ }
+}
+
+var int32Tests = []struct {
+ where string
+ in []string
+ i int32
+ int32 int32
+ err string
+}{
+ {
+ loc(),
+ []string{},
+ 17, 42,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i", "1", "--int32", "2"},
+ 1, 2,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i1", "--int32=2"},
+ 1, 2,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i1", "-i2"},
+ 2, 42,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i=1"},
+ 17, 42,
+ "test: not a valid number: =1\n",
+ },
+ {
+ loc(),
+ []string{"test", "-i0x20"},
+ 0x20, 42,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i010"},
+ 8, 42,
+ "",
+ },
+}
+
+func TestInt32(t *testing.T) {
+ for x, tt := range int32Tests {
+ reset()
+ i := Int32('i', 17)
+ opt := Int32Long("int32", 0, 42)
+ if strings.Index(tt.where, ":-") > 0 {
+ tt.where = fmt.Sprintf("#%d", x)
+ }
+
+ parse(tt.in)
+ if s := checkError(tt.err); s != "" {
+ t.Errorf("%s: %s", tt.where, s)
+ }
+ if got, want := *i, tt.i; got != want {
+ t.Errorf("%s: got %v, want %v", tt.where, got, want)
+ }
+ if got, want := *opt, tt.int32; got != want {
+ t.Errorf("%s: got %v, want %v", tt.where, got, want)
+ }
+ }
+}
+
+var int64Tests = []struct {
+ where string
+ in []string
+ i int64
+ int64 int64
+ err string
+}{
+ {
+ loc(),
+ []string{},
+ 17, 42,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i", "1", "--int64", "2"},
+ 1, 2,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i1", "--int64=2"},
+ 1, 2,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i1", "-i2"},
+ 2, 42,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i=1"},
+ 17, 42,
+ "test: not a valid number: =1\n",
+ },
+ {
+ loc(),
+ []string{"test", "-i0x20"},
+ 0x20, 42,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i010"},
+ 8, 42,
+ "",
+ },
+}
+
+func TestInt64(t *testing.T) {
+ for x, tt := range int64Tests {
+ reset()
+ i := Int64('i', 17)
+ opt := Int64Long("int64", 0, 42)
+ if strings.Index(tt.where, ":-") > 0 {
+ tt.where = fmt.Sprintf("#%d", x)
+ }
+
+ parse(tt.in)
+ if s := checkError(tt.err); s != "" {
+ t.Errorf("%s: %s", tt.where, s)
+ }
+ if got, want := *i, tt.i; got != want {
+ t.Errorf("%s: got %v, want %v", tt.where, got, want)
+ }
+ if got, want := *opt, tt.int64; got != want {
+ t.Errorf("%s: got %v, want %v", tt.where, got, want)
+ }
+ }
+}
+
+var uintTests = []struct {
+ where string
+ in []string
+ i uint
+ uint uint
+ err string
+}{
+ {
+ loc(),
+ []string{},
+ 17, 42,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i", "1", "--uint", "2"},
+ 1, 2,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i1", "--uint=2"},
+ 1, 2,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i1", "-i2"},
+ 2, 42,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i=1"},
+ 17, 42,
+ "test: not a valid number: =1\n",
+ },
+ {
+ loc(),
+ []string{"test", "-i0x20"},
+ 0x20, 42,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i010"},
+ 8, 42,
+ "",
+ },
+}
+
+func TestUint(t *testing.T) {
+ for x, tt := range uintTests {
+ reset()
+ i := Uint('i', 17)
+ opt := UintLong("uint", 0, 42)
+ if strings.Index(tt.where, ":-") > 0 {
+ tt.where = fmt.Sprintf("#%d", x)
+ }
+
+ parse(tt.in)
+ if s := checkError(tt.err); s != "" {
+ t.Errorf("%s: %s", tt.where, s)
+ }
+ if got, want := *i, tt.i; got != want {
+ t.Errorf("%s: got %v, want %v", tt.where, got, want)
+ }
+ if got, want := *opt, tt.uint; got != want {
+ t.Errorf("%s: got %v, want %v", tt.where, got, want)
+ }
+ }
+}
+
+var uint16Tests = []struct {
+ where string
+ in []string
+ i uint16
+ uint16 uint16
+ err string
+}{
+ {
+ loc(),
+ []string{},
+ 17, 42,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i", "1", "--uint16", "2"},
+ 1, 2,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i1", "--uint16=2"},
+ 1, 2,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i1", "-i2"},
+ 2, 42,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i=1"},
+ 17, 42,
+ "test: not a valid number: =1\n",
+ },
+ {
+ loc(),
+ []string{"test", "-i0x20"},
+ 0x20, 42,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i010"},
+ 8, 42,
+ "",
+ },
+}
+
+func TestUint16(t *testing.T) {
+ for x, tt := range uint16Tests {
+ reset()
+ i := Uint16('i', 17)
+ opt := Uint16Long("uint16", 0, 42)
+ if strings.Index(tt.where, ":-") > 0 {
+ tt.where = fmt.Sprintf("#%d", x)
+ }
+
+ parse(tt.in)
+ if s := checkError(tt.err); s != "" {
+ t.Errorf("%s: %s", tt.where, s)
+ }
+ if got, want := *i, tt.i; got != want {
+ t.Errorf("%s: got %v, want %v", tt.where, got, want)
+ }
+ if got, want := *opt, tt.uint16; got != want {
+ t.Errorf("%s: got %v, want %v", tt.where, got, want)
+ }
+ }
+}
+
+var uint32Tests = []struct {
+ where string
+ in []string
+ i uint32
+ uint32 uint32
+ err string
+}{
+ {
+ loc(),
+ []string{},
+ 17, 42,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i", "1", "--uint32", "2"},
+ 1, 2,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i1", "--uint32=2"},
+ 1, 2,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i1", "-i2"},
+ 2, 42,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i=1"},
+ 17, 42,
+ "test: not a valid number: =1\n",
+ },
+ {
+ loc(),
+ []string{"test", "-i0x20"},
+ 0x20, 42,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i010"},
+ 8, 42,
+ "",
+ },
+}
+
+func TestUint32(t *testing.T) {
+ for x, tt := range uint32Tests {
+ reset()
+ i := Uint32('i', 17)
+ opt := Uint32Long("uint32", 0, 42)
+ if strings.Index(tt.where, ":-") > 0 {
+ tt.where = fmt.Sprintf("#%d", x)
+ }
+
+ parse(tt.in)
+ if s := checkError(tt.err); s != "" {
+ t.Errorf("%s: %s", tt.where, s)
+ }
+ if got, want := *i, tt.i; got != want {
+ t.Errorf("%s: got %v, want %v", tt.where, got, want)
+ }
+ if got, want := *opt, tt.uint32; got != want {
+ t.Errorf("%s: got %v, want %v", tt.where, got, want)
+ }
+ }
+}
+
+var uint64Tests = []struct {
+ where string
+ in []string
+ i uint64
+ uint64 uint64
+ err string
+}{
+ {
+ loc(),
+ []string{},
+ 17, 42,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i", "1", "--uint64", "2"},
+ 1, 2,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i1", "--uint64=2"},
+ 1, 2,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i1", "-i2"},
+ 2, 42,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i=1"},
+ 17, 42,
+ "test: not a valid number: =1\n",
+ },
+ {
+ loc(),
+ []string{"test", "-i0x20"},
+ 0x20, 42,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-i010"},
+ 8, 42,
+ "",
+ },
+}
+
+func TestUint64(t *testing.T) {
+ for x, tt := range uint64Tests {
+ reset()
+ i := Uint64('i', 17)
+ opt := Uint64Long("uint64", 0, 42)
+ if strings.Index(tt.where, ":-") > 0 {
+ tt.where = fmt.Sprintf("#%d", x)
+ }
+
+ parse(tt.in)
+ if s := checkError(tt.err); s != "" {
+ t.Errorf("%s: %s", tt.where, s)
+ }
+ if got, want := *i, tt.i; got != want {
+ t.Errorf("%s: got %v, want %v", tt.where, got, want)
+ }
+ if got, want := *opt, tt.uint64; got != want {
+ t.Errorf("%s: got %v, want %v", tt.where, got, want)
+ }
+ }
+}
diff --git a/vendor/github.com/pborman/getopt/v2/list.go b/vendor/github.com/pborman/getopt/v2/list.go
new file mode 100644
index 0000000..99a09ef
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/v2/list.go
@@ -0,0 +1,32 @@
+// Copyright 2017 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package getopt
+
+// List creates an option that returns a slice of strings. The parameters
+// passed are converted from a comma separated value list into a slice.
+// Subsequent occurrences append to the list.
+func List(name rune, helpvalue ...string) *[]string {
+ p := []string{}
+ CommandLine.Flag(&p, name, helpvalue...)
+ return &p
+}
+
+func (s *Set) List(name rune, helpvalue ...string) *[]string {
+ p := []string{}
+ s.Flag(&p, name, helpvalue...)
+ return &p
+}
+
+func ListLong(name string, short rune, helpvalue ...string) *[]string {
+ p := []string{}
+ CommandLine.FlagLong(&p, name, short, helpvalue...)
+ return &p
+}
+
+func (s *Set) ListLong(name string, short rune, helpvalue ...string) *[]string {
+ p := []string{}
+ s.FlagLong(&p, name, short, helpvalue...)
+ return &p
+}
diff --git a/vendor/github.com/pborman/getopt/v2/list_test.go b/vendor/github.com/pborman/getopt/v2/list_test.go
new file mode 100644
index 0000000..e8c8d18
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/v2/list_test.go
@@ -0,0 +1,99 @@
+// Copyright 2017 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package getopt
+
+import "testing"
+
+var listTests = []struct {
+ where string
+ in []string
+ l, list []string
+ err string
+}{
+ {
+ loc(),
+ []string{},
+ nil, nil,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-l", "one"},
+ []string{"one"}, nil,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-lone", "-ltwo"},
+ []string{"one", "two"}, nil,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "--list", "one"},
+ nil, []string{"one"},
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "--list=one", "--list=two"},
+ nil, []string{"one", "two"},
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "--list=one,two"},
+ nil, []string{"one", "two"},
+ "",
+ },
+}
+
+func TestList(t *testing.T) {
+ for _, tt := range listTests {
+ reset()
+ l := List('l')
+ list := ListLong("list", 0)
+
+ parse(tt.in)
+ if s := checkError(tt.err); s != "" {
+ t.Errorf("%s: %s", tt.where, s)
+ }
+ if badSlice(*l, tt.l) {
+ t.Errorf("%s: got s = %q, want %q", tt.where, *l, tt.l)
+ }
+ if badSlice(*list, tt.list) {
+ t.Errorf("%s: got s = %q, want %q", tt.where, *list, tt.list)
+ }
+ }
+}
+
+func TestDefaultList(t *testing.T) {
+ reset()
+ list := []string{"d1", "d2", "d3"}
+ Flag(&list, 'l')
+ parse([]string{"test"})
+
+ want := []string{"d1", "d2", "d3"}
+ if badSlice(list, want) {
+ t.Errorf("got s = %q, want %q", list, want)
+ }
+
+ parse([]string{"test", "-l", "one"})
+ want = []string{"one"}
+ if badSlice(list, want) {
+ t.Errorf("got s = %q, want %q", list, want)
+ }
+
+ parse([]string{"test", "-l", "two"})
+ want = []string{"one", "two"}
+ if badSlice(list, want) {
+ t.Errorf("got s = %q, want %q", list, want)
+ }
+ Lookup('l').Reset()
+ want = []string{"d1", "d2", "d3"}
+ if badSlice(list, want) {
+ t.Errorf("got s = %q, want %q", list, want)
+ }
+}
diff --git a/vendor/github.com/pborman/getopt/v2/option.go b/vendor/github.com/pborman/getopt/v2/option.go
new file mode 100644
index 0000000..6d5fc47
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/v2/option.go
@@ -0,0 +1,193 @@
+// Copyright 2017 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package getopt
+
+import (
+ "fmt"
+ "strings"
+)
+
+// An Option can be either a Flag or a Value
+type Option interface {
+ // Name returns the name of the option. If the option has been seen
+ // then the last way it was referenced (short or long) is returned
+ // otherwise if there is a short name then this will be the short name
+ // as a string, else it will be the long name.
+ Name() string
+
+ // IsFlag returns true if Option is a flag.
+ IsFlag() bool
+
+ // Seen returns true if the flag was seen.
+ Seen() bool
+
+ // Count returns the number of times the flag was seen.
+ Count() int
+
+ // String returns the last value the option was set to.
+ String() string
+
+ // Value returns the Value of the option.
+ Value() Value
+
+ // SetOptional makes the value optional. The option and value are
+ // always a single argument. Either --option or --option=value. In
+ // the former case the value of the option does not change but the Set()
+ // will return true and the value returned by Count() is incremented.
+ // The short form is either -o or -ovalue. SetOptional returns
+ // the Option
+ SetOptional() Option
+
+ // SetFlag makes the value a flag. Flags are boolean values and
+ // normally do not taken a value. They are set to true when seen.
+ // If a value is passed in the long form then it must be on, case
+ // insensitivinsensitive, one of "true", "false", "t", "f", "on", "off", "1", "0".
+ // SetFlag returns the Option
+ SetFlag() Option
+
+ // Reset resets the state of the option so it appears it has not
+ // yet been seen, including resetting the value of the option
+ // to its original default state.
+ Reset()
+}
+
+type option struct {
+ short rune // 0 means no short name
+ long string // "" means no long name
+ isLong bool // True if they used the long name
+ flag bool // true if a boolean flag
+ defval string // default value
+ optional bool // true if we take an optional value
+ help string // help message
+ where string // file where the option was defined
+ value Value // current value of option
+ count int // number of times we have seen this option
+ name string // name of the value (for usage)
+ uname string // name of the option (for usage)
+}
+
+// usageName returns the name of the option for printing usage lines in one
+// of the following forms:
+//
+// -f
+// --flag
+// -f, --flag
+// -s value
+// --set=value
+// -s, --set=value
+func (o *option) usageName() string {
+ // Don't print help messages if we have none and there is only one
+ // way to specify the option.
+ if o.help == "" && (o.short == 0 || o.long == "") {
+ return ""
+ }
+ n := ""
+
+ switch {
+ case o.short != 0 && o.long == "":
+ n = "-" + string(o.short)
+ case o.short == 0 && o.long != "":
+ n = " --" + o.long
+ case o.short != 0 && o.long != "":
+ n = "-" + string(o.short) + ", --" + o.long
+ }
+
+ switch {
+ case o.flag:
+ return n
+ case o.optional:
+ return n + "[=" + o.name + "]"
+ case o.long != "":
+ return n + "=" + o.name
+ }
+ return n + " " + o.name
+}
+
+// sortName returns the name to sort the option on.
+func (o *option) sortName() string {
+ if o.short != 0 {
+ return string(o.short) + o.long
+ }
+ return o.long[:1] + o.long
+}
+
+func (o *option) Seen() bool { return o.count > 0 }
+func (o *option) Count() int { return o.count }
+func (o *option) IsFlag() bool { return o.flag }
+func (o *option) String() string { return o.value.String() }
+func (o *option) SetOptional() Option { o.optional = true; return o }
+func (o *option) SetFlag() Option { o.flag = true; return o }
+
+func (o *option) Value() Value {
+ if o == nil {
+ return nil
+ }
+ return o.value
+}
+
+func (o *option) Name() string {
+ if !o.isLong && o.short != 0 {
+ return "-" + string(o.short)
+ }
+ return "--" + o.long
+}
+
+// Reset rests an option so that it appears it has not yet been seen.
+func (o *option) Reset() {
+ o.isLong = false
+ o.count = 0
+ o.value.Set(o.defval, o)
+}
+
+type optionList []*option
+
+func (ol optionList) Len() int { return len(ol) }
+func (ol optionList) Swap(i, j int) { ol[i], ol[j] = ol[j], ol[i] }
+func (ol optionList) Less(i, j int) bool {
+ // first check the short names (or the first letter of the long name)
+ // If they are not equal (case insensitive) then we have our answer
+ n1 := ol[i].sortName()
+ n2 := ol[j].sortName()
+ l1 := strings.ToLower(n1)
+ l2 := strings.ToLower(n2)
+ if l1 < l2 {
+ return true
+ }
+ if l2 < l1 {
+ return false
+ }
+ return n1 < n2
+}
+
+// AddOption add the option o to set CommandLine if o is not already in set
+// CommandLine.
+func AddOption(o Option) {
+ CommandLine.AddOption(o)
+}
+
+// AddOption add the option o to set s if o is not already in set s.
+func (s *Set) AddOption(o Option) {
+ opt := o.(*option)
+ for _, eopt := range s.options {
+ if opt == eopt {
+ return
+ }
+ }
+ if opt.short != 0 {
+ if oo, ok := s.shortOptions[opt.short]; ok {
+ fmt.Fprintf(stderr, "%s: -%c already declared at %s\n", opt.where, opt.short, oo.where)
+ exit(1)
+ }
+ s.shortOptions[opt.short] = opt
+ }
+ if opt.long != "" {
+ if oo, ok := s.longOptions[opt.long]; ok {
+ fmt.Fprintf(stderr, "%s: --%s already declared at %s\n", opt.where, opt.long, oo.where)
+ exit(1)
+ }
+ s.longOptions[opt.long] = opt
+ }
+ s.options = append(s.options, opt)
+}
diff --git a/vendor/github.com/pborman/getopt/v2/set.go b/vendor/github.com/pborman/getopt/v2/set.go
new file mode 100644
index 0000000..ce546ed
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/v2/set.go
@@ -0,0 +1,284 @@
+// Copyright 2017 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package getopt
+
+import (
+ "io"
+ "os"
+ "sort"
+ "sync"
+)
+
+// A State is why the Getopt returned.
+type State int
+
+const (
+ InProgress = State(iota) // Getopt is still running
+ Dash // Returned on "-"
+ DashDash // Returned on "--"
+ EndOfOptions // End of options reached
+ EndOfArguments // No more arguments
+ Terminated // Terminated by callback function
+ Failure // Terminated due to error
+ Unknown // Indicates internal error
+)
+
+type Set struct {
+ stateMu sync.Mutex
+ state State
+
+ // args are the parameters remaining after parsing the optoins.
+ args []string
+
+ // program is the name of the program for usage and error messages.
+ // If not set it will automatically be set to the base name of the
+ // first argument passed to parse.
+ program string
+
+ // parameters is what is displayed on the usage line after displaying
+ // the various options.
+ parameters string
+
+ usage func() // usage should print the programs usage and exit.
+
+ shortOptions map[rune]*option
+ longOptions map[string]*option
+ options optionList
+}
+
+// New returns a newly created option set.
+func New() *Set {
+ s := &Set{
+ shortOptions: make(map[rune]*option),
+ longOptions: make(map[string]*option),
+ parameters: "[parameters ...]",
+ }
+
+ s.usage = func() {
+ s.PrintUsage(stderr)
+ }
+ return s
+}
+
+func (s *Set) setState(state State) {
+ s.stateMu.Lock()
+ s.state = state
+ s.stateMu.Unlock()
+}
+
+// State returns the current state of the Set s. The state is normally the
+// reason the most recent call to Getopt returned.
+func (s *Set) State() State {
+ s.stateMu.Lock()
+ defer s.stateMu.Unlock()
+ return s.state
+}
+
+// The default set of command-line options.
+var CommandLine = New()
+
+// PrintUsage calls PrintUsage in the default option set.
+func PrintUsage(w io.Writer) { CommandLine.PrintUsage(w) }
+
+// Usage calls the usage function in the default option set.
+func Usage() { CommandLine.usage() }
+
+// Parse calls Parse in the default option set with the command line arguments
+// found in os.Args.
+func Parse() { CommandLine.Parse(os.Args) }
+
+// Getops returns the result of calling Getop in the default option set with the
+// command line arguments found in os.Args. The fn function, which may be nil,
+// is passed to Getopt.
+func Getopt(fn func(Option) bool) error { return CommandLine.Getopt(os.Args, fn) }
+
+// Arg returns the n'th command-line argument. Arg(0) is the first remaining
+// argument after options have been processed.
+func Arg(n int) string {
+ if n >= 0 && n < len(CommandLine.args) {
+ return CommandLine.args[n]
+ }
+ return ""
+}
+
+// Arg returns the n'th argument. Arg(0) is the first remaining
+// argument after options have been processed.
+func (s *Set) Arg(n int) string {
+ if n >= 0 && n < len(s.args) {
+ return s.args[n]
+ }
+ return ""
+}
+
+// Args returns the non-option command line arguments.
+func Args() []string {
+ return CommandLine.args
+}
+
+// Args returns the non-option arguments.
+func (s *Set) Args() []string {
+ return s.args
+}
+
+// NArgs returns the number of non-option command line arguments.
+func NArgs() int {
+ return len(CommandLine.args)
+}
+
+// NArgs returns the number of non-option arguments.
+func (s *Set) NArgs() int {
+ return len(s.args)
+}
+
+// SetParameters sets the parameters string for printing the command line
+// usage. It defaults to "[parameters ...]"
+func SetParameters(parameters string) {
+ CommandLine.parameters = parameters
+}
+
+// SetParameters sets the parameters string for printing the s's usage.
+// It defaults to "[parameters ...]"
+func (s *Set) SetParameters(parameters string) {
+ s.parameters = parameters
+}
+
+// SetProgram sets the program name to program. Normally it is determined
+// from the zeroth command line argument (see os.Args).
+func SetProgram(program string) {
+ CommandLine.program = program
+}
+
+// SetProgram sets s's program name to program. Normally it is determined
+// from the zeroth argument passed to Getopt or Parse.
+func (s *Set) SetProgram(program string) {
+ s.program = program
+}
+
+// SetUsage sets the function used by Parse to display the commands usage
+// on error. It defaults to calling PrintUsage(os.Stderr).
+func SetUsage(usage func()) {
+ CommandLine.usage = usage
+}
+
+// SetUsage sets the function used by Parse to display usage on error. It
+// defaults to calling f.PrintUsage(os.Stderr).
+func (s *Set) SetUsage(usage func()) {
+ s.usage = usage
+}
+
+// Lookup returns the Option associated with name. Name should either be
+// a rune (the short name) or a string (the long name).
+func Lookup(name interface{}) Option {
+ return CommandLine.Lookup(name)
+}
+
+// Lookup returns the Option associated with name in s. Name should either be
+// a rune (the short name) or a string (the long name).
+func (s *Set) Lookup(name interface{}) Option {
+ switch v := name.(type) {
+ case rune:
+ return s.shortOptions[v]
+ case int:
+ return s.shortOptions[rune(v)]
+ case string:
+ return s.longOptions[v]
+ }
+ return nil
+}
+
+// IsSet returns true if the Option associated with name was seen while
+// parsing the command line arguments. Name should either be a rune (the
+// short name) or a string (the long name).
+func IsSet(name interface{}) bool {
+ return CommandLine.IsSet(name)
+}
+
+// IsSet returns true if the Option associated with name was seen while
+// parsing s. Name should either be a rune (the short name) or a string (the
+// long name).
+func (s *Set) IsSet(name interface{}) bool {
+ if opt := s.Lookup(name); opt != nil {
+ return opt.Seen()
+ }
+ return false
+}
+
+// GetCount returns the number of times the Option associated with name has been
+// seen while parsing the command line arguments. Name should either be a rune
+// (the short name) or a string (the long name).
+func GetCount(name interface{}) int {
+ return CommandLine.GetCount(name)
+}
+
+// GetCount returns the number of times the Option associated with name has been
+// seen while parsing s's arguments. Name should either be a rune (the short
+// name) or a string (the long name).
+func (s *Set) GetCount(name interface{}) int {
+ if opt := s.Lookup(name); opt != nil {
+ return opt.Count()
+ }
+ return 0
+}
+
+// GetValue returns the final value set to the command-line Option with name.
+// If the option has not been seen while parsing s then the default value is
+// returned. Name should either be a rune (the short name) or a string (the
+// long name).
+func GetValue(name interface{}) string {
+ return CommandLine.GetValue(name)
+}
+
+// GetValue returns the final value set to the Option in s associated with name.
+// If the option has not been seen while parsing s then the default value is
+// returned. Name should either be a rune (the short name) or a string (the
+// long name).
+func (s *Set) GetValue(name interface{}) string {
+ if opt := s.Lookup(name); opt != nil {
+ return opt.String()
+ }
+ return ""
+}
+
+// Visit visits the command-line options in lexicographical order, calling fn
+// for each. It visits only those options that have been set.
+func Visit(fn func(Option)) { CommandLine.Visit(fn) }
+
+// Visit visits the options in s in lexicographical order, calling fn
+// for each. It visits only those options that have been set.
+func (s *Set) Visit(fn func(Option)) {
+ sort.Sort(s.options)
+ for _, opt := range s.options {
+ if opt.count > 0 {
+ fn(opt)
+ }
+ }
+}
+
+// VisitAll visits the options in s in lexicographical order, calling fn
+// for each. It visits all options, even those not set.
+func VisitAll(fn func(Option)) { CommandLine.VisitAll(fn) }
+
+// VisitAll visits the command-line flags in lexicographical order, calling fn
+// for each. It visits all flags, even those not set.
+func (s *Set) VisitAll(fn func(Option)) {
+ sort.Sort(s.options)
+ for _, opt := range s.options {
+ fn(opt)
+ }
+}
+
+// Reset resets all the command line options to the initial state so it
+// appears none of them have been seen.
+func Reset() {
+ CommandLine.Reset()
+}
+
+// Reset resets all the options in s to the initial state so it
+// appears none of them have been seen.
+func (s *Set) Reset() {
+ for _, opt := range s.options {
+ opt.Reset()
+ }
+}
diff --git a/vendor/github.com/pborman/getopt/v2/signed.go b/vendor/github.com/pborman/getopt/v2/signed.go
new file mode 100644
index 0000000..dc371a7
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/v2/signed.go
@@ -0,0 +1,110 @@
+// Copyright 2017 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package getopt
+
+import (
+ "fmt"
+ "strconv"
+ "sync"
+)
+
+type signed int64
+
+type SignedLimit struct {
+ Base int // Base for conversion as per strconv.ParseInt
+ Bits int // Number of bits as per strconv.ParseInt
+ Min int64 // Minimum allowed value if both Min and Max are not 0
+ Max int64 // Maximum allowed value if both Min and Max are not 0
+}
+
+var (
+ signedLimitsMu sync.Mutex
+ signedLimits = make(map[*signed]*SignedLimit)
+)
+
+func (n *signed) Set(value string, opt Option) error {
+ signedLimitsMu.Lock()
+ l := signedLimits[n]
+ signedLimitsMu.Unlock()
+ if l == nil {
+ return fmt.Errorf("no limits defined for %s", opt.Name())
+ }
+ v, err := strconv.ParseInt(value, l.Base, l.Bits)
+ if err != nil {
+ if e, ok := err.(*strconv.NumError); ok {
+ switch e.Err {
+ case strconv.ErrRange:
+ err = fmt.Errorf("value out of range: %s", value)
+ case strconv.ErrSyntax:
+ err = fmt.Errorf("not a valid number: %s", value)
+ }
+ }
+ return err
+ }
+ if l.Min != 0 || l.Max != 0 {
+ if v < l.Min {
+ return fmt.Errorf("value out of range (<%v): %s", l.Min, value)
+ }
+ if v > l.Max {
+ return fmt.Errorf("value out of range (>%v): %s", l.Max, value)
+ }
+ }
+ *n = signed(v)
+ return nil
+}
+
+func (n *signed) String() string {
+ signedLimitsMu.Lock()
+ l := signedLimits[n]
+ signedLimitsMu.Unlock()
+ if l != nil && l.Base != 0 {
+ return strconv.FormatInt(int64(*n), l.Base)
+ }
+ return strconv.FormatInt(int64(*n), 10)
+}
+
+// Signed creates an option that is stored in an int64 and is constrained
+// by the limits pointed to by l. The Max and Min values are only used if
+// at least one of the values are not 0. If Base is 0, the base is implied by
+// the string's prefix: base 16 for "0x", base 8 for "0", and base 10 otherwise.
+func Signed(name rune, value int64, l *SignedLimit, helpvalue ...string) *int64 {
+ CommandLine.signedOption(&value, "", name, l, helpvalue...)
+ return &value
+}
+
+func (s *Set) Signed(name rune, value int64, l *SignedLimit, helpvalue ...string) *int64 {
+ s.signedOption(&value, "", name, l, helpvalue...)
+ return &value
+}
+
+func SignedLong(name string, short rune, value int64, l *SignedLimit, helpvalue ...string) *int64 {
+ CommandLine.signedOption(&value, name, short, l, helpvalue...)
+ return &value
+}
+
+func (s *Set) SignedLong(name string, short rune, value int64, l *SignedLimit, helpvalue ...string) *int64 {
+ s.signedOption(&value, name, short, l, helpvalue...)
+ return &value
+}
+
+func (s *Set) signedOption(p *int64, name string, short rune, l *SignedLimit, helpvalue ...string) {
+ opt := s.FlagLong((*signed)(p), name, short, helpvalue...)
+ if l.Base > 36 || l.Base == 1 || l.Base < 0 {
+ fmt.Fprintf(stderr, "invalid base for %s: %d\n", opt.Name(), l.Base)
+ exit(1)
+ }
+ if l.Bits < 0 || l.Bits > 64 {
+ fmt.Fprintf(stderr, "invalid bit size for %s: %d\n", opt.Name(), l.Bits)
+ exit(1)
+ }
+ if l.Min > l.Max {
+ fmt.Fprintf(stderr, "min greater than max for %s\n", opt.Name())
+ exit(1)
+ }
+ lim := *l
+ signedLimitsMu.Lock()
+ signedLimits[(*signed)(p)] = &lim
+ signedLimitsMu.Unlock()
+}
diff --git a/vendor/github.com/pborman/getopt/v2/signed_test.go b/vendor/github.com/pborman/getopt/v2/signed_test.go
new file mode 100644
index 0000000..768a06d
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/v2/signed_test.go
@@ -0,0 +1,97 @@
+// Copyright 2017 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package getopt
+
+import (
+ "fmt"
+ "strings"
+ "testing"
+)
+
+var signedNumberTests = []struct {
+ where string
+ in []string
+ l SignedLimit
+ out int64
+ err string
+}{
+ {
+ where: loc(),
+ },
+ {
+ loc(),
+ []string{"test", "-n", "1010"},
+ SignedLimit{Base: 2, Bits: 5},
+ 10,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-n", "1010"},
+ SignedLimit{Base: 2, Bits: 4},
+ 0,
+ "test: value out of range: 1010\n",
+ },
+ {
+ loc(),
+ []string{"test", "-n", "-1000"},
+ SignedLimit{Base: 2, Bits: 4},
+ -8,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-n", "3"},
+ SignedLimit{Min: 4, Max: 6},
+ 0,
+ "test: value out of range (<4): 3\n",
+ },
+ {
+ loc(),
+ []string{"test", "-n", "4"},
+ SignedLimit{Min: 4, Max: 6},
+ 4,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-n", "5"},
+ SignedLimit{Min: 4, Max: 6},
+ 5,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-n", "6"},
+ SignedLimit{Min: 4, Max: 6},
+ 6,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-n", "7"},
+ SignedLimit{Min: 4, Max: 6},
+ 0,
+ "test: value out of range (>6): 7\n",
+ },
+}
+
+func TestSigneds(t *testing.T) {
+ for x, tt := range signedNumberTests {
+ if strings.Index(tt.where, ":-") > 0 {
+ tt.where = fmt.Sprintf("#%d", x)
+ }
+
+ reset()
+ n := Signed('n', 0, &tt.l)
+ parse(tt.in)
+ if s := checkError(tt.err); s != "" {
+ t.Errorf("%s: %s", tt.where, s)
+ }
+ if *n != tt.out {
+ t.Errorf("%s: got %v, want %v", tt.where, *n, tt.out)
+ }
+ }
+}
diff --git a/vendor/github.com/pborman/getopt/v2/string.go b/vendor/github.com/pborman/getopt/v2/string.go
new file mode 100644
index 0000000..cab5733
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/v2/string.go
@@ -0,0 +1,27 @@
+// Copyright 2017 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package getopt
+
+// String returns a value option that stores is value as a string. The
+// initial value of the string is passed in value.
+func String(name rune, value string, helpvalue ...string) *string {
+ CommandLine.Flag(&value, name, helpvalue...)
+ return &value
+}
+
+func (s *Set) String(name rune, value string, helpvalue ...string) *string {
+ s.Flag(&value, name, helpvalue...)
+ return &value
+}
+
+func StringLong(name string, short rune, value string, helpvalue ...string) *string {
+ CommandLine.FlagLong(&value, name, short, helpvalue...)
+ return &value
+}
+
+func (s *Set) StringLong(name string, short rune, value string, helpvalue ...string) *string {
+ s.FlagLong(&value, name, short, helpvalue...)
+ return &value
+}
diff --git a/vendor/github.com/pborman/getopt/v2/string_test.go b/vendor/github.com/pborman/getopt/v2/string_test.go
new file mode 100644
index 0000000..31abae8
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/v2/string_test.go
@@ -0,0 +1,77 @@
+// Copyright 2017 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package getopt
+
+import "testing"
+
+var stringTests = []struct {
+ where string
+ in []string
+ sout string
+ optout string
+ err string
+}{
+ {
+ loc(),
+ []string{},
+ "one",
+ "two",
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-s"},
+ "one",
+ "two",
+ "test: missing parameter for -s\n",
+ },
+ {
+ loc(),
+ []string{"test", "--opt"},
+ "one",
+ "two",
+ "test: missing parameter for --opt\n",
+ },
+ {
+ loc(),
+ []string{"test", "-svalue", "--opt=option"},
+ "value",
+ "option",
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-s", "value", "--opt", "option"},
+ "value",
+ "option",
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-swrong", "--opt=wrong", "-s", "value", "--opt", "option"},
+ "value",
+ "option",
+ "",
+ },
+}
+
+func TestString(t *testing.T) {
+ for _, tt := range stringTests {
+ reset()
+ s := String('s', "one")
+ opt := StringLong("opt", 0, "two")
+
+ parse(tt.in)
+ if s := checkError(tt.err); s != "" {
+ t.Errorf("%s: %s", tt.where, s)
+ }
+ if *s != tt.sout {
+ t.Errorf("%s: got s = %q, want %q", tt.where, *s, tt.sout)
+ }
+ if *opt != tt.optout {
+ t.Errorf("%s: got opt = %q, want %q", tt.where, *opt, tt.optout)
+ }
+ }
+}
diff --git a/vendor/github.com/pborman/getopt/v2/unsigned.go b/vendor/github.com/pborman/getopt/v2/unsigned.go
new file mode 100644
index 0000000..5594660
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/v2/unsigned.go
@@ -0,0 +1,111 @@
+// Copyright 2017 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package getopt
+
+import (
+ "fmt"
+ "strconv"
+ "sync"
+)
+
+type unsigned uint64
+
+type UnsignedLimit struct {
+ Base int // Base for conversion as per strconv.ParseInt
+ Bits int // Number of bits as per strconv.ParseInt
+ Min uint64 // Minimum allowed value if both Min and Max are not 0
+ Max uint64 // Maximum allowed value if both Min and Max are not 0
+}
+
+var (
+ unsignedLimitsMu sync.Mutex
+ unsignedLimits = make(map[*unsigned]*UnsignedLimit)
+)
+
+func (n *unsigned) Set(value string, opt Option) error {
+ unsignedLimitsMu.Lock()
+ l := unsignedLimits[n]
+ unsignedLimitsMu.Unlock()
+ if l == nil {
+ return fmt.Errorf("no limits defined for %s", opt.Name())
+ }
+ v, err := strconv.ParseUint(value, l.Base, l.Bits)
+ if err != nil {
+ if e, ok := err.(*strconv.NumError); ok {
+ switch e.Err {
+ case strconv.ErrRange:
+ err = fmt.Errorf("value out of range: %s", value)
+ case strconv.ErrSyntax:
+ err = fmt.Errorf("not a valid number: %s", value)
+ }
+ }
+ return err
+ }
+ if l.Min != 0 || l.Max != 0 {
+ if v < l.Min {
+ return fmt.Errorf("value out of range (<%v): %s", l.Min, value)
+ }
+ if v > l.Max {
+ return fmt.Errorf("value out of range (>%v): %s", l.Max, value)
+ }
+ }
+ *n = unsigned(v)
+ return nil
+}
+
+func (n *unsigned) String() string {
+ unsignedLimitsMu.Lock()
+ l := unsignedLimits[n]
+ unsignedLimitsMu.Unlock()
+ if l != nil && l.Base != 0 {
+ return strconv.FormatUint(uint64(*n), l.Base)
+ }
+ return strconv.FormatUint(uint64(*n), 10)
+}
+
+// Unsigned creates an option that is stored in a uint64 and is
+// constrained by the limits pointed to by l. The Max and Min values are only
+// used if at least one of the values are not 0. If Base is 0, the base is
+// implied by the string's prefix: base 16 for "0x", base 8 for "0", and base
+// 10 otherwise.
+func Unsigned(name rune, value uint64, l *UnsignedLimit, helpvalue ...string) *uint64 {
+ CommandLine.unsignedOption(&value, "", name, l, helpvalue...)
+ return &value
+}
+
+func (s *Set) Unsigned(name rune, value uint64, l *UnsignedLimit, helpvalue ...string) *uint64 {
+ s.unsignedOption(&value, "", name, l, helpvalue...)
+ return &value
+}
+
+func UnsignedLong(name string, short rune, value uint64, l *UnsignedLimit, helpvalue ...string) *uint64 {
+ CommandLine.unsignedOption(&value, name, short, l, helpvalue...)
+ return &value
+}
+
+func (s *Set) UnsignedLong(name string, short rune, value uint64, l *UnsignedLimit, helpvalue ...string) *uint64 {
+ s.unsignedOption(&value, name, short, l, helpvalue...)
+ return &value
+}
+
+func (s *Set) unsignedOption(p *uint64, name string, short rune, l *UnsignedLimit, helpvalue ...string) {
+ opt := s.FlagLong((*unsigned)(p), name, short, helpvalue...)
+ if l.Base > 36 || l.Base == 1 || l.Base < 0 {
+ fmt.Fprintf(stderr, "invalid base for %s: %d\n", opt.Name(), l.Base)
+ exit(1)
+ }
+ if l.Bits < 0 || l.Bits > 64 {
+ fmt.Fprintf(stderr, "invalid bit size for %s: %d\n", opt.Name(), l.Bits)
+ exit(1)
+ }
+ if l.Min > l.Max {
+ fmt.Fprintf(stderr, "min greater than max for %s\n", opt.Name())
+ exit(1)
+ }
+ lim := *l
+ unsignedLimitsMu.Lock()
+ unsignedLimits[(*unsigned)(p)] = &lim
+ unsignedLimitsMu.Unlock()
+}
diff --git a/vendor/github.com/pborman/getopt/v2/unsigned_test.go b/vendor/github.com/pborman/getopt/v2/unsigned_test.go
new file mode 100644
index 0000000..bf3d61a
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/v2/unsigned_test.go
@@ -0,0 +1,97 @@
+// Copyright 2017 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package getopt
+
+import (
+ "fmt"
+ "strings"
+ "testing"
+)
+
+var unsignedTests = []struct {
+ where string
+ in []string
+ l UnsignedLimit
+ out uint64
+ err string
+}{
+ {
+ where: loc(),
+ },
+ {
+ loc(),
+ []string{"test", "-n", "1010"},
+ UnsignedLimit{Base: 2, Bits: 5},
+ 10,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-n", "1010"},
+ UnsignedLimit{Base: 2, Bits: 4},
+ 10,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-n", "1010"},
+ UnsignedLimit{Base: 2, Bits: 3},
+ 0,
+ "test: value out of range: 1010\n",
+ },
+ {
+ loc(),
+ []string{"test", "-n", "3"},
+ UnsignedLimit{Min: 4, Max: 6},
+ 0,
+ "test: value out of range (<4): 3\n",
+ },
+ {
+ loc(),
+ []string{"test", "-n", "4"},
+ UnsignedLimit{Min: 4, Max: 6},
+ 4,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-n", "5"},
+ UnsignedLimit{Min: 4, Max: 6},
+ 5,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-n", "6"},
+ UnsignedLimit{Min: 4, Max: 6},
+ 6,
+ "",
+ },
+ {
+ loc(),
+ []string{"test", "-n", "7"},
+ UnsignedLimit{Min: 4, Max: 6},
+ 0,
+ "test: value out of range (>6): 7\n",
+ },
+}
+
+func TestUnsigneds(t *testing.T) {
+ for x, tt := range unsignedTests {
+ if strings.Index(tt.where, ":-") > 0 {
+ tt.where = fmt.Sprintf("#%d", x)
+ }
+
+ reset()
+ n := Unsigned('n', 0, &tt.l)
+ parse(tt.in)
+ if s := checkError(tt.err); s != "" {
+ t.Errorf("%s: %s", tt.where, s)
+ }
+ if *n != tt.out {
+ t.Errorf("%s: got %v, want %v", tt.where, *n, tt.out)
+ }
+ }
+}
diff --git a/vendor/github.com/pborman/getopt/v2/util_test.go b/vendor/github.com/pborman/getopt/v2/util_test.go
new file mode 100644
index 0000000..d46e198
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/v2/util_test.go
@@ -0,0 +1,85 @@
+// Copyright 2017 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package getopt
+
+import (
+ "bytes"
+ "fmt"
+ "path"
+ "reflect"
+ "runtime"
+ "strings"
+)
+
+var errorString string
+
+func reset() {
+ CommandLine.shortOptions = make(map[rune]*option)
+ CommandLine.longOptions = make(map[string]*option)
+ CommandLine.options = nil
+ CommandLine.args = nil
+ CommandLine.program = ""
+ errorString = ""
+}
+
+func parse(args []string) {
+ err := CommandLine.Getopt(args, nil)
+ if err != nil {
+ b := &bytes.Buffer{}
+
+ fmt.Fprintln(b, CommandLine.program+": "+err.Error())
+ CommandLine.PrintUsage(b)
+ errorString = b.String()
+ }
+}
+
+func badSlice(a, b []string) bool {
+ if len(a) != len(b) {
+ return true
+ }
+ for x, v := range a {
+ if b[x] != v {
+ return true
+ }
+ }
+ return false
+}
+
+func loc() string {
+ _, file, line, _ := runtime.Caller(1)
+ return fmt.Sprintf("%s:%d", path.Base(file), line)
+}
+
+func (o *option) Equal(opt *option) bool {
+ if o.value != nil && opt.value == nil {
+ return false
+ }
+ if o.value == nil && opt.value != nil {
+ return false
+ }
+ if o.value != nil && o.value.String() != opt.value.String() {
+ return false
+ }
+
+ oc := *o
+ optc := *opt
+ oc.value = nil
+ optc.value = nil
+ return reflect.DeepEqual(&oc, &optc)
+}
+
+func checkError(err string) string {
+ switch {
+ case err == errorString:
+ return ""
+ case err == "":
+ return fmt.Sprintf("unexpected error %q", errorString)
+ case errorString == "":
+ return fmt.Sprintf("did not get expected error %q", err)
+ case !strings.HasPrefix(errorString, err):
+ return fmt.Sprintf("got error %q, want %q", errorString, err)
+ }
+ return ""
+}
diff --git a/vendor/github.com/pborman/getopt/v2/var.go b/vendor/github.com/pborman/getopt/v2/var.go
new file mode 100644
index 0000000..0aaa79c
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/v2/var.go
@@ -0,0 +1,100 @@
+// Copyright 2017 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package getopt
+
+import (
+ "fmt"
+ "runtime"
+ "strings"
+)
+
+// Value is the interface to the dynamic value stored in a flag. Flags of type
+// Value are declared using the Flag and FlagLong functions.
+type Value interface {
+ // Set converts value into the appropriate type and assigns it to the
+ // receiver value. Option details are provided via opt (such as the
+ // flags name).
+ //
+ // Set is used to reset the value of an option to its default value
+ // (which is stored in string form internally).
+ Set(value string, opt Option) error
+
+ // String returns the value of the flag as a string.
+ String() string
+}
+
+var thisPackage string
+
+// init initializes thisPackage to our full package with the trailing .
+// included.
+func init() {
+ pc, _, _, ok := runtime.Caller(0)
+ if !ok {
+ return
+ }
+ f := runtime.FuncForPC(pc)
+ if f == nil {
+ return
+ }
+ thisPackage = f.Name()
+ x := strings.LastIndex(thisPackage, "/")
+ if x < 0 {
+ return
+ }
+ y := strings.Index(thisPackage[x:], ".")
+ if y < 0 {
+ return
+ }
+ // thisPackage includes the trailing . after the package name.
+ thisPackage = thisPackage[:x+y+1]
+}
+
+// calledFrom returns a string containing the file and linenumber of the first
+// stack frame above us that is not part of this package and is not a test.
+// This is used to determine where a flag was initialized.
+func calledFrom() string {
+ for i := 2; ; i++ {
+ pc, file, line, ok := runtime.Caller(i)
+ if !ok {
+ return ""
+ }
+ if !strings.HasSuffix(file, "_test.go") {
+ f := runtime.FuncForPC(pc)
+ if f != nil && strings.HasPrefix(f.Name(), thisPackage) {
+ continue
+ }
+ }
+ return fmt.Sprintf("%s:%d", file, line)
+ }
+}
+
+func (s *Set) addFlag(p Value, name string, short rune, helpvalue ...string) Option {
+ opt := &option{
+ short: short,
+ long: name,
+ value: p,
+ defval: p.String(),
+ }
+
+ switch len(helpvalue) {
+ case 2:
+ opt.name = helpvalue[1]
+ fallthrough
+ case 1:
+ opt.help = helpvalue[0]
+ case 0:
+ default:
+ panic("Too many strings for String helpvalue")
+ }
+ if where := calledFrom(); where != "" {
+ opt.where = where
+ }
+ if opt.short == 0 && opt.long == "" {
+ fmt.Fprintf(stderr, opt.where+": no short or long option given")
+ exit(1)
+ }
+ s.AddOption(opt)
+ return opt
+}
diff --git a/vendor/github.com/pborman/getopt/var.go b/vendor/github.com/pborman/getopt/var.go
new file mode 100644
index 0000000..fd816b9
--- /dev/null
+++ b/vendor/github.com/pborman/getopt/var.go
@@ -0,0 +1,63 @@
+// Copyright 2013 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package getopt
+
+import (
+ "fmt"
+ "runtime"
+)
+
+// Value is the interface to the dynamic value stored in a flag. (The default
+// value is represented as a string.) Set is passed the string to set the
+// value to as well as the Option that is being processed.
+type Value interface {
+ Set(string, Option) error
+ String() string
+}
+
+// Var creates an option of the specified name. The type and value of the option
+// are represented by the first argument, of type Value, which typically holds a
+// user-defined implementation of Value. All options are ultimately created
+// as a Var.
+func Var(p Value, name rune, helpvalue ...string) Option {
+ return CommandLine.VarLong(p, "", name, helpvalue...)
+}
+
+func VarLong(p Value, name string, short rune, helpvalue ...string) Option {
+ return CommandLine.VarLong(p, name, short, helpvalue...)
+}
+
+func (s *Set) Var(p Value, name rune, helpvalue ...string) Option {
+ return s.VarLong(p, "", name, helpvalue...)
+}
+
+func (s *Set) VarLong(p Value, name string, short rune, helpvalue ...string) Option {
+ opt := &option{
+ short: short,
+ long: name,
+ value: p,
+ defval: p.String(),
+ }
+
+ switch len(helpvalue) {
+ case 2:
+ opt.name = helpvalue[1]
+ fallthrough
+ case 1:
+ opt.help = helpvalue[0]
+ case 0:
+ default:
+ panic("Too many strings for String helpvalue")
+ }
+ if _, file, line, ok := runtime.Caller(1); ok {
+ opt.where = fmt.Sprintf("%s:%d", file, line)
+ }
+ if opt.short == 0 && opt.long == "" {
+ fmt.Fprintf(stderr, opt.where+": no short or long option given")
+ exit(1)
+ }
+ s.AddOption(opt)
+ return opt
+}
diff --git a/vendor/github.com/utahta/go-openuri/openuri.go b/vendor/github.com/utahta/go-openuri/openuri.go
new file mode 100644
index 0000000..a1ce966
--- /dev/null
+++ b/vendor/github.com/utahta/go-openuri/openuri.go
@@ -0,0 +1,54 @@
+package openuri
+
+import (
+ "io"
+ "net/http"
+ "os"
+ "strings"
+)
+
+// Client type
+type Client struct {
+ httpClient *http.Client
+}
+
+// ClientOption type
+type ClientOption func(*Client) error
+
+// New returns a Client struct
+func New(options ...ClientOption) (*Client, error) {
+ c := &Client{httpClient: http.DefaultClient}
+ for _, option := range options {
+ if err := option(c); err != nil {
+ return nil, err
+ }
+ }
+ return c, nil
+}
+
+// Open an io.ReadCloser from a local file or URL
+func Open(name string, options ...ClientOption) (io.ReadCloser, error) {
+ c, err := New(options...)
+ if err != nil {
+ return nil, err
+ }
+ return c.Open(name)
+}
+
+func WithHTTPClient(v *http.Client) ClientOption {
+ return func(c *Client) error {
+ c.httpClient = v
+ return nil
+ }
+}
+
+func (c *Client) Open(name string) (io.ReadCloser, error) {
+ if strings.HasPrefix(name, "http://") || strings.HasPrefix(name, "https://") {
+ resp, err := c.httpClient.Get(name)
+ if err != nil {
+ return nil, err
+ }
+ return resp.Body, nil
+ }
+ return os.Open(name)
+}
diff --git a/vendor/github.com/utahta/go-openuri/openuri_test.go b/vendor/github.com/utahta/go-openuri/openuri_test.go
new file mode 100644
index 0000000..7f653e6
--- /dev/null
+++ b/vendor/github.com/utahta/go-openuri/openuri_test.go
@@ -0,0 +1,74 @@
+package openuri
+
+import (
+ "io/ioutil"
+ "net/http"
+ "strings"
+ "testing"
+)
+
+type dummyRoundTripper struct{}
+
+func (d *dummyRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
+ return &http.Response{Status: "dummy", Body: ioutil.NopCloser(strings.NewReader("body dummy"))}, nil
+}
+
+func TestNew(t *testing.T) {
+ _, err := New()
+ if err != nil {
+ t.Error(err)
+ }
+}
+
+func TestWithHTTPClient(t *testing.T) {
+ c, err := New(WithHTTPClient(&http.Client{Transport: &dummyRoundTripper{}}))
+ if err != nil {
+ t.Error(err)
+ }
+
+ resp, _ := c.httpClient.Get("test")
+ if resp.Status != "dummy" {
+ t.Errorf("Expected status dummy, got %s", resp.Status)
+ }
+}
+
+func TestOpen_File(t *testing.T) {
+ o, err := Open("./openuri.go")
+ if err != nil {
+ t.Error(err)
+ }
+
+ b, err := ioutil.ReadAll(o)
+ if err != nil {
+ t.Error(err)
+ }
+
+ if !strings.HasPrefix(string(b), "package openuri") {
+ t.Errorf("Expected open file, go %s", string(b))
+ }
+}
+
+func TestOpen_URL(t *testing.T) {
+ tests := []struct {
+ url string
+ }{
+ {"http://example.com"},
+ {"https://example.com"},
+ }
+
+ for _, test := range tests {
+ o, err := Open(test.url, WithHTTPClient(&http.Client{Transport: &dummyRoundTripper{}}))
+ if err != nil {
+ t.Error(err)
+ }
+
+ b, err := ioutil.ReadAll(o)
+ if err != nil {
+ t.Error(err)
+ }
+
+ if !strings.HasPrefix(string(b), "body dummy") {
+ t.Errorf("Expected open file, go %s", string(b))
+ }
+ }
+}
diff --git a/vendor/gopkg.in/go-playground/validator.v9/README.md b/vendor/gopkg.in/go-playground/validator.v9/README.md
index 0259370..d783749 100644
--- a/vendor/gopkg.in/go-playground/validator.v9/README.md
+++ b/vendor/gopkg.in/go-playground/validator.v9/README.md
@@ -1,7 +1,7 @@
Package validator
================
<img align="right" src="https://raw.githubusercontent.com/go-playground/validator/v9/logo.png">[![Join the chat at https://gitter.im/go-playground/validator](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/go-playground/validator?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
-![Project status](https://img.shields.io/badge/version-9.9.0-green.svg)
+![Project status](https://img.shields.io/badge/version-9.11.0-green.svg)
[![Build Status](https://semaphoreci.com/api/v1/joeybloggs/validator/branches/v9/badge.svg)](https://semaphoreci.com/joeybloggs/validator)
[![Coverage Status](https://coveralls.io/repos/go-playground/validator/badge.svg?branch=v9&service=github)](https://coveralls.io/github/go-playground/validator?branch=v9)
[![Go Report Card](https://goreportcard.com/badge/github.com/go-playground/validator)](https://goreportcard.com/report/github.com/go-playground/validator)
@@ -66,69 +66,71 @@ Please see http://godoc.org/gopkg.in/go-playground/validator.v9 for detailed usa
Benchmarks
------
-###### Run on MacBook Pro (15-inch, 2017) Go version go1.9.2 darwin/amd64
+###### Run on MacBook Pro (15-inch, 2017) Go version go1.9.4 darwin/amd64
```go
-go test -bench=. -benchmem=true
-BenchmarkFieldSuccess-8 20000000 79.9 ns/op 0 B/op 0 allocs/op
-BenchmarkFieldSuccessParallel-8 50000000 25.0 ns/op 0 B/op 0 allocs/op
-BenchmarkFieldFailure-8 5000000 281 ns/op 208 B/op 4 allocs/op
-BenchmarkFieldFailureParallel-8 20000000 97.0 ns/op 208 B/op 4 allocs/op
-BenchmarkFieldArrayDiveSuccess-8 3000000 591 ns/op 201 B/op 11 allocs/op
-BenchmarkFieldArrayDiveSuccessParallel-8 10000000 195 ns/op 201 B/op 11 allocs/op
-BenchmarkFieldArrayDiveFailure-8 2000000 878 ns/op 412 B/op 16 allocs/op
-BenchmarkFieldArrayDiveFailureParallel-8 5000000 274 ns/op 413 B/op 16 allocs/op
-BenchmarkFieldMapDiveSuccess-8 1000000 1279 ns/op 432 B/op 18 allocs/op
-BenchmarkFieldMapDiveSuccessParallel-8 5000000 401 ns/op 432 B/op 18 allocs/op
-BenchmarkFieldMapDiveFailure-8 1000000 1060 ns/op 512 B/op 16 allocs/op
-BenchmarkFieldMapDiveFailureParallel-8 5000000 334 ns/op 512 B/op 16 allocs/op
-BenchmarkFieldMapDiveWithKeysSuccess-8 1000000 1462 ns/op 480 B/op 21 allocs/op
-BenchmarkFieldMapDiveWithKeysSuccessParallel-8 3000000 463 ns/op 480 B/op 21 allocs/op
-BenchmarkFieldMapDiveWithKeysFailure-8 1000000 1414 ns/op 721 B/op 21 allocs/op
-BenchmarkFieldMapDiveWithKeysFailureParallel-8 3000000 446 ns/op 721 B/op 21 allocs/op
-BenchmarkFieldCustomTypeSuccess-8 10000000 211 ns/op 32 B/op 2 allocs/op
-BenchmarkFieldCustomTypeSuccessParallel-8 20000000 65.9 ns/op 32 B/op 2 allocs/op
-BenchmarkFieldCustomTypeFailure-8 5000000 270 ns/op 208 B/op 4 allocs/op
-BenchmarkFieldCustomTypeFailureParallel-8 20000000 93.3 ns/op 208 B/op 4 allocs/op
-BenchmarkFieldOrTagSuccess-8 2000000 729 ns/op 16 B/op 1 allocs/op
-BenchmarkFieldOrTagSuccessParallel-8 5000000 367 ns/op 16 B/op 1 allocs/op
-BenchmarkFieldOrTagFailure-8 3000000 472 ns/op 224 B/op 5 allocs/op
-BenchmarkFieldOrTagFailureParallel-8 5000000 373 ns/op 224 B/op 5 allocs/op
-BenchmarkStructLevelValidationSuccess-8 10000000 201 ns/op 32 B/op 2 allocs/op
-BenchmarkStructLevelValidationSuccessParallel-8 20000000 66.3 ns/op 32 B/op 2 allocs/op
-BenchmarkStructLevelValidationFailure-8 3000000 468 ns/op 304 B/op 8 allocs/op
-BenchmarkStructLevelValidationFailureParallel-8 10000000 172 ns/op 304 B/op 8 allocs/op
-BenchmarkStructSimpleCustomTypeSuccess-8 5000000 376 ns/op 32 B/op 2 allocs/op
-BenchmarkStructSimpleCustomTypeSuccessParallel-8 20000000 126 ns/op 32 B/op 2 allocs/op
-BenchmarkStructSimpleCustomTypeFailure-8 2000000 646 ns/op 424 B/op 9 allocs/op
-BenchmarkStructSimpleCustomTypeFailureParallel-8 10000000 240 ns/op 440 B/op 10 allocs/op
-BenchmarkStructFilteredSuccess-8 3000000 582 ns/op 288 B/op 9 allocs/op
-BenchmarkStructFilteredSuccessParallel-8 10000000 198 ns/op 288 B/op 9 allocs/op
-BenchmarkStructFilteredFailure-8 3000000 447 ns/op 256 B/op 7 allocs/op
-BenchmarkStructFilteredFailureParallel-8 10000000 156 ns/op 256 B/op 7 allocs/op
-BenchmarkStructPartialSuccess-8 3000000 536 ns/op 256 B/op 6 allocs/op
-BenchmarkStructPartialSuccessParallel-8 10000000 175 ns/op 256 B/op 6 allocs/op
-BenchmarkStructPartialFailure-8 2000000 738 ns/op 480 B/op 11 allocs/op
-BenchmarkStructPartialFailureParallel-8 5000000 256 ns/op 480 B/op 11 allocs/op
-BenchmarkStructExceptSuccess-8 2000000 835 ns/op 496 B/op 12 allocs/op
-BenchmarkStructExceptSuccessParallel-8 10000000 163 ns/op 240 B/op 5 allocs/op
-BenchmarkStructExceptFailure-8 2000000 682 ns/op 464 B/op 10 allocs/op
-BenchmarkStructExceptFailureParallel-8 10000000 244 ns/op 464 B/op 10 allocs/op
-BenchmarkStructSimpleCrossFieldSuccess-8 5000000 392 ns/op 72 B/op 3 allocs/op
-BenchmarkStructSimpleCrossFieldSuccessParallel-8 20000000 126 ns/op 72 B/op 3 allocs/op
-BenchmarkStructSimpleCrossFieldFailure-8 2000000 611 ns/op 304 B/op 8 allocs/op
-BenchmarkStructSimpleCrossFieldFailureParallel-8 10000000 214 ns/op 304 B/op 8 allocs/op
-BenchmarkStructSimpleCrossStructCrossFieldSuccess-8 3000000 567 ns/op 80 B/op 4 allocs/op
-BenchmarkStructSimpleCrossStructCrossFieldSuccessParallel-8 10000000 177 ns/op 80 B/op 4 allocs/op
-BenchmarkStructSimpleCrossStructCrossFieldFailure-8 2000000 807 ns/op 320 B/op 9 allocs/op
-BenchmarkStructSimpleCrossStructCrossFieldFailureParallel-8 5000000 268 ns/op 320 B/op 9 allocs/op
-BenchmarkStructSimpleSuccess-8 5000000 256 ns/op 0 B/op 0 allocs/op
-BenchmarkStructSimpleSuccessParallel-8 20000000 76.3 ns/op 0 B/op 0 allocs/op
-BenchmarkStructSimpleFailure-8 2000000 625 ns/op 424 B/op 9 allocs/op
-BenchmarkStructSimpleFailureParallel-8 10000000 219 ns/op 424 B/op 9 allocs/op
-BenchmarkStructComplexSuccess-8 1000000 1431 ns/op 128 B/op 8 allocs/op
-BenchmarkStructComplexSuccessParallel-8 3000000 427 ns/op 128 B/op 8 allocs/op
-BenchmarkStructComplexFailure-8 300000 4065 ns/op 3041 B/op 53 allocs/op
-BenchmarkStructComplexFailureParallel-8 1000000 1478 ns/op 3041 B/op 53 allocs/op
+goos: darwin
+goarch: amd64
+pkg: github.com/go-playground/validator
+BenchmarkFieldSuccess-8 20000000 86.4 ns/op 0 B/op 0 allocs/op
+BenchmarkFieldSuccessParallel-8 50000000 27.6 ns/op 0 B/op 0 allocs/op
+BenchmarkFieldFailure-8 5000000 297 ns/op 208 B/op 4 allocs/op
+BenchmarkFieldFailureParallel-8 20000000 107 ns/op 208 B/op 4 allocs/op
+BenchmarkFieldArrayDiveSuccess-8 2000000 618 ns/op 201 B/op 11 allocs/op
+BenchmarkFieldArrayDiveSuccessParallel-8 10000000 225 ns/op 201 B/op 11 allocs/op
+BenchmarkFieldArrayDiveFailure-8 2000000 863 ns/op 412 B/op 16 allocs/op
+BenchmarkFieldArrayDiveFailureParallel-8 5000000 322 ns/op 413 B/op 16 allocs/op
+BenchmarkFieldMapDiveSuccess-8 1000000 1336 ns/op 432 B/op 18 allocs/op
+BenchmarkFieldMapDiveSuccessParallel-8 3000000 474 ns/op 432 B/op 18 allocs/op
+BenchmarkFieldMapDiveFailure-8 1000000 1103 ns/op 512 B/op 16 allocs/op
+BenchmarkFieldMapDiveFailureParallel-8 5000000 412 ns/op 512 B/op 16 allocs/op
+BenchmarkFieldMapDiveWithKeysSuccess-8 1000000 1572 ns/op 480 B/op 21 allocs/op
+BenchmarkFieldMapDiveWithKeysSuccessParallel-8 3000000 615 ns/op 480 B/op 21 allocs/op
+BenchmarkFieldMapDiveWithKeysFailure-8 1000000 1438 ns/op 721 B/op 21 allocs/op
+BenchmarkFieldMapDiveWithKeysFailureParallel-8 3000000 543 ns/op 721 B/op 21 allocs/op
+BenchmarkFieldCustomTypeSuccess-8 10000000 230 ns/op 32 B/op 2 allocs/op
+BenchmarkFieldCustomTypeSuccessParallel-8 20000000 82.5 ns/op 32 B/op 2 allocs/op
+BenchmarkFieldCustomTypeFailure-8 5000000 284 ns/op 208 B/op 4 allocs/op
+BenchmarkFieldCustomTypeFailureParallel-8 20000000 118 ns/op 208 B/op 4 allocs/op
+BenchmarkFieldOrTagSuccess-8 2000000 824 ns/op 16 B/op 1 allocs/op
+BenchmarkFieldOrTagSuccessParallel-8 3000000 472 ns/op 16 B/op 1 allocs/op
+BenchmarkFieldOrTagFailure-8 3000000 487 ns/op 224 B/op 5 allocs/op
+BenchmarkFieldOrTagFailureParallel-8 5000000 405 ns/op 224 B/op 5 allocs/op
+BenchmarkStructLevelValidationSuccess-8 10000000 214 ns/op 32 B/op 2 allocs/op
+BenchmarkStructLevelValidationSuccessParallel-8 20000000 78.0 ns/op 32 B/op 2 allocs/op
+BenchmarkStructLevelValidationFailure-8 3000000 475 ns/op 304 B/op 8 allocs/op
+BenchmarkStructLevelValidationFailureParallel-8 10000000 200 ns/op 304 B/op 8 allocs/op
+BenchmarkStructSimpleCustomTypeSuccess-8 3000000 403 ns/op 32 B/op 2 allocs/op
+BenchmarkStructSimpleCustomTypeSuccessParallel-8 10000000 143 ns/op 32 B/op 2 allocs/op
+BenchmarkStructSimpleCustomTypeFailure-8 2000000 655 ns/op 424 B/op 9 allocs/op
+BenchmarkStructSimpleCustomTypeFailureParallel-8 5000000 286 ns/op 440 B/op 10 allocs/op
+BenchmarkStructFilteredSuccess-8 2000000 598 ns/op 288 B/op 9 allocs/op
+BenchmarkStructFilteredSuccessParallel-8 10000000 231 ns/op 288 B/op 9 allocs/op
+BenchmarkStructFilteredFailure-8 3000000 455 ns/op 256 B/op 7 allocs/op
+BenchmarkStructFilteredFailureParallel-8 10000000 197 ns/op 256 B/op 7 allocs/op
+BenchmarkStructPartialSuccess-8 3000000 552 ns/op 256 B/op 6 allocs/op
+BenchmarkStructPartialSuccessParallel-8 10000000 206 ns/op 256 B/op 6 allocs/op
+BenchmarkStructPartialFailure-8 2000000 750 ns/op 480 B/op 11 allocs/op
+BenchmarkStructPartialFailureParallel-8 5000000 317 ns/op 480 B/op 11 allocs/op
+BenchmarkStructExceptSuccess-8 2000000 853 ns/op 496 B/op 12 allocs/op
+BenchmarkStructExceptSuccessParallel-8 10000000 179 ns/op 240 B/op 5 allocs/op
+BenchmarkStructExceptFailure-8 2000000 698 ns/op 464 B/op 10 allocs/op
+BenchmarkStructExceptFailureParallel-8 5000000 276 ns/op 464 B/op 10 allocs/op
+BenchmarkStructSimpleCrossFieldSuccess-8 3000000 412 ns/op 72 B/op 3 allocs/op
+BenchmarkStructSimpleCrossFieldSuccessParallel-8 10000000 148 ns/op 72 B/op 3 allocs/op
+BenchmarkStructSimpleCrossFieldFailure-8 2000000 630 ns/op 304 B/op 8 allocs/op
+BenchmarkStructSimpleCrossFieldFailureParallel-8 10000000 244 ns/op 304 B/op 8 allocs/op
+BenchmarkStructSimpleCrossStructCrossFieldSuccess-8 2000000 610 ns/op 80 B/op 4 allocs/op
+BenchmarkStructSimpleCrossStructCrossFieldSuccessParallel-8 10000000 205 ns/op 80 B/op 4 allocs/op
+BenchmarkStructSimpleCrossStructCrossFieldFailure-8 2000000 861 ns/op 320 B/op 9 allocs/op
+BenchmarkStructSimpleCrossStructCrossFieldFailureParallel-8 5000000 315 ns/op 320 B/op 9 allocs/op
+BenchmarkStructSimpleSuccess-8 5000000 279 ns/op 0 B/op 0 allocs/op
+BenchmarkStructSimpleSuccessParallel-8 20000000 86.4 ns/op 0 B/op 0 allocs/op
+BenchmarkStructSimpleFailure-8 2000000 636 ns/op 424 B/op 9 allocs/op
+BenchmarkStructSimpleFailureParallel-8 10000000 264 ns/op 424 B/op 9 allocs/op
+BenchmarkStructComplexSuccess-8 1000000 1539 ns/op 128 B/op 8 allocs/op
+BenchmarkStructComplexSuccessParallel-8 3000000 557 ns/op 128 B/op 8 allocs/op
+BenchmarkStructComplexFailure-8 300000 4136 ns/op 3041 B/op 53 allocs/op
+BenchmarkStructComplexFailureParallel-8 1000000 1855 ns/op 3041 B/op 53 allocs/op
```
Complementary Software
diff --git a/vendor/gopkg.in/go-playground/validator.v9/baked_in.go b/vendor/gopkg.in/go-playground/validator.v9/baked_in.go
index 6654094..231b78e 100644
--- a/vendor/gopkg.in/go-playground/validator.v9/baked_in.go
+++ b/vendor/gopkg.in/go-playground/validator.v9/baked_in.go
@@ -6,7 +6,9 @@ import (
"net"
"net/url"
"reflect"
+ "strconv"
"strings"
+ "sync"
"time"
"unicode/utf8"
)
@@ -55,88 +57,130 @@ var (
// you can add, remove or even replace items to suite your needs,
// or even disregard and use your own map if so desired.
bakedInValidators = map[string]Func{
- "required": hasValue,
- "isdefault": isDefault,
- "len": hasLengthOf,
- "min": hasMinOf,
- "max": hasMaxOf,
- "eq": isEq,
- "ne": isNe,
- "lt": isLt,
- "lte": isLte,
- "gt": isGt,
- "gte": isGte,
- "eqfield": isEqField,
- "eqcsfield": isEqCrossStructField,
- "necsfield": isNeCrossStructField,
- "gtcsfield": isGtCrossStructField,
- "gtecsfield": isGteCrossStructField,
- "ltcsfield": isLtCrossStructField,
- "ltecsfield": isLteCrossStructField,
- "nefield": isNeField,
- "gtefield": isGteField,
- "gtfield": isGtField,
- "ltefield": isLteField,
- "ltfield": isLtField,
- "alpha": isAlpha,
- "alphanum": isAlphanum,
- "alphaunicode": isAlphaUnicode,
- "alphanumunicode": isAlphanumUnicode,
- "numeric": isNumeric,
- "number": isNumber,
- "hexadecimal": isHexadecimal,
- "hexcolor": isHEXColor,
- "rgb": isRGB,
- "rgba": isRGBA,
- "hsl": isHSL,
- "hsla": isHSLA,
- "email": isEmail,
- "url": isURL,
- "uri": isURI,
- "base64": isBase64,
- "contains": contains,
- "containsany": containsAny,
- "containsrune": containsRune,
- "excludes": excludes,
- "excludesall": excludesAll,
- "excludesrune": excludesRune,
- "isbn": isISBN,
- "isbn10": isISBN10,
- "isbn13": isISBN13,
- "uuid": isUUID,
- "uuid3": isUUID3,
- "uuid4": isUUID4,
- "uuid5": isUUID5,
- "ascii": isASCII,
- "printascii": isPrintableASCII,
- "multibyte": hasMultiByteCharacter,
- "datauri": isDataURI,
- "latitude": isLatitude,
- "longitude": isLongitude,
- "ssn": isSSN,
- "ipv4": isIPv4,
- "ipv6": isIPv6,
- "ip": isIP,
- "cidrv4": isCIDRv4,
- "cidrv6": isCIDRv6,
- "cidr": isCIDR,
- "tcp4_addr": isTCP4AddrResolvable,
- "tcp6_addr": isTCP6AddrResolvable,
- "tcp_addr": isTCPAddrResolvable,
- "udp4_addr": isUDP4AddrResolvable,
- "udp6_addr": isUDP6AddrResolvable,
- "udp_addr": isUDPAddrResolvable,
- "ip4_addr": isIP4AddrResolvable,
- "ip6_addr": isIP6AddrResolvable,
- "ip_addr": isIPAddrResolvable,
- "unix_addr": isUnixAddrResolvable,
- "mac": isMAC,
- "hostname": isHostname,
- "fqdn": isFQDN,
- "unique": isUnique,
+ "required": hasValue,
+ "isdefault": isDefault,
+ "len": hasLengthOf,
+ "min": hasMinOf,
+ "max": hasMaxOf,
+ "eq": isEq,
+ "ne": isNe,
+ "lt": isLt,
+ "lte": isLte,
+ "gt": isGt,
+ "gte": isGte,
+ "eqfield": isEqField,
+ "eqcsfield": isEqCrossStructField,
+ "necsfield": isNeCrossStructField,
+ "gtcsfield": isGtCrossStructField,
+ "gtecsfield": isGteCrossStructField,
+ "ltcsfield": isLtCrossStructField,
+ "ltecsfield": isLteCrossStructField,
+ "nefield": isNeField,
+ "gtefield": isGteField,
+ "gtfield": isGtField,
+ "ltefield": isLteField,
+ "ltfield": isLtField,
+ "alpha": isAlpha,
+ "alphanum": isAlphanum,
+ "alphaunicode": isAlphaUnicode,
+ "alphanumunicode": isAlphanumUnicode,
+ "numeric": isNumeric,
+ "number": isNumber,
+ "hexadecimal": isHexadecimal,
+ "hexcolor": isHEXColor,
+ "rgb": isRGB,
+ "rgba": isRGBA,
+ "hsl": isHSL,
+ "hsla": isHSLA,
+ "email": isEmail,
+ "url": isURL,
+ "uri": isURI,
+ "base64": isBase64,
+ "contains": contains,
+ "containsany": containsAny,
+ "containsrune": containsRune,
+ "excludes": excludes,
+ "excludesall": excludesAll,
+ "excludesrune": excludesRune,
+ "isbn": isISBN,
+ "isbn10": isISBN10,
+ "isbn13": isISBN13,
+ "uuid": isUUID,
+ "uuid3": isUUID3,
+ "uuid4": isUUID4,
+ "uuid5": isUUID5,
+ "ascii": isASCII,
+ "printascii": isPrintableASCII,
+ "multibyte": hasMultiByteCharacter,
+ "datauri": isDataURI,
+ "latitude": isLatitude,
+ "longitude": isLongitude,
+ "ssn": isSSN,
+ "ipv4": isIPv4,
+ "ipv6": isIPv6,
+ "ip": isIP,
+ "cidrv4": isCIDRv4,
+ "cidrv6": isCIDRv6,
+ "cidr": isCIDR,
+ "tcp4_addr": isTCP4AddrResolvable,
+ "tcp6_addr": isTCP6AddrResolvable,
+ "tcp_addr": isTCPAddrResolvable,
+ "udp4_addr": isUDP4AddrResolvable,
+ "udp6_addr": isUDP6AddrResolvable,
+ "udp_addr": isUDPAddrResolvable,
+ "ip4_addr": isIP4AddrResolvable,
+ "ip6_addr": isIP6AddrResolvable,
+ "ip_addr": isIPAddrResolvable,
+ "unix_addr": isUnixAddrResolvable,
+ "mac": isMAC,
+ "hostname": isHostnameRFC952, // RFC 952
+ "hostname_rfc1123": isHostnameRFC1123, // RFC 1123
+ "fqdn": isFQDN,
+ "unique": isUnique,
+ "oneof": isOneOf,
}
)
+var oneofValsCache = map[string][]string{}
+var oneofValsCacheRWLock = sync.RWMutex{}
+
+func parseOneOfParam2(s string) []string {
+ oneofValsCacheRWLock.RLock()
+ vals, ok := oneofValsCache[s]
+ oneofValsCacheRWLock.RUnlock()
+ if !ok {
+ oneofValsCacheRWLock.Lock()
+ vals = strings.Fields(s)
+ oneofValsCache[s] = vals
+ oneofValsCacheRWLock.Unlock()
+ }
+ return vals
+}
+
+func isOneOf(fl FieldLevel) bool {
+ vals := parseOneOfParam2(fl.Param())
+
+ field := fl.Field()
+
+ var v string
+ switch field.Kind() {
+ case reflect.String:
+ v = field.String()
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ v = strconv.FormatInt(field.Int(), 10)
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+ v = strconv.FormatUint(field.Uint(), 10)
+ default:
+ panic(fmt.Sprintf("Bad field type %T", field.Interface()))
+ }
+ for i := 0; i < len(vals); i++ {
+ if vals[i] == v {
+ return true
+ }
+ }
+ return false
+}
+
// isUnique is the validation function for validating if each array|slice element is unique
func isUnique(fl FieldLevel) bool {
@@ -1511,8 +1555,12 @@ func isIP6Addr(fl FieldLevel) bool {
return ip != nil && ip.To4() == nil
}
-func isHostname(fl FieldLevel) bool {
- return hostnameRegex.MatchString(fl.Field().String())
+func isHostnameRFC952(fl FieldLevel) bool {
+ return hostnameRegexRFC952.MatchString(fl.Field().String())
+}
+
+func isHostnameRFC1123(fl FieldLevel) bool {
+ return hostnameRegexRFC1123.MatchString(fl.Field().String())
}
func isFQDN(fl FieldLevel) bool {
@@ -1526,6 +1574,6 @@ func isFQDN(fl FieldLevel) bool {
val = val[0 : len(val)-1]
}
- return (strings.IndexAny(val, ".") > -1) &&
- hostnameRegex.MatchString(val)
+ return strings.ContainsAny(val, ".") &&
+ hostnameRegexRFC952.MatchString(val)
}
diff --git a/vendor/gopkg.in/go-playground/validator.v9/benchmarks_test.go b/vendor/gopkg.in/go-playground/validator.v9/benchmarks_test.go
index 3e7e79f..5ac871f 100644
--- a/vendor/gopkg.in/go-playground/validator.v9/benchmarks_test.go
+++ b/vendor/gopkg.in/go-playground/validator.v9/benchmarks_test.go
@@ -1184,3 +1184,27 @@ func BenchmarkStructComplexFailureParallel(b *testing.B) {
}
})
}
+
+type TestOneof struct {
+ Color string `validate:"oneof=red green"`
+}
+
+func BenchmarkOneof(b *testing.B) {
+ w := &TestOneof{Color: "green"}
+ val := New()
+ for i := 0; i < b.N; i++ {
+ val.Struct(w)
+ }
+}
+
+func BenchmarkOneofParallel(b *testing.B) {
+ w := &TestOneof{Color: "green"}
+ val := New()
+
+ b.ResetTimer()
+ b.RunParallel(func(pb *testing.PB) {
+ for pb.Next() {
+ val.Struct(w)
+ }
+ })
+}
diff --git a/vendor/gopkg.in/go-playground/validator.v9/cache.go b/vendor/gopkg.in/go-playground/validator.v9/cache.go
index 8c59e16..c7fb0fb 100644
--- a/vendor/gopkg.in/go-playground/validator.v9/cache.go
+++ b/vendor/gopkg.in/go-playground/validator.v9/cache.go
@@ -91,12 +91,14 @@ type cTag struct {
aliasTag string
actualAliasTag string
param string
- typeof tagType
keys *cTag // only populated when using tag's 'keys' and 'endkeys' for map key validation
next *cTag
+ fn FuncCtx
+ typeof tagType
hasTag bool
hasAlias bool
- fn FuncCtx
+ hasParam bool // true if parameter used eg. eq= where the equal sign has been set
+ isBlockEnd bool // indicates the current tag represents the last validation in the block
}
func (v *Validate) extractStructCache(current reflect.Value, sName string) *cStruct {
@@ -291,6 +293,7 @@ func (v *Validate) parseFieldTagsRecursive(tag string, fieldName string, alias s
current.next = &cTag{aliasTag: alias, actualAliasTag: current.actualAliasTag, hasAlias: hasAlias, hasTag: true}
current = current.next
}
+ current.hasParam = len(vals) > 1
current.tag = vals[0]
if len(current.tag) == 0 {
@@ -309,8 +312,26 @@ func (v *Validate) parseFieldTagsRecursive(tag string, fieldName string, alias s
current.param = strings.Replace(strings.Replace(vals[1], utf8HexComma, ",", -1), utf8Pipe, "|", -1)
}
}
+ current.isBlockEnd = true
}
}
-
return
}
+
+func (v *Validate) fetchCacheTag(tag string) *cTag {
+ // find cached tag
+ ctag, found := v.tagCache.Get(tag)
+ if !found {
+ v.tagCache.lock.Lock()
+ defer v.tagCache.lock.Unlock()
+
+ // could have been multiple trying to access, but once first is done this ensures tag
+ // isn't parsed again.
+ ctag, found = v.tagCache.Get(tag)
+ if !found {
+ ctag, _ = v.parseFieldTagsRecursive(tag, "", "", false)
+ v.tagCache.Set(tag, ctag)
+ }
+ }
+ return ctag
+}
diff --git a/vendor/gopkg.in/go-playground/validator.v9/doc.go b/vendor/gopkg.in/go-playground/validator.v9/doc.go
index d3a69f7..f7efe23 100644
--- a/vendor/gopkg.in/go-playground/validator.v9/doc.go
+++ b/vendor/gopkg.in/go-playground/validator.v9/doc.go
@@ -94,7 +94,7 @@ used "eqcsfield" it could be multiple levels down. Example:
// NOTE: when calling validate.Struct(val) topStruct will be the top level struct passed
// into the function
- // when calling validate.FieldWithValue(val, field, tag) val will be
+ // when calling validate.VarWithValue(val, field, tag) val will be
// whatever you pass, struct, field...
// when calling validate.Field(field, tag) val will be nil
@@ -132,7 +132,7 @@ so the above will become excludesall=0x2C.
Field `validate:"excludesall=0x2C"` // GOOD! Use the UTF-8 hex representation.
}
-Pipe ("|") is the default separator of validation tags. If you wish to
+Pipe ("|") is the 'or' validation tags deparator. If you wish to
have a pipe included within the parameter i.e. excludesall=| you will need to
use the UTF-8 hex representation 0x7C, which is replaced in the code as a pipe,
so the above will become excludesall=0x7C
@@ -295,6 +295,16 @@ validates the number of items.
Usage: ne=10
+One Of
+
+For strings, ints, and uints, oneof will ensure that the value
+is one of the values in the parameter. The parameter should be
+a list of values separated by whitespace. Values may be
+strings or numbers.
+
+ Usage: oneof=red green
+ oneof=5 7 9
+
Greater Than
For numbers, this will ensure that the value is greater than the
@@ -369,7 +379,7 @@ Example #1:
Example #2:
// Validating by field:
- validate.FieldWithValue(password, confirmpassword, "eqfield")
+ validate.VarWithValue(password, confirmpassword, "eqfield")
Field Equals Another Field (relative)
@@ -391,7 +401,7 @@ Examples:
Usage: nefield=Color2
// Validating by field:
- validate.FieldWithValue(color1, color2, "nefield")
+ validate.VarWithValue(color1, color2, "nefield")
Field Does Not Equal Another Field (relative)
@@ -414,7 +424,7 @@ Example #1:
Example #2:
// Validating by field:
- validate.FieldWithValue(start, end, "gtfield")
+ validate.VarWithValue(start, end, "gtfield")
Field Greater Than Another Relative Field
@@ -438,7 +448,7 @@ Example #1:
Example #2:
// Validating by field:
- validate.FieldWithValue(start, end, "gtefield")
+ validate.VarWithValue(start, end, "gtefield")
Field Greater Than or Equal To Another Relative Field
@@ -461,7 +471,7 @@ Example #1:
Example #2:
// Validating by field:
- validate.FieldWithValue(start, end, "ltfield")
+ validate.VarWithValue(start, end, "ltfield")
Less Than Another Relative Field
@@ -484,7 +494,7 @@ Example #1:
Example #2:
// Validating by field:
- validate.FieldWithValue(start, end, "ltefield")
+ validate.VarWithValue(start, end, "ltefield")
Less Than or Equal To Another Relative Field
@@ -832,12 +842,18 @@ Note: See Go's ParseMAC for accepted formats and types:
http://golang.org/src/net/mac.go?s=866:918#L29
-Hostname
+Hostname RFC 952
-This validates that a string value is a valid Hostname
+This validates that a string value is a valid Hostname according to RFC 952 https://tools.ietf.org/html/rfc952
Usage: hostname
+Hostname RFC 1123
+
+This validates that a string value is a valid Hostname according to RFC 1123 https://tools.ietf.org/html/rfc1123
+
+ Usage: hostname_rfc1123 or if you want to continue to use 'hostname' in your tags, create an alias.
+
Full Qualified Domain Name (FQDN)
This validates that a string value contains a valid FQDN.
diff --git a/vendor/gopkg.in/go-playground/validator.v9/regexes.go b/vendor/gopkg.in/go-playground/validator.v9/regexes.go
index ec78ceb..78f3ea0 100644
--- a/vendor/gopkg.in/go-playground/validator.v9/regexes.go
+++ b/vendor/gopkg.in/go-playground/validator.v9/regexes.go
@@ -30,7 +30,8 @@ const (
latitudeRegexString = "^[-+]?([1-8]?\\d(\\.\\d+)?|90(\\.0+)?)$"
longitudeRegexString = "^[-+]?(180(\\.0+)?|((1[0-7]\\d)|([1-9]?\\d))(\\.\\d+)?)$"
sSNRegexString = `^\d{3}[- ]?\d{2}[- ]?\d{4}$`
- hostnameRegexString = `^[a-zA-Z][a-zA-Z0-9\-\.]+[a-z-Az0-9]$`
+ hostnameRegexStringRFC952 = `^[a-zA-Z][a-zA-Z0-9\-\.]+[a-z-Az0-9]$` // https://tools.ietf.org/html/rfc952
+ hostnameRegexStringRFC1123 = `^[a-zA-Z0-9][a-zA-Z0-9\-\.]+[a-z-Az0-9]$` // accepts hostname starting with a digit https://tools.ietf.org/html/rfc1123
)
var (
@@ -61,5 +62,6 @@ var (
latitudeRegex = regexp.MustCompile(latitudeRegexString)
longitudeRegex = regexp.MustCompile(longitudeRegexString)
sSNRegex = regexp.MustCompile(sSNRegexString)
- hostnameRegex = regexp.MustCompile(hostnameRegexString)
+ hostnameRegexRFC952 = regexp.MustCompile(hostnameRegexStringRFC952)
+ hostnameRegexRFC1123 = regexp.MustCompile(hostnameRegexStringRFC1123)
)
diff --git a/vendor/gopkg.in/go-playground/validator.v9/util.go b/vendor/gopkg.in/go-playground/validator.v9/util.go
index a01d4b1..16a5517 100644
--- a/vendor/gopkg.in/go-playground/validator.v9/util.go
+++ b/vendor/gopkg.in/go-playground/validator.v9/util.go
@@ -80,7 +80,7 @@ BEGIN:
typ := current.Type()
fld := namespace
- ns := namespace
+ var ns string
if typ != timeType {
diff --git a/vendor/gopkg.in/go-playground/validator.v9/validator.go b/vendor/gopkg.in/go-playground/validator.v9/validator.go
index f180a9c..483e0a2 100644
--- a/vendor/gopkg.in/go-playground/validator.v9/validator.go
+++ b/vendor/gopkg.in/go-playground/validator.v9/validator.go
@@ -14,24 +14,19 @@ type validate struct {
ns []byte
actualNs []byte
errs ValidationErrors
+ includeExclude map[string]struct{} // reset only if StructPartial or StructExcept are called, no need otherwise
+ ffn FilterFunc
+ slflParent reflect.Value // StructLevel & FieldLevel
+ slCurrent reflect.Value // StructLevel & FieldLevel
+ flField reflect.Value // StructLevel & FieldLevel
+ cf *cField // StructLevel & FieldLevel
+ ct *cTag // StructLevel & FieldLevel
+ misc []byte // misc reusable
+ str1 string // misc reusable
+ str2 string // misc reusable
+ fldIsPointer bool // StructLevel & FieldLevel
isPartial bool
hasExcludes bool
- includeExclude map[string]struct{} // reset only if StructPartial or StructExcept are called, no need otherwise
-
- ffn FilterFunc
-
- // StructLevel & FieldLevel fields
- slflParent reflect.Value
- slCurrent reflect.Value
- flField reflect.Value
- fldIsPointer bool
- cf *cField
- ct *cTag
-
- // misc reusable values
- misc []byte
- str1 string
- str2 string
}
// parent and current will be the same the first run of validateStruct
@@ -127,7 +122,6 @@ func (v *validate) traverseField(ctx context.Context, parent reflect.Value, curr
}
if kind == reflect.Invalid {
-
v.errs = append(v.errs,
&fieldError{
v: v.v,
@@ -378,14 +372,13 @@ OUTER:
v.misc = append(v.misc, '|')
v.misc = append(v.misc, ct.tag...)
- if len(ct.param) > 0 {
+ if ct.hasParam {
v.misc = append(v.misc, '=')
v.misc = append(v.misc, ct.param...)
}
- if ct.next == nil || ct.next.typeof != typeOr { // ct.typeof != typeOr
+ if ct.isBlockEnd || ct.next == nil {
// if we get here, no valid 'or' value and no more tags
-
v.str1 = string(append(ns, cf.altName...))
if v.v.hasTagNameFunc {
@@ -474,9 +467,7 @@ OUTER:
)
return
-
}
-
ct = ct.next
}
}
diff --git a/vendor/gopkg.in/go-playground/validator.v9/validator_instance.go b/vendor/gopkg.in/go-playground/validator.v9/validator_instance.go
index d3a1543..e84b452 100644
--- a/vendor/gopkg.in/go-playground/validator.v9/validator_instance.go
+++ b/vendor/gopkg.in/go-playground/validator.v9/validator_instance.go
@@ -370,39 +370,37 @@ func (v *Validate) StructPartialCtx(ctx context.Context, s interface{}, fields .
typ := val.Type()
name := typ.Name()
- if fields != nil {
- for _, k := range fields {
+ for _, k := range fields {
- flds := strings.Split(k, namespaceSeparator)
- if len(flds) > 0 {
+ flds := strings.Split(k, namespaceSeparator)
+ if len(flds) > 0 {
- vd.misc = append(vd.misc[0:0], name...)
- vd.misc = append(vd.misc, '.')
-
- for _, s := range flds {
+ vd.misc = append(vd.misc[0:0], name...)
+ vd.misc = append(vd.misc, '.')
- idx := strings.Index(s, leftBracket)
+ for _, s := range flds {
- if idx != -1 {
- for idx != -1 {
- vd.misc = append(vd.misc, s[:idx]...)
- vd.includeExclude[string(vd.misc)] = struct{}{}
+ idx := strings.Index(s, leftBracket)
- idx2 := strings.Index(s, rightBracket)
- idx2++
- vd.misc = append(vd.misc, s[idx:idx2]...)
- vd.includeExclude[string(vd.misc)] = struct{}{}
- s = s[idx2:]
- idx = strings.Index(s, leftBracket)
- }
- } else {
+ if idx != -1 {
+ for idx != -1 {
+ vd.misc = append(vd.misc, s[:idx]...)
+ vd.includeExclude[string(vd.misc)] = struct{}{}
- vd.misc = append(vd.misc, s...)
+ idx2 := strings.Index(s, rightBracket)
+ idx2++
+ vd.misc = append(vd.misc, s[idx:idx2]...)
vd.includeExclude[string(vd.misc)] = struct{}{}
+ s = s[idx2:]
+ idx = strings.Index(s, leftBracket)
}
+ } else {
- vd.misc = append(vd.misc, '.')
+ vd.misc = append(vd.misc, s...)
+ vd.includeExclude[string(vd.misc)] = struct{}{}
}
+
+ vd.misc = append(vd.misc, '.')
}
}
}
@@ -520,36 +518,18 @@ func (v *Validate) VarCtx(ctx context.Context, field interface{}, tag string) (e
return nil
}
- // find cached tag
- ctag, ok := v.tagCache.Get(tag)
- if !ok {
- v.tagCache.lock.Lock()
- defer v.tagCache.lock.Unlock()
-
- // could have been multiple trying to access, but once first is done this ensures tag
- // isn't parsed again.
- ctag, ok = v.tagCache.Get(tag)
- if !ok {
- ctag, _ = v.parseFieldTagsRecursive(tag, "", "", false)
- v.tagCache.Set(tag, ctag)
- }
- }
-
+ ctag := v.fetchCacheTag(tag)
val := reflect.ValueOf(field)
-
vd := v.pool.Get().(*validate)
vd.top = val
vd.isPartial = false
-
vd.traverseField(ctx, val, val, vd.ns[0:0], vd.actualNs[0:0], defaultCField, ctag)
if len(vd.errs) > 0 {
err = vd.errs
vd.errs = nil
}
-
v.pool.Put(vd)
-
return
}
@@ -590,36 +570,17 @@ func (v *Validate) VarWithValueCtx(ctx context.Context, field interface{}, other
if len(tag) == 0 || tag == skipValidationTag {
return nil
}
-
- // find cached tag
- ctag, ok := v.tagCache.Get(tag)
- if !ok {
- v.tagCache.lock.Lock()
- defer v.tagCache.lock.Unlock()
-
- // could have been multiple trying to access, but once first is done this ensures tag
- // isn't parsed again.
- ctag, ok = v.tagCache.Get(tag)
- if !ok {
- ctag, _ = v.parseFieldTagsRecursive(tag, "", "", false)
- v.tagCache.Set(tag, ctag)
- }
- }
-
+ ctag := v.fetchCacheTag(tag)
otherVal := reflect.ValueOf(other)
-
vd := v.pool.Get().(*validate)
vd.top = otherVal
vd.isPartial = false
-
vd.traverseField(ctx, otherVal, reflect.ValueOf(field), vd.ns[0:0], vd.actualNs[0:0], defaultCField, ctag)
if len(vd.errs) > 0 {
err = vd.errs
vd.errs = nil
}
-
v.pool.Put(vd)
-
return
}
diff --git a/vendor/gopkg.in/go-playground/validator.v9/validator_test.go b/vendor/gopkg.in/go-playground/validator.v9/validator_test.go
index 7d085e8..9600d0f 100644
--- a/vendor/gopkg.in/go-playground/validator.v9/validator_test.go
+++ b/vendor/gopkg.in/go-playground/validator.v9/validator_test.go
@@ -1564,10 +1564,6 @@ func TestCrossNamespaceFieldValidation(t *testing.T) {
Name string
}
- type MapStruct struct {
- Name string
- }
-
type Inner struct {
CreatedAt *time.Time
Slice []string
@@ -1653,10 +1649,10 @@ func TestCrossNamespaceFieldValidation(t *testing.T) {
Equal(t, kind, reflect.String)
Equal(t, current.String(), "val2")
- current, kind, ok = v.getStructFieldOKInternal(val, "Inner.CrazyNonExistantField")
+ current, _, ok = v.getStructFieldOKInternal(val, "Inner.CrazyNonExistantField")
Equal(t, ok, false)
- current, kind, ok = v.getStructFieldOKInternal(val, "Inner.Slice[101]")
+ current, _, ok = v.getStructFieldOKInternal(val, "Inner.Slice[101]")
Equal(t, ok, false)
current, kind, ok = v.getStructFieldOKInternal(val, "Inner.Map[key3]")
@@ -1854,8 +1850,6 @@ func TestSQLValue2Validation(t *testing.T) {
PanicMatches(t, func() { validate.Var(val, "required") }, "SQL Driver Valuer error: some kind of error")
- type myValuer valuer
-
myVal := valuer{
Name: "",
}
@@ -1907,8 +1901,6 @@ func TestSQLValueValidation(t *testing.T) {
PanicMatches(t, func() { errs = validate.Var(val, "required") }, "SQL Driver Valuer error: some kind of error")
- type myValuer valuer
-
myVal := valuer{
Name: "",
}
@@ -2696,11 +2688,8 @@ func TestBadKeyValidation(t *testing.T) {
func TestInterfaceErrValidation(t *testing.T) {
- var v1 interface{}
- var v2 interface{}
-
- v2 = 1
- v1 = v2
+ var v2 interface{} = 1
+ var v1 interface{} = v2
validate := New()
errs := validate.Var(v1, "len=1")
@@ -4325,6 +4314,66 @@ func TestIsEqValidation(t *testing.T) {
PanicMatches(t, func() { validate.Var(now, "eq=now") }, "Bad field type time.Time")
}
+func TestOneOfValidation(t *testing.T) {
+ validate := New()
+
+ passSpecs := []struct {
+ f interface{}
+ t string
+ }{
+ {f: "red", t: "oneof=red green"},
+ {f: "green", t: "oneof=red green"},
+ {f: 5, t: "oneof=5 6"},
+ {f: 6, t: "oneof=5 6"},
+ {f: int8(6), t: "oneof=5 6"},
+ {f: int16(6), t: "oneof=5 6"},
+ {f: int32(6), t: "oneof=5 6"},
+ {f: int64(6), t: "oneof=5 6"},
+ {f: uint(6), t: "oneof=5 6"},
+ {f: uint8(6), t: "oneof=5 6"},
+ {f: uint16(6), t: "oneof=5 6"},
+ {f: uint32(6), t: "oneof=5 6"},
+ {f: uint64(6), t: "oneof=5 6"},
+ }
+
+ for _, spec := range passSpecs {
+ t.Logf("%#v", spec)
+ errs := validate.Var(spec.f, spec.t)
+ Equal(t, errs, nil)
+ }
+
+ failSpecs := []struct {
+ f interface{}
+ t string
+ }{
+ {f: "", t: "oneof=red green"},
+ {f: "yellow", t: "oneof=red green"},
+ {f: 5, t: "oneof=red green"},
+ {f: 6, t: "oneof=red green"},
+ {f: 6, t: "oneof=7"},
+ {f: uint(6), t: "oneof=7"},
+ {f: int8(5), t: "oneof=red green"},
+ {f: int16(5), t: "oneof=red green"},
+ {f: int32(5), t: "oneof=red green"},
+ {f: int64(5), t: "oneof=red green"},
+ {f: uint(5), t: "oneof=red green"},
+ {f: uint8(5), t: "oneof=red green"},
+ {f: uint16(5), t: "oneof=red green"},
+ {f: uint32(5), t: "oneof=red green"},
+ {f: uint64(5), t: "oneof=red green"},
+ }
+
+ for _, spec := range failSpecs {
+ t.Logf("%#v", spec)
+ errs := validate.Var(spec.f, spec.t)
+ AssertError(t, errs, "", "", "", "", "oneof")
+ }
+
+ PanicMatches(t, func() {
+ validate.Var(3.14, "oneof=red green")
+ }, "Bad field type float64")
+}
+
func TestBase64Validation(t *testing.T) {
validate := New()
@@ -5585,6 +5634,13 @@ func TestOrTag(t *testing.T) {
errs = validate.Var(s, "omitempty,rgb|rgba")
Equal(t, errs, nil)
+ s = "green"
+ errs = validate.Var(s, "eq=|eq=blue,rgb|rgba") //should fail on first validation block
+ NotEqual(t, errs, nil)
+ ve := errs.(ValidationErrors)
+ Equal(t, len(ve), 1)
+ Equal(t, ve[0].Tag(), "eq=|eq=blue")
+
s = "this is right, but a blank or isn't"
PanicMatches(t, func() { validate.Var(s, "rgb||len=13") }, "Invalid validation tag on field ''")
@@ -7139,7 +7195,7 @@ func TestValidateStructRegisterCtx(t *testing.T) {
Equal(t, ctxSlVal, "slVal")
}
-func TestHostnameValidation(t *testing.T) {
+func TestHostnameRFC952Validation(t *testing.T) {
tests := []struct {
param string
expected bool
@@ -7150,6 +7206,7 @@ func TestHostnameValidation(t *testing.T) {
{"test.example24.com", true},
{"test24.example24.com", true},
{"example", true},
+ {"1.foo.com", false},
{"test.example.com.", false},
{"example.com.", false},
{"example24.com.", false},
@@ -7171,15 +7228,112 @@ func TestHostnameValidation(t *testing.T) {
if test.expected {
if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d hostname failed Error: %s", i, errs)
+ t.Fatalf("Index: %d hostname failed Error: %v", i, errs)
+ }
+ } else {
+ if IsEqual(errs, nil) {
+ t.Fatalf("Index: %d hostname failed Error: %v", i, errs)
+ } else {
+ val := getError(errs, "", "")
+ if val.Tag() != "hostname" {
+ t.Fatalf("Index: %d hostname failed Error: %v", i, errs)
+ }
+ }
+ }
+ }
+}
+
+func TestHostnameRFC1123Validation(t *testing.T) {
+ tests := []struct {
+ param string
+ expected bool
+ }{
+ {"test.example.com", true},
+ {"example.com", true},
+ {"example24.com", true},
+ {"test.example24.com", true},
+ {"test24.example24.com", true},
+ {"example", true},
+ {"1.foo.com", true},
+ {"test.example.com.", false},
+ {"example.com.", false},
+ {"example24.com.", false},
+ {"test.example24.com.", false},
+ {"test24.example24.com.", false},
+ {"example.", false},
+ {"192.168.0.1", true},
+ {"email@example.com", false},
+ {"2001:cdba:0000:0000:0000:0000:3257:9652", false},
+ {"2001:cdba:0:0:0:0:3257:9652", false},
+ {"2001:cdba::3257:9652", false},
+ }
+
+ validate := New()
+
+ for i, test := range tests {
+
+ errs := validate.Var(test.param, "hostname_rfc1123")
+
+ if test.expected {
+ if !IsEqual(errs, nil) {
+ t.Fatalf("Index: %d hostname failed Error: %v", i, errs)
+ }
+ } else {
+ if IsEqual(errs, nil) {
+ t.Fatalf("Index: %d hostname failed Error: %v", i, errs)
+ } else {
+ val := getError(errs, "", "")
+ if val.Tag() != "hostname_rfc1123" {
+ t.Fatalf("Index: %d hostname failed Error: %v", i, errs)
+ }
+ }
+ }
+ }
+}
+
+func TestHostnameRFC1123AliasValidation(t *testing.T) {
+ tests := []struct {
+ param string
+ expected bool
+ }{
+ {"test.example.com", true},
+ {"example.com", true},
+ {"example24.com", true},
+ {"test.example24.com", true},
+ {"test24.example24.com", true},
+ {"example", true},
+ {"1.foo.com", true},
+ {"test.example.com.", false},
+ {"example.com.", false},
+ {"example24.com.", false},
+ {"test.example24.com.", false},
+ {"test24.example24.com.", false},
+ {"example.", false},
+ {"192.168.0.1", true},
+ {"email@example.com", false},
+ {"2001:cdba:0000:0000:0000:0000:3257:9652", false},
+ {"2001:cdba:0:0:0:0:3257:9652", false},
+ {"2001:cdba::3257:9652", false},
+ }
+
+ validate := New()
+ validate.RegisterAlias("hostname", "hostname_rfc1123")
+
+ for i, test := range tests {
+
+ errs := validate.Var(test.param, "hostname")
+
+ if test.expected {
+ if !IsEqual(errs, nil) {
+ t.Fatalf("Index: %d hostname failed Error: %v", i, errs)
}
} else {
if IsEqual(errs, nil) {
- t.Fatalf("Index: %d hostname failed Error: %s", i, errs)
+ t.Fatalf("Index: %d hostname failed Error: %v", i, errs)
} else {
val := getError(errs, "", "")
if val.Tag() != "hostname" {
- t.Fatalf("Index: %d hostname failed Error: %s", i, errs)
+ t.Fatalf("Index: %d hostname failed Error: %v", i, errs)
}
}
}
@@ -7219,15 +7373,15 @@ func TestFQDNValidation(t *testing.T) {
if test.expected {
if !IsEqual(errs, nil) {
- t.Fatalf("Index: %d fqdn failed Error: %s", i, errs)
+ t.Fatalf("Index: %d fqdn failed Error: %v", i, errs)
}
} else {
if IsEqual(errs, nil) {
- t.Fatalf("Index: %d fqdn failed Error: %s", i, errs)
+ t.Fatalf("Index: %d fqdn failed Error: %v", i, errs)
} else {
val := getError(errs, "", "")
if val.Tag() != "fqdn" {
- t.Fatalf("Index: %d fqdn failed Error: %s", i, errs)
+ t.Fatalf("Index: %d fqdn failed Error: %v", i, errs)
}
}
}