summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Duvall <dduvall@wikimedia.org>2018-03-06 20:31:58 -0800
committerDan Duvall <dduvall@wikimedia.org>2018-03-19 15:55:16 -0700
commiteb9b69dd3d710cb7afa1dfb6e23a5987842b21cc (patch)
tree049b11cc885e4e9f54aac8981c91a1bf3620e7af
parent6896e655eb5cc88b90e66979bc2d862eb92cbb9f (diff)
downloadblubber-eb9b69dd3d710cb7afa1dfb6e23a5987842b21cc.tar.gz
Allow for configuration policies
Summary: Implements a rough interface for validating configuration against arbitrary policy rules. Policies are provided as YAML and passed via the command line as file paths or remote URIs. The format of policies is: enforcements: - path: <path> rule: <rule> Where `<path>` is a YAML-ish path to a config field and `<rule>` is any expression our config validator understands (expressions built in by the validator library and custom tags defined in `config.validation.go`). Example policy: enforcements: - path: variants.production.base rule: oneof=debian:jessie debian:stretch - path: variants.production.runs.as rule: ne=foo - path: variants.production.node.dependencies rule: isfalse Command flag parsing was implemented in `main.go` to support the new `--policy=uri` flag and improve existing handling of `--version` and the usage statement. Test Plan: Run `go test ./...`. Reviewers: thcipriani, demon, hashar, mmodell, #release-engineering-team Reviewed By: thcipriani, #release-engineering-team Tags: #release-engineering-team Differential Revision: https://phabricator.wikimedia.org/D999
-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)
}
}
}