Fix #736: Find home dir without using cgo
diff --git a/glide.lock b/glide.lock index 2d3fc9c..5a9fee4 100644 --- a/glide.lock +++ b/glide.lock
@@ -1,12 +1,14 @@ -hash: 67c5571c33bfcb663d32d2b40b9ce1f2a05a3fa2e9f442077277c2782195729c -updated: 2016-08-11T14:22:17.773372627-04:00 +hash: e36c5a71bd15a6d2f7f795a68b0fbfbd41537ee29aec16e7105bd8fd3ef118ee +updated: 2017-01-12T13:12:10.704271522-05:00 imports: - name: github.com/codegangsta/cli - version: 1efa31f08b9333f1bd4882d61f9d668a70cd902e + version: 0bdeddeeb0f650497d603c4ad7b20cfe685682f6 - name: github.com/Masterminds/semver - version: 8d0431362b544d1a3536cca26684828866a7de09 + version: 59c29afe1a994eacb71c833025ca7acf874bb1da - name: github.com/Masterminds/vcs - version: fbe9fb6ad5b5f35b3e82a7c21123cfc526cbf895 + version: 87fca6b9ec721bb38f1e9f2e3c0a36c78f6067d5 +- name: github.com/mitchellh/go-homedir + version: b8bc1bf767474819792c23f32d8286a45736f1c6 - name: gopkg.in/yaml.v2 - version: e4d366fc3c7938e2958e662b4258c7a89e1f0e3e + version: a5b47d31c556af34a302ce5d659e6fea44d90de0 testImports: []
diff --git a/glide.yaml b/glide.yaml index f293f35..875506c 100644 --- a/glide.yaml +++ b/glide.yaml
@@ -16,3 +16,4 @@ version: ^1.16.0 - package: github.com/Masterminds/semver version: ^1.1.1 +- package: github.com/mitchellh/go-homedir
diff --git a/path/path.go b/path/path.go index 953d851..2181c99 100644 --- a/path/path.go +++ b/path/path.go
@@ -8,9 +8,10 @@ "fmt" "io" "os" - "os/user" "path/filepath" "strings" + + "github.com/mitchellh/go-homedir" ) // DefaultGlideFile is the default name for the glide.yaml file. @@ -45,10 +46,8 @@ return homeDir } - // Initialize the default user. - u, err := user.Current() - if err == nil && u.HomeDir != "" { - homeDir = filepath.Join(u.HomeDir, ".glide") + if h, err := homedir.Dir(); err != nil { + homeDir = filepath.Join(h, ".glide") } else { cwd, err := os.Getwd() if err == nil {
diff --git a/vendor/github.com/Masterminds/semver/.travis.yml b/vendor/github.com/Masterminds/semver/.travis.yml index 5600ae8..3231840 100644 --- a/vendor/github.com/Masterminds/semver/.travis.yml +++ b/vendor/github.com/Masterminds/semver/.travis.yml
@@ -1,9 +1,9 @@ language: go go: - - 1.3 - - 1.4 - 1.5 + - 1.6 + - 1.7 - tip # Setting sudo access to false will let Travis CI use containers rather than @@ -12,5 +12,14 @@ # - http://docs.travis-ci.com/user/workers/standard-infrastructure/ sudo: false +script: + - GO15VENDOREXPERIMENT=1 make setup + - GO15VENDOREXPERIMENT=1 make test + notifications: - irc: "irc.freenode.net#masterminds" + webhooks: + urls: + - https://webhooks.gitter.im/e/06e3328629952dabe3e0 + on_success: change # options: [always|never|change] default: always + on_failure: always # options: [always|never|change] default: always + on_start: never # options: [always|never|change] default: always
diff --git a/vendor/github.com/Masterminds/semver/CHANGELOG.md b/vendor/github.com/Masterminds/semver/CHANGELOG.md index c3808ea..237d53a 100644 --- a/vendor/github.com/Masterminds/semver/CHANGELOG.md +++ b/vendor/github.com/Masterminds/semver/CHANGELOG.md
@@ -1,3 +1,27 @@ +# Release 1.2.2 (2016-12-13) + +## Fixed +- #34: Fixed issue where hyphen range was not working with pre-release parsing. + +# Release 1.2.1 (2016-11-28) + +## Fixed +- #24: Fixed edge case issue where constraint "> 0" does not handle "0.0.1-alpha" + properly. + +# Release 1.2.0 (2016-11-04) + +## Added +- #20: Added MustParse function for versions (thanks @adamreese) +- #15: Added increment methods on versions (thanks @mh-cbon) + +## Fixed +- Issue #21: Per the SemVer spec (section 9) a pre-release is unstable and + might not satisfy the intended compatibility. The change here ignores pre-releases + on constraint checks (e.g., ~ or ^) when a pre-release is not part of the + constraint. For example, `^1.2.3` will ignore pre-releases while + `^1.2.3-alpha` will include them. + # Release 1.1.1 (2016-06-30) ## Changed
diff --git a/vendor/github.com/Masterminds/semver/Makefile b/vendor/github.com/Masterminds/semver/Makefile new file mode 100644 index 0000000..a7a1b4e --- /dev/null +++ b/vendor/github.com/Masterminds/semver/Makefile
@@ -0,0 +1,36 @@ +.PHONY: setup +setup: + go get -u gopkg.in/alecthomas/gometalinter.v1 + gometalinter.v1 --install + +.PHONY: test +test: validate lint + @echo "==> Running tests" + go test -v + +.PHONY: validate +validate: + @echo "==> Running static validations" + @gometalinter.v1 \ + --disable-all \ + --enable deadcode \ + --severity deadcode:error \ + --enable gofmt \ + --enable gosimple \ + --enable ineffassign \ + --enable misspell \ + --enable vet \ + --tests \ + --vendor \ + --deadline 60s \ + ./... || exit_code=1 + +.PHONY: lint +lint: + @echo "==> Running linters" + @gometalinter.v1 \ + --disable-all \ + --enable golint \ + --vendor \ + --deadline 60s \ + ./... || :
diff --git a/vendor/github.com/Masterminds/semver/README.md b/vendor/github.com/Masterminds/semver/README.md index 1edec7a..9a9ed45 100644 --- a/vendor/github.com/Masterminds/semver/README.md +++ b/vendor/github.com/Masterminds/semver/README.md
@@ -78,6 +78,15 @@ * `>=`: greater than or equal to * `<=`: less than or equal to +_Note, according to the Semantic Version specification pre-releases may not be +API compliant with their release counterpart. It says,_ + +> _A pre-release version indicates that the version is unstable and might not satisfy the intended compatibility requirements as denoted by its associated normal version._ + +_SemVer comparisons without a pre-release value will skip pre-release versions. +For example, `>1.2.3` will skip pre-releases when looking at a list of values +while `>1.2.3-alpha.1` will evaluate pre-releases._ + ## Hyphen Range Comparisons There are multiple methods to handle ranges and the first is hyphens ranges.
diff --git a/vendor/github.com/Masterminds/semver/appveyor.yml b/vendor/github.com/Masterminds/semver/appveyor.yml index cf7801b..b2778df 100644 --- a/vendor/github.com/Masterminds/semver/appveyor.yml +++ b/vendor/github.com/Masterminds/semver/appveyor.yml
@@ -12,11 +12,33 @@ install: - go version - go env + - go get -u gopkg.in/alecthomas/gometalinter.v1 + - set PATH=%PATH%;%GOPATH%\bin + - gometalinter.v1.exe --install build_script: - go install -v ./... test_script: + - "gometalinter.v1 \ + --disable-all \ + --enable deadcode \ + --severity deadcode:error \ + --enable gofmt \ + --enable gosimple \ + --enable ineffassign \ + --enable misspell \ + --enable vet \ + --tests \ + --vendor \ + --deadline 60s \ + ./... || exit_code=1" + - "gometalinter.v1 \ + --disable-all \ + --enable golint \ + --vendor \ + --deadline 60s \ + ./... || :" - go test -v deploy: off
diff --git a/vendor/github.com/Masterminds/semver/constraints.go b/vendor/github.com/Masterminds/semver/constraints.go index b63f5f6..4c4fac3 100644 --- a/vendor/github.com/Masterminds/semver/constraints.go +++ b/vendor/github.com/Masterminds/semver/constraints.go
@@ -129,7 +129,7 @@ cvRegex)) constraintRangeRegex = regexp.MustCompile(fmt.Sprintf( - `\s*(%s)\s*-\s*(%s)\s*`, + `\s*(%s)\s+-\s+(%s)\s*`, cvRegex, cvRegex)) } @@ -204,6 +204,14 @@ // Constraint functions func constraintNotEqual(v *Version, c *constraint) bool { if c.dirty { + + // If there is a pre-release on the version but the constraint isn't looking + // for them assume that pre-releases are not compatible. See issue 21 for + // more details. + if v.Prerelease() != "" && c.con.Prerelease() == "" { + return false + } + if c.con.Major() != v.Major() { return true } @@ -220,10 +228,31 @@ } func constraintGreaterThan(v *Version, c *constraint) bool { + + // An edge case the constraint is 0.0.0 and the version is 0.0.0-someprerelease + // exists. This that case. + if !isNonZero(c.con) && isNonZero(v) { + return true + } + + // If there is a pre-release on the version but the constraint isn't looking + // for them assume that pre-releases are not compatible. See issue 21 for + // more details. + if v.Prerelease() != "" && c.con.Prerelease() == "" { + return false + } + return v.Compare(c.con) == 1 } func constraintLessThan(v *Version, c *constraint) bool { + // If there is a pre-release on the version but the constraint isn't looking + // for them assume that pre-releases are not compatible. See issue 21 for + // more details. + if v.Prerelease() != "" && c.con.Prerelease() == "" { + return false + } + if !c.dirty { return v.Compare(c.con) < 0 } @@ -238,10 +267,30 @@ } func constraintGreaterThanEqual(v *Version, c *constraint) bool { + // An edge case the constraint is 0.0.0 and the version is 0.0.0-someprerelease + // exists. This that case. + if !isNonZero(c.con) && isNonZero(v) { + return true + } + + // If there is a pre-release on the version but the constraint isn't looking + // for them assume that pre-releases are not compatible. See issue 21 for + // more details. + if v.Prerelease() != "" && c.con.Prerelease() == "" { + return false + } + return v.Compare(c.con) >= 0 } func constraintLessThanEqual(v *Version, c *constraint) bool { + // If there is a pre-release on the version but the constraint isn't looking + // for them assume that pre-releases are not compatible. See issue 21 for + // more details. + if v.Prerelease() != "" && c.con.Prerelease() == "" { + return false + } + if !c.dirty { return v.Compare(c.con) <= 0 } @@ -262,6 +311,13 @@ // ~1.2.3, ~>1.2.3 --> >=1.2.3, <1.3.0 // ~1.2.0, ~>1.2.0 --> >=1.2.0, <1.3.0 func constraintTilde(v *Version, c *constraint) bool { + // If there is a pre-release on the version but the constraint isn't looking + // for them assume that pre-releases are not compatible. See issue 21 for + // more details. + if v.Prerelease() != "" && c.con.Prerelease() == "" { + return false + } + if v.LessThan(c.con) { return false } @@ -286,6 +342,13 @@ // When there is a .x (dirty) status it automatically opts in to ~. Otherwise // it's a straight = func constraintTildeOrEqual(v *Version, c *constraint) bool { + // If there is a pre-release on the version but the constraint isn't looking + // for them assume that pre-releases are not compatible. See issue 21 for + // more details. + if v.Prerelease() != "" && c.con.Prerelease() == "" { + return false + } + if c.dirty { c.msg = constraintMsg["~"] return constraintTilde(v, c) @@ -301,6 +364,13 @@ // ^1.2.3 --> >=1.2.3, <2.0.0 // ^1.2.0 --> >=1.2.0, <2.0.0 func constraintCaret(v *Version, c *constraint) bool { + // If there is a pre-release on the version but the constraint isn't looking + // for them assume that pre-releases are not compatible. See issue 21 for + // more details. + if v.Prerelease() != "" && c.con.Prerelease() == "" { + return false + } + if v.LessThan(c.con) { return false } @@ -340,3 +410,12 @@ return o } + +// Detect if a version is not zero (0.0.0) +func isNonZero(v *Version) bool { + if v.Major() != 0 || v.Minor() != 0 || v.Patch() != 0 || v.Prerelease() != "" { + return true + } + + return false +}
diff --git a/vendor/github.com/Masterminds/semver/constraints_test.go b/vendor/github.com/Masterminds/semver/constraints_test.go index 6dad455..5910622 100644 --- a/vendor/github.com/Masterminds/semver/constraints_test.go +++ b/vendor/github.com/Masterminds/semver/constraints_test.go
@@ -72,6 +72,10 @@ {"<=1.1", "0.1.0", true}, {"<=1.1", "1.1.0", true}, {"<=1.1", "1.1.1", false}, + {">0", "0.0.1-alpha", true}, + {">=0", "0.0.1-alpha", true}, + {">0", "0", false}, + {">=0", "0", true}, } for _, tc := range tests { @@ -89,7 +93,7 @@ a := c.check(v) if a != tc.check { - t.Errorf("Constraint '%s' failing", tc.constraint) + t.Errorf("Constraint %q failing with %q", tc.constraint, tc.version) } } } @@ -103,12 +107,13 @@ }{ {">= 1.1", 1, 1, false}, {"2.0", 1, 1, false}, + {"v2.3.5-20161202202307-sha.e8fc5e5", 1, 1, false}, {">= bar", 0, 0, true}, {">= 1.2.3, < 2.0", 1, 2, false}, {">= 1.2.3, < 2.0 || => 3.0, < 4", 2, 2, false}, - // The 3-4 should be broken into 2 by the range rewriting - {"3-4 || => 3.0, < 4", 2, 2, false}, + // The 3 - 4 should be broken into 2 by the range rewriting + {"3 - 4 || => 3.0, < 4", 2, 2, false}, } for _, tc := range tests { @@ -152,6 +157,8 @@ {"4.1.x", "4.1.3", true}, {"1.x", "1.4", true}, {"!=4.1", "4.1.0", false}, + {"!=4.1-alpha", "4.1.0-alpha", false}, + {"!=4.1-alpha", "4.1.0", true}, {"!=4.1", "5.1.0", true}, {"!=4.x", "5.1.0", true}, {"!=4.x", "4.1.0", false}, @@ -168,9 +175,12 @@ {"<1.1.x", "1.1.500", true}, {"<1.2.x", "1.1.1", true}, {">=1.1", "4.1.0", true}, + {">=1.1", "4.1.0-beta", false}, {">=1.1", "1.1.0", true}, {">=1.1", "0.0.9", false}, {"<=1.1", "0.1.0", true}, + {"<=1.1", "0.1.0-alpha", false}, + {"<=1.1-a", "0.1.0-alpha", true}, {"<=1.1", "1.1.0", true}, {"<=1.x", "1.1.0", true}, {"<=2.x", "3.1.0", false}, @@ -190,11 +200,18 @@ {"^1.x", "1.1.1", true}, {"^2.x", "1.1.1", false}, {"^1.x", "2.1.1", false}, + {"^1.x", "1.1.1-beta1", false}, + {"^1.1.2-alpha", "1.2.1-beta1", true}, + {"^1.2.x-alpha", "1.1.1-beta1", false}, {"~*", "2.1.1", true}, {"~1.x", "2.1.1", false}, {"~1.x", "1.3.5", true}, {"~1.x", "1.4", true}, {"~1.1", "1.1.1", true}, + {"~1.1", "1.1.1-alpha", false}, + {"~1.1-alpha", "1.1.1-beta", true}, + {"~1.1.1-beta", "1.1.1-alpha", false}, + {"~1.1.1-beta", "1.1.1", true}, {"~1.2.3", "1.2.5", true}, {"~1.2.3", "1.2.2", false}, {"~1.2.3", "1.3.2", false}, @@ -227,9 +244,9 @@ c string nc string }{ - {"2-3", ">= 2, <= 3"}, - {"2-3, 2-3", ">= 2, <= 3,>= 2, <= 3"}, - {"2-3, 4.0.0-5.1", ">= 2, <= 3,>= 4.0.0, <= 5.1"}, + {"2 - 3", ">= 2, <= 3"}, + {"2 - 3, 2 - 3", ">= 2, <= 3,>= 2, <= 3"}, + {"2 - 3, 4.0.0 - 5.1", ">= 2, <= 3,>= 4.0.0, <= 5.1"}, } for _, tc := range tests { @@ -309,6 +326,9 @@ {"1.1 - 2", "1.1.1", true}, {"1.1-3", "4.3.2", false}, {"^1.1", "1.1.1", true}, + {"^1.1", "1.1.1-alpha", false}, + {"^1.1.1-alpha", "1.1.1-beta", true}, + {"^1.1.1-beta", "1.1.1-alpha", false}, {"^1.1", "4.3.2", false}, {"^1.x", "1.1.1", true}, {"^2.x", "1.1.1", false}, @@ -316,6 +336,10 @@ {"~*", "2.1.1", true}, {"~1.x", "2.1.1", false}, {"~1.x", "1.3.5", true}, + {"~1.x", "1.3.5-beta", false}, + {"~1.3.6-alpha", "1.3.5-beta", false}, + {"~1.3.5-alpha", "1.3.5-beta", true}, + {"~1.3.5-beta", "1.3.5-alpha", false}, {"~1.x", "1.4", true}, {"~1.1", "1.1.1", true}, {"~1.2.3", "1.2.5", true}, @@ -341,7 +365,7 @@ a, msgs := c.Validate(v) if a != tc.check { t.Errorf("Constraint '%s' failing with '%s'", tc.constraint, tc.version) - } else if a == false && len(msgs) == 0 { + } else if !a && len(msgs) == 0 { t.Errorf("%q failed with %q but no errors returned", tc.constraint, tc.version) } @@ -395,7 +419,7 @@ {">=1.1, <2, !=1.2.3", "1.2.3", "1.2.3 is equal to 1.2.3"}, {">=1.1, <2, !=1.2.3 || > 3", "3.0.0", "3.0.0 is greater than or equal to 2"}, {">=1.1, <2, !=1.2.3 || > 3", "1.2.3", "1.2.3 is equal to 1.2.3"}, - {"1.1-3", "4.3.2", "4.3.2 is greater than 3"}, + {"1.1 - 3", "4.3.2", "4.3.2 is greater than 3"}, {"^1.1", "4.3.2", "4.3.2 does not have same major version as 1.1"}, {"^2.x", "1.1.1", "1.1.1 does not have same major version as 2.x"}, {"^1.x", "2.1.1", "2.1.1 does not have same major version as 1.x"},
diff --git a/vendor/github.com/Masterminds/semver/version.go b/vendor/github.com/Masterminds/semver/version.go index dbb93f8..28b26ac 100644 --- a/vendor/github.com/Masterminds/semver/version.go +++ b/vendor/github.com/Masterminds/semver/version.go
@@ -12,18 +12,29 @@ // The compiled version of the regex created at init() is cached here so it // only needs to be created once. var versionRegex *regexp.Regexp +var validPrereleaseRegex *regexp.Regexp var ( // ErrInvalidSemVer is returned a version is found to be invalid when // being parsed. ErrInvalidSemVer = errors.New("Invalid Semantic Version") + + // ErrInvalidMetadata is returned when the metadata is an invalid format + ErrInvalidMetadata = errors.New("Invalid Metadata string") + + // ErrInvalidPrerelease is returned when the pre-release is an invalid format + ErrInvalidPrerelease = errors.New("Invalid Prerelease string") ) -// SemVerRegex id the regular expression used to parse a semantic version. +// SemVerRegex is the regular expression used to parse a semantic version. const SemVerRegex string = `v?([0-9]+)(\.[0-9]+)?(\.[0-9]+)?` + `(-([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?` + `(\+([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?` +// ValidPrerelease is the regular expression which validates +// both prerelease and metadata values. +const ValidPrerelease string = `^([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*)` + // Version represents a single semantic version. type Version struct { major, minor, patch int64 @@ -34,6 +45,7 @@ func init() { versionRegex = regexp.MustCompile("^" + SemVerRegex + "$") + validPrereleaseRegex = regexp.MustCompile(ValidPrerelease) } // NewVersion parses a given version and returns an instance of Version or @@ -80,6 +92,15 @@ return sv, nil } +// MustParse parses a given version and panics on error. +func MustParse(v string) *Version { + sv, err := NewVersion(v) + if err != nil { + panic(err) + } + return sv +} + // String converts a Version object to a string. // Note, if the original version contained a leading v this version will not. // See the Original() method to retrieve the original value. Semantic Versions @@ -129,6 +150,95 @@ return v.metadata } +// originalVPrefix returns the original 'v' prefix if any. +func (v *Version) originalVPrefix() string { + + // Note, only lowercase v is supported as a prefix by the parser. + if v.original != "" && v.original[:1] == "v" { + return v.original[:1] + } + return "" +} + +// IncPatch produces the next patch version. +// If the current version does not have prerelease/metadata information, +// it unsets metadata and prerelease values, increments patch number. +// If the current version has any of prerelease or metadata information, +// it unsets both values and keeps curent patch value +func (v Version) IncPatch() Version { + vNext := v + // according to http://semver.org/#spec-item-9 + // Pre-release versions have a lower precedence than the associated normal version. + // according to http://semver.org/#spec-item-10 + // Build metadata SHOULD be ignored when determining version precedence. + if v.pre != "" { + vNext.metadata = "" + vNext.pre = "" + } else { + vNext.metadata = "" + vNext.pre = "" + vNext.patch = v.patch + 1 + } + vNext.original = v.originalVPrefix() + "" + vNext.String() + return vNext +} + +// IncMinor produces the next minor version. +// Sets patch to 0. +// Increments minor number. +// Unsets metadata. +// Unsets prerelease status. +func (v Version) IncMinor() Version { + vNext := v + vNext.metadata = "" + vNext.pre = "" + vNext.patch = 0 + vNext.minor = v.minor + 1 + vNext.original = v.originalVPrefix() + "" + vNext.String() + return vNext +} + +// IncMajor produces the next major version. +// Sets patch to 0. +// Sets minor to 0. +// Increments major number. +// Unsets metadata. +// Unsets prerelease status. +func (v Version) IncMajor() Version { + vNext := v + vNext.metadata = "" + vNext.pre = "" + vNext.patch = 0 + vNext.minor = 0 + vNext.major = v.major + 1 + vNext.original = v.originalVPrefix() + "" + vNext.String() + return vNext +} + +// SetPrerelease defines the prerelease value. +// Value must not include the required 'hypen' prefix. +func (v Version) SetPrerelease(prerelease string) (Version, error) { + vNext := v + if len(prerelease) > 0 && !validPrereleaseRegex.MatchString(prerelease) { + return vNext, ErrInvalidPrerelease + } + vNext.pre = prerelease + vNext.original = v.originalVPrefix() + "" + vNext.String() + return vNext, nil +} + +// SetMetadata defines metadata value. +// Value must not include the required 'plus' prefix. +func (v Version) SetMetadata(metadata string) (Version, error) { + vNext := v + if len(metadata) > 0 && !validPrereleaseRegex.MatchString(metadata) { + return vNext, ErrInvalidMetadata + } + vNext.metadata = metadata + vNext.original = v.originalVPrefix() + "" + vNext.String() + return vNext, nil +} + // LessThan tests if one version is less than another one. func (v *Version) LessThan(o *Version) bool { return v.Compare(o) < 0
diff --git a/vendor/github.com/Masterminds/semver/version_test.go b/vendor/github.com/Masterminds/semver/version_test.go index e8ad413..0e02a6a 100644 --- a/vendor/github.com/Masterminds/semver/version_test.go +++ b/vendor/github.com/Masterminds/semver/version_test.go
@@ -281,3 +281,170 @@ } } } + +func TestInc(t *testing.T) { + tests := []struct { + v1 string + expected string + how string + expectedOriginal string + }{ + {"1.2.3", "1.2.4", "patch", "1.2.4"}, + {"v1.2.4", "1.2.5", "patch", "v1.2.5"}, + {"1.2.3", "1.3.0", "minor", "1.3.0"}, + {"v1.2.4", "1.3.0", "minor", "v1.3.0"}, + {"1.2.3", "2.0.0", "major", "2.0.0"}, + {"v1.2.4", "2.0.0", "major", "v2.0.0"}, + {"1.2.3+meta", "1.2.4", "patch", "1.2.4"}, + {"1.2.3-beta+meta", "1.2.3", "patch", "1.2.3"}, + {"v1.2.4-beta+meta", "1.2.4", "patch", "v1.2.4"}, + {"1.2.3-beta+meta", "1.3.0", "minor", "1.3.0"}, + {"v1.2.4-beta+meta", "1.3.0", "minor", "v1.3.0"}, + {"1.2.3-beta+meta", "2.0.0", "major", "2.0.0"}, + {"v1.2.4-beta+meta", "2.0.0", "major", "v2.0.0"}, + } + + for _, tc := range tests { + v1, err := NewVersion(tc.v1) + if err != nil { + t.Errorf("Error parsing version: %s", err) + } + + var v2 Version + switch tc.how { + case "patch": + v2 = v1.IncPatch() + case "minor": + v2 = v1.IncMinor() + case "major": + v2 = v1.IncMajor() + } + + a := v2.String() + e := tc.expected + if a != e { + t.Errorf( + "Inc %q failed. Expected %q got %q", + tc.how, e, a, + ) + } + + a = v2.Original() + e = tc.expectedOriginal + if a != e { + t.Errorf( + "Inc %q failed. Expected original %q got %q", + tc.how, e, a, + ) + } + } +} + +func TestSetPrerelease(t *testing.T) { + tests := []struct { + v1 string + prerelease string + expectedVersion string + expectedPrerelease string + expectedOriginal string + expectedErr error + }{ + {"1.2.3", "**", "1.2.3", "", "1.2.3", ErrInvalidPrerelease}, + {"1.2.3", "beta", "1.2.3-beta", "beta", "1.2.3-beta", nil}, + {"v1.2.4", "beta", "1.2.4-beta", "beta", "v1.2.4-beta", nil}, + } + + for _, tc := range tests { + v1, err := NewVersion(tc.v1) + if err != nil { + t.Errorf("Error parsing version: %s", err) + } + + v2, err := v1.SetPrerelease(tc.prerelease) + if err != tc.expectedErr { + t.Errorf("Expected to get err=%s, but got err=%s", tc.expectedErr, err) + } + + a := v2.Prerelease() + e := tc.expectedPrerelease + if a != e { + t.Errorf("Expected prerelease value=%q, but got %q", e, a) + } + + a = v2.String() + e = tc.expectedVersion + if a != e { + t.Errorf("Expected version string=%q, but got %q", e, a) + } + + a = v2.Original() + e = tc.expectedOriginal + if a != e { + t.Errorf("Expected version original=%q, but got %q", e, a) + } + } +} + +func TestSetMetadata(t *testing.T) { + tests := []struct { + v1 string + metadata string + expectedVersion string + expectedMetadata string + expectedOriginal string + expectedErr error + }{ + {"1.2.3", "**", "1.2.3", "", "1.2.3", ErrInvalidMetadata}, + {"1.2.3", "meta", "1.2.3+meta", "meta", "1.2.3+meta", nil}, + {"v1.2.4", "meta", "1.2.4+meta", "meta", "v1.2.4+meta", nil}, + } + + for _, tc := range tests { + v1, err := NewVersion(tc.v1) + if err != nil { + t.Errorf("Error parsing version: %s", err) + } + + v2, err := v1.SetMetadata(tc.metadata) + if err != tc.expectedErr { + t.Errorf("Expected to get err=%s, but got err=%s", tc.expectedErr, err) + } + + a := v2.Metadata() + e := tc.expectedMetadata + if a != e { + t.Errorf("Expected metadata value=%q, but got %q", e, a) + } + + a = v2.String() + e = tc.expectedVersion + if e != a { + t.Errorf("Expected version string=%q, but got %q", e, a) + } + + a = v2.Original() + e = tc.expectedOriginal + if a != e { + t.Errorf("Expected version original=%q, but got %q", e, a) + } + } +} + +func TestOriginalVPrefix(t *testing.T) { + tests := []struct { + version string + vprefix string + }{ + {"1.2.3", ""}, + {"v1.2.4", "v"}, + } + + for _, tc := range tests { + v1, _ := NewVersion(tc.version) + a := v1.originalVPrefix() + e := tc.vprefix + if a != e { + t.Errorf("Expected vprefix=%q, but got %q", e, a) + } + } +}
diff --git a/vendor/github.com/Masterminds/vcs/.travis.yml b/vendor/github.com/Masterminds/vcs/.travis.yml index 5c50c4a..b14aeb8 100644 --- a/vendor/github.com/Masterminds/vcs/.travis.yml +++ b/vendor/github.com/Masterminds/vcs/.travis.yml
@@ -1,10 +1,9 @@ language: go go: - - 1.3 - - 1.4 - 1.5 - 1.6 + - 1.7 - tip before_script: @@ -17,6 +16,10 @@ # - http://docs.travis-ci.com/user/workers/standard-infrastructure/ sudo: false +script: + - GO15VENDOREXPERIMENT=1 make setup + - GO15VENDOREXPERIMENT=1 make test + notifications: webhooks: urls:
diff --git a/vendor/github.com/Masterminds/vcs/CHANGELOG.md b/vendor/github.com/Masterminds/vcs/CHANGELOG.md index 6362674..4379d3f 100644 --- a/vendor/github.com/Masterminds/vcs/CHANGELOG.md +++ b/vendor/github.com/Masterminds/vcs/CHANGELOG.md
@@ -1,3 +1,22 @@ +# 1.10.0 (2017-01-09) + +## Added +- #60: Handle Git submodules (thanks @sdboyer) +- #61: Add gometalinter to testing + +# 1.9.0 (2016-11-18) + +## Added +- #50: Auto-detect remotes with file:// prefix. +- #59: Testing against Go 1.7 + +## Changed +- Removed auto-detection for Google Code as the service is deprecated +- Added auto-detection of git.openstack.org + +## Fixed +- #53: Git not fetching tags off branch + # 1.8.0 (2016-06-29) ## Added
diff --git a/vendor/github.com/Masterminds/vcs/Makefile b/vendor/github.com/Masterminds/vcs/Makefile new file mode 100644 index 0000000..5d722c2 --- /dev/null +++ b/vendor/github.com/Masterminds/vcs/Makefile
@@ -0,0 +1,41 @@ +.PHONY: setup +setup: + go get -u gopkg.in/alecthomas/gometalinter.v1 + gometalinter.v1 --install + +.PHONY: test +test: validate lint + @echo "==> Running tests" + go test -v + +.PHONY: validate +validate: +# misspell finds the work adresáÅ™ (used in bzr.go) as a mispelling of +# address. It finds adres. An issue has been filed at +# https://github.com/client9/misspell/issues/99. In the meantime adding +# adres to the ignore list. + @echo "==> Running static validations" + @gometalinter.v1 \ + --disable-all \ + --linter "misspell:misspell -i adres -j 1 {path}/*.go:PATH:LINE:COL:MESSAGE" \ + --enable deadcode \ + --severity deadcode:error \ + --enable gofmt \ + --enable gosimple \ + --enable ineffassign \ + --enable misspell \ + --enable vet \ + --tests \ + --vendor \ + --deadline 60s \ + ./... || exit_code=1 + +.PHONY: lint +lint: + @echo "==> Running linters" + @gometalinter.v1 \ + --disable-all \ + --enable golint \ + --vendor \ + --deadline 60s \ + ./... || :
diff --git a/vendor/github.com/Masterminds/vcs/bzr.go b/vendor/github.com/Masterminds/vcs/bzr.go index e8f55b6..8343d3c 100644 --- a/vendor/github.com/Masterminds/vcs/bzr.go +++ b/vendor/github.com/Masterminds/vcs/bzr.go
@@ -39,7 +39,7 @@ // http://bazaar.launchpad.net/~mattfarina/govcstestbzrrepo/trunk/. Notice // the change from https to http and the path chance. // Here we set the remote to be the local one if none is passed in. - if err == nil && r.CheckLocal() == true && remote == "" { + if err == nil && r.CheckLocal() && remote == "" { c := exec.Command("bzr", "info") c.Dir = local c.Env = envForDir(c.Dir) @@ -226,11 +226,7 @@ // commit id or tag. func (s *BzrRepo) IsReference(r string) bool { _, err := s.RunFromDir("bzr", "revno", "-r", r) - if err == nil { - return true - } - - return false + return err == nil } // IsDirty returns if the checkout has been modified from the checked @@ -308,21 +304,14 @@ // an error is returned. Launchpad returns a 404 for a codebase that // does not exist. Otherwise it returns a JSON object describing it. _, er := get("https://api.launchpad.net/1.0/" + try) - if er == nil { - return true - } - return false + return er == nil } } // This is the same command that Go itself uses but it's not fast (or fast // enough by my standards). A faster method would be useful. _, err = s.run("bzr", "info", s.Remote()) - if err != nil { - return false - } - - return true + return err == nil } // ExportDir exports the current revision to the passed in directory. @@ -340,6 +329,7 @@ // https://bazaar.launchpad.net/~bzr-pqm/bzr/bzr.dev/files/head:/po/ func (s *BzrRepo) isUnableToCreateDir(err error) bool { msg := err.Error() + if strings.HasPrefix(msg, fmt.Sprintf("Parent directory of %s does not exist.", s.LocalPath())) || strings.HasPrefix(msg, fmt.Sprintf("NadÅ™azený adresáÅ™ %s neexistuje.", s.LocalPath())) || strings.HasPrefix(msg, fmt.Sprintf("El directorio padre de %s no existe.", s.LocalPath())) ||
diff --git a/vendor/github.com/Masterminds/vcs/bzr_test.go b/vendor/github.com/Masterminds/vcs/bzr_test.go index e12c6d3..385fd18 100644 --- a/vendor/github.com/Masterminds/vcs/bzr_test.go +++ b/vendor/github.com/Masterminds/vcs/bzr_test.go
@@ -55,7 +55,7 @@ } // Verify Bzr repo is a Bzr repo - if repo.CheckLocal() == false { + if !repo.CheckLocal() { t.Error("Problem checking out repo or Bzr CheckLocal is not working") } @@ -75,7 +75,7 @@ t.Error(nrerr) } // Verify the right oject is returned. It will check the local repo type. - if nrepo.CheckLocal() == false { + if !nrepo.CheckLocal() { t.Error("Wrong version returned from NewRepo") } @@ -164,15 +164,15 @@ t.Error("Bzr is incorrectly returning branches") } - if repo.IsReference("1.0.0") != true { + if !repo.IsReference("1.0.0") { t.Error("Bzr is reporting a reference is not one") } - if repo.IsReference("foo") == true { - t.Error("Bzr is reporting a non-existant reference is one") + if repo.IsReference("foo") { + t.Error("Bzr is reporting a non-existent reference is one") } - if repo.IsDirty() == true { + if repo.IsDirty() { t.Error("Bzr incorrectly reporting dirty") } @@ -227,7 +227,7 @@ _, err = os.Stat(filepath.Join(exportDir, string(repo.Vcs()))) if err != nil { - if found := os.IsNotExist(err); found == false { + if found := os.IsNotExist(err); !found { t.Errorf("Error checking exported metadata in Bzr: %s", err) } } else { @@ -250,7 +250,7 @@ }() repo, _ := NewBzrRepo("", tempDir) - if repo.CheckLocal() == true { + if repo.CheckLocal() { t.Error("Bzr CheckLocal does not identify non-Bzr location") }
diff --git a/vendor/github.com/Masterminds/vcs/errors.go b/vendor/github.com/Masterminds/vcs/errors.go index ea8c5fc..be70970 100644 --- a/vendor/github.com/Masterminds/vcs/errors.go +++ b/vendor/github.com/Masterminds/vcs/errors.go
@@ -5,7 +5,7 @@ // The vcs package provides ways to work with errors that hide the underlying // implementation details but make them accessible if needed. For basic errors // that do not have underlying implementation specific details or the underlying -// details are likely not necessairy there are errors for comparison. +// details are not necessary there are errors for comparison. // // For example: //
diff --git a/vendor/github.com/Masterminds/vcs/git.go b/vendor/github.com/Masterminds/vcs/git.go index eb4b86e..dcf6278 100644 --- a/vendor/github.com/Masterminds/vcs/git.go +++ b/vendor/github.com/Masterminds/vcs/git.go
@@ -33,7 +33,7 @@ // Make sure the local Git repo is configured the same as the remote when // A remote value was passed in. - if err == nil && r.CheckLocal() == true { + if err == nil && r.CheckLocal() { c := exec.Command("git", "config", "--get", "remote.origin.url") c.Dir = local c.Env = envForDir(c.Dir) @@ -70,7 +70,7 @@ // Get is used to perform an initial clone of a repository. func (s *GitRepo) Get() error { - out, err := s.run("git", "clone", s.Remote(), s.LocalPath()) + out, err := s.run("git", "clone", "--recursive", s.Remote(), s.LocalPath()) // There are some windows cases where Git cannot create the parent directory, // if it does not already exist, to the location it's trying to create the @@ -131,7 +131,7 @@ // Update performs an Git fetch and pull to an existing checkout. func (s *GitRepo) Update() error { // Perform a fetch to make sure everything is up to date. - out, err := s.RunFromDir("git", "fetch", s.RemoteLocation) + out, err := s.RunFromDir("git", "fetch", "--tags", s.RemoteLocation) if err != nil { return NewRemoteError("Unable to update repository", err, string(out)) } @@ -143,7 +143,7 @@ return NewLocalError("Unable to update repository", err, "") } - if detached == true { + if detached { return nil } @@ -151,7 +151,8 @@ if err != nil { return NewRemoteError("Unable to update repository", err, string(out)) } - return nil + + return s.defendAgainstSubmodules() } // UpdateVersion sets the version of a package currently checked out via Git. @@ -160,6 +161,30 @@ if err != nil { return NewLocalError("Unable to update checked out version", err, string(out)) } + + return s.defendAgainstSubmodules() +} + +// defendAgainstSubmodules tries to keep repo state sane in the event of +// submodules. Or nested submodules. What a great idea, submodules. +func (s *GitRepo) defendAgainstSubmodules() error { + // First, update them to whatever they should be, if there should happen to be any. + out, err := s.RunFromDir("git", "submodule", "update", "--init", "--recursive") + if err != nil { + return NewLocalError("Unexpected error while defensively updating submodules", err, string(out)) + } + // Now, do a special extra-aggressive clean in case changing versions caused + // one or more submodules to go away. + out, err = s.RunFromDir("git", "clean", "-x", "-d", "-f", "-f") + if err != nil { + return NewLocalError("Unexpected error while defensively cleaning up after possible derelict submodule directories", err, string(out)) + } + // Then, repeat just in case there are any nested submodules that went away. + out, err = s.RunFromDir("git", "submodule", "foreach", "--recursive", "git", "clean", "-x", "-d", "-f", "-f") + if err != nil { + return NewLocalError("Unexpected error while defensively cleaning up after possible derelict nested submodule directories", err, string(out)) + } + return nil } @@ -255,11 +280,7 @@ // not been checked out yet. This next step should pickup the other // possible references. _, err = s.RunFromDir("git", "show-ref", r) - if err == nil { - return true - } - - return false + return err == nil } // IsDirty returns if the checkout has been modified from the checked @@ -339,11 +360,7 @@ // remote needs to be different. c.Env = mergeEnvLists([]string{"GIT_TERMINAL_PROMPT=0"}, os.Environ()) _, err := c.CombinedOutput() - if err != nil { - return false - } - - return true + return err == nil } // ExportDir exports the current revision to the passed in directory. @@ -359,6 +376,12 @@ if err != nil { return NewLocalError("Unable to export source", err, string(out)) } + // and now, the horror of submodules + out, err = s.RunFromDir("git", "submodule", "foreach", "--recursive", "'git checkout-index -f -a --prefix=\""+filepath.Join(dir, "$path")+"\"'") + s.log(out) + if err != nil { + return NewLocalError("Error while exporting submodule sources", err, string(out)) + } return nil }
diff --git a/vendor/github.com/Masterminds/vcs/git_test.go b/vendor/github.com/Masterminds/vcs/git_test.go index 80eae55..7c6e093 100644 --- a/vendor/github.com/Masterminds/vcs/git_test.go +++ b/vendor/github.com/Masterminds/vcs/git_test.go
@@ -1,6 +1,7 @@ package vcs import ( + "fmt" "io/ioutil" "path/filepath" "time" @@ -53,7 +54,7 @@ } // Verify Git repo is a Git repo - if repo.CheckLocal() == false { + if !repo.CheckLocal() { t.Error("Problem checking out repo or Git CheckLocal is not working") } @@ -73,7 +74,7 @@ t.Error(nrerr) } // Verify the right oject is returned. It will check the local repo type. - if nrepo.CheckLocal() == false { + if !nrepo.CheckLocal() { t.Error("Wrong version returned from NewRepo") } @@ -153,8 +154,23 @@ if err != nil { t.Error(err) } - if tags[0] != "1.0.0" { - t.Error("Git tags is not reporting the correct version") + + var hasRelTag bool + var hasOffMasterTag bool + + for _, tv := range tags { + if tv == "1.0.0" { + hasRelTag = true + } else if tv == "off-master-tag" { + hasOffMasterTag = true + } + } + + if !hasRelTag { + t.Error("Git tags unable to find release tag on master") + } + if !hasOffMasterTag { + t.Error("Git tags did not fetch tags not on master") } tags, err = repo.TagsFromCommit("74dd547545b7df4aa285bcec1b54e2b76f726395") @@ -177,20 +193,20 @@ if err != nil { t.Error(err) } - // The branches should be HEAD, master, and test. - if branches[2] != "test" { + // The branches should be HEAD, master, other, and test. + if branches[3] != "test" { t.Error("Git is incorrectly returning branches") } - if repo.IsReference("1.0.0") != true { + if !repo.IsReference("1.0.0") { t.Error("Git is reporting a reference is not one") } - if repo.IsReference("foo") == true { - t.Error("Git is reporting a non-existant reference is one") + if repo.IsReference("foo") { + t.Error("Git is reporting a non-existent reference is one") } - if repo.IsDirty() == true { + if repo.IsDirty() { t.Error("Git incorrectly reporting dirty") } @@ -245,7 +261,7 @@ _, err = os.Stat(filepath.Join(exportDir, string(repo.Vcs()))) if err != nil { - if found := os.IsNotExist(err); found == false { + if found := os.IsNotExist(err); !found { t.Errorf("Error checking exported metadata in Git: %s", err) } } else { @@ -268,7 +284,7 @@ }() repo, _ := NewGitRepo("", tempDir) - if repo.CheckLocal() == true { + if repo.CheckLocal() { t.Error("Git CheckLocal does not identify non-Git location") } @@ -341,3 +357,128 @@ t.Error(err) } } + +func TestGitSubmoduleHandling(t *testing.T) { + tempDir, err := ioutil.TempDir("", "go-vcs-git-submodule-tests") + if err != nil { + t.Fatal(err) + } + defer func() { + err = os.RemoveAll(tempDir) + if err != nil { + t.Error(err) + } + }() + + dumplocal := func(err error) string { + if terr, ok := err.(*LocalError); ok { + return fmt.Sprintf("msg: %s\norig: %s\nout: %s", terr.Error(), terr.Original(), terr.Out()) + } + return err.Error() + } + + subdirExists := func(dir ...string) bool { + _, err := os.Stat(filepath.Join(append([]string{tempDir}, dir...)...)) + return err == nil + } + + // Initial clone should get version with two submodules, each of which have + // their own submodule + repo, err := NewGitRepo("https://github.com/sdboyer/subm", tempDir) + if err != nil { + t.Fatal(dumplocal(err)) + } + err = repo.Get() + if err != nil { + t.Fatalf("unable to clone Git repo. Err was %s", dumplocal(err)) + } + + // Verify we are on the right version. + v, err := repo.Version() + if v != "18e3a5f6fc7f6d577e732e7a5ab2caf990efbf8f" { + t.Fatalf("did not start from expected rev, tests could fail - bailing out (got %s)", v) + } + if err != nil { + t.Fatal(dumplocal(err)) + } + + if !subdirExists("subm1", ".git") { + t.Fatal("subm1 submodule does not exist on initial clone/checkout") + } + if !subdirExists("subm1", "dep-test", ".git") { + t.Fatal("dep-test submodule nested under subm1 does not exist on initial clone/checkout") + } + + if !subdirExists("subm-again", ".git") { + t.Fatal("subm-again submodule does not exist on initial clone/checkout") + } + if !subdirExists("subm-again", "dep-test", ".git") { + t.Fatal("dep-test submodule nested under subm-again does not exist on initial clone/checkout") + } + + // Now switch to version with no submodules, make sure they all go away + err = repo.UpdateVersion("e677f82015f72ac1c8fafa66b5463163b3597af2") + if err != nil { + t.Fatalf("checking out needed version failed with err: %s", dumplocal(err)) + } + + if subdirExists("subm1") { + t.Fatal("checking out version without submodule did not clean up immediate submodules") + } + if subdirExists("subm1", "dep-test") { + t.Fatal("checking out version without submodule did not clean up nested submodules") + } + if subdirExists("subm-again") { + t.Fatal("checking out version without submodule did not clean up immediate submodules") + } + if subdirExists("subm-again", "dep-test") { + t.Fatal("checking out version without submodule did not clean up nested submodules") + } + + err = repo.UpdateVersion("aaf7aa1bc4c3c682cc530eca8f80417088ee8540") + if err != nil { + t.Fatalf("checking out needed version failed with err: %s", dumplocal(err)) + } + + if !subdirExists("subm1", ".git") { + t.Fatal("checking out version with immediate submodule did not set up git subrepo") + } + + err = repo.UpdateVersion("6cc4669af468f3b4f16e7e96275ad01ade5b522f") + if err != nil { + t.Fatalf("checking out needed version failed with err: %s", dumplocal(err)) + } + + if !subdirExists("subm1", "dep-test", ".git") { + t.Fatal("checking out version with nested submodule did not set up nested git subrepo") + } + + err = repo.UpdateVersion("aaf7aa1bc4c3c682cc530eca8f80417088ee8540") + if err != nil { + t.Fatalf("checking out needed version failed with err: %s", dumplocal(err)) + } + + if subdirExists("subm1", "dep-test") { + t.Fatal("rolling back to version without nested submodule did not clean up the nested submodule") + } + + err = repo.UpdateVersion("18e3a5f6fc7f6d577e732e7a5ab2caf990efbf8f") + if err != nil { + t.Fatalf("checking out needed version failed with err: %s", dumplocal(err)) + } + + if !subdirExists("subm1", ".git") { + t.Fatal("subm1 submodule does not exist after switch from other commit") + } + if !subdirExists("subm1", "dep-test", ".git") { + t.Fatal("dep-test submodule nested under subm1 does not exist after switch from other commit") + } + + if !subdirExists("subm-again", ".git") { + t.Fatal("subm-again submodule does not exist after switch from other commit") + } + if !subdirExists("subm-again", "dep-test", ".git") { + t.Fatal("dep-test submodule nested under subm-again does not exist after switch from other commit") + } + +}
diff --git a/vendor/github.com/Masterminds/vcs/hg.go b/vendor/github.com/Masterminds/vcs/hg.go index df41cd6..5000a6d 100644 --- a/vendor/github.com/Masterminds/vcs/hg.go +++ b/vendor/github.com/Masterminds/vcs/hg.go
@@ -32,7 +32,7 @@ // Make sure the local Hg repo is configured the same as the remote when // A remote value was passed in. - if err == nil && r.CheckLocal() == true { + if err == nil && r.CheckLocal() { // An Hg repo was found so test that the URL there matches // the repo passed in here. c := exec.Command("hg", "paths") @@ -207,11 +207,7 @@ // commit id, branch, or tag. func (s *HgRepo) IsReference(r string) bool { _, err := s.RunFromDir("hg", "log", "-r", r) - if err == nil { - return true - } - - return false + return err == nil } // IsDirty returns if the checkout has been modified from the checked @@ -305,11 +301,7 @@ // Ping returns if remote location is accessible. func (s *HgRepo) Ping() bool { _, err := s.run("hg", "identify", s.Remote()) - if err != nil { - return false - } - - return true + return err == nil } // ExportDir exports the current revision to the passed in directory.
diff --git a/vendor/github.com/Masterminds/vcs/hg_test.go b/vendor/github.com/Masterminds/vcs/hg_test.go index b8aa39a..6b19f72 100644 --- a/vendor/github.com/Masterminds/vcs/hg_test.go +++ b/vendor/github.com/Masterminds/vcs/hg_test.go
@@ -55,7 +55,7 @@ } // Verify Hg repo is a Hg repo - if repo.CheckLocal() == false { + if !repo.CheckLocal() { t.Error("Problem checking out repo or Hg CheckLocal is not working") } @@ -75,7 +75,7 @@ t.Error(nrerr) } // Verify the right oject is returned. It will check the local repo type. - if nrepo.CheckLocal() == false { + if !nrepo.CheckLocal() { t.Error("Wrong version returned from NewRepo") } @@ -166,19 +166,19 @@ t.Error("Hg is incorrectly returning branches") } - if repo.IsReference("1.0.0") != true { + if !repo.IsReference("1.0.0") { t.Error("Hg is reporting a reference is not one") } - if repo.IsReference("test") != true { + if !repo.IsReference("test") { t.Error("Hg is reporting a reference is not one") } - if repo.IsReference("foo") == true { - t.Error("Hg is reporting a non-existant reference is one") + if repo.IsReference("foo") { + t.Error("Hg is reporting a non-existent reference is one") } - if repo.IsDirty() == true { + if repo.IsDirty() { t.Error("Hg incorrectly reporting dirty") } @@ -231,7 +231,7 @@ _, err = os.Stat(filepath.Join(exportDir, string(repo.Vcs()))) if err != nil { - if found := os.IsNotExist(err); found == false { + if found := os.IsNotExist(err); !found { t.Errorf("Error checking exported metadata in Hg: %s", err) } } else { @@ -254,7 +254,7 @@ }() repo, _ := NewHgRepo("", tempDir) - if repo.CheckLocal() == true { + if repo.CheckLocal() { t.Error("Hg CheckLocal does not identify non-Hg location") }
diff --git a/vendor/github.com/Masterminds/vcs/repo_test.go b/vendor/github.com/Masterminds/vcs/repo_test.go index d61f6cb..fef0bcb 100644 --- a/vendor/github.com/Masterminds/vcs/repo_test.go +++ b/vendor/github.com/Masterminds/vcs/repo_test.go
@@ -63,12 +63,12 @@ func TestDepInstalled(t *testing.T) { i := depInstalled("git") - if i != true { + if !i { t.Error("depInstalled not finding installed dep.") } i = depInstalled("thisreallyisntinstalled") - if i != false { + if i { t.Error("depInstalled finding not installed dep.") } }
diff --git a/vendor/github.com/Masterminds/vcs/svn.go b/vendor/github.com/Masterminds/vcs/svn.go index 888ae09..895f93e 100644 --- a/vendor/github.com/Masterminds/vcs/svn.go +++ b/vendor/github.com/Masterminds/vcs/svn.go
@@ -33,7 +33,7 @@ // Make sure the local SVN repo is configured the same as the remote when // A remote value was passed in. - if err == nil && r.CheckLocal() == true { + if err == nil && r.CheckLocal() { // An SVN repo was found so test that the URL there matches // the repo passed in here. out, err := exec.Command("svn", "info", local).CombinedOutput() @@ -139,6 +139,9 @@ } out, err := s.RunFromDir("svn", "info", "--xml") + if err != nil { + return "", NewLocalError("Unable to retrieve checked out version", err, string(out)) + } s.log(out) infos := &Info{} err = xml.Unmarshal(out, &infos) @@ -261,6 +264,9 @@ } out, err := s.RunFromDir("svn", "info", "-r", id, "--xml") + if err != nil { + return nil, NewLocalError("Unable to retrieve commit information", err, string(out)) + } infos := &Info{} err = xml.Unmarshal(out, &infos) if err != nil { @@ -323,11 +329,7 @@ // Ping returns if remote location is accessible. func (s *SvnRepo) Ping() bool { _, err := s.run("svn", "--non-interactive", "info", s.Remote()) - if err != nil { - return false - } - - return true + return err == nil } // ExportDir exports the current revision to the passed in directory. @@ -346,11 +348,7 @@ // where the parent directory of the VCS local path doesn't exist. func (s *SvnRepo) isUnableToCreateDir(err error) bool { msg := err.Error() - if strings.HasPrefix(msg, "E000002") { - return true - } - - return false + return strings.HasPrefix(msg, "E000002") } // detectRemoteFromInfoCommand finds the remote url from the `svn info`
diff --git a/vendor/github.com/Masterminds/vcs/svn_test.go b/vendor/github.com/Masterminds/vcs/svn_test.go index d242f3e..dfa0af8 100644 --- a/vendor/github.com/Masterminds/vcs/svn_test.go +++ b/vendor/github.com/Masterminds/vcs/svn_test.go
@@ -54,7 +54,7 @@ } // Verify SVN repo is a SVN repo - if repo.CheckLocal() == false { + if !repo.CheckLocal() { t.Error("Problem checking out repo or SVN CheckLocal is not working") } @@ -167,15 +167,15 @@ t.Error("Svn is incorrectly returning branches") } - if repo.IsReference("r4") != true { + if !repo.IsReference("r4") { t.Error("Svn is reporting a reference is not one") } - if repo.IsReference("55") == true { - t.Error("Svn is reporting a non-existant reference is one") + if repo.IsReference("55") { + t.Error("Svn is reporting a non-existent reference is one") } - if repo.IsDirty() == true { + if repo.IsDirty() { t.Error("Svn incorrectly reporting dirty") } @@ -230,7 +230,7 @@ _, err = os.Stat(filepath.Join(exportDir, string(repo.Vcs()))) if err != nil { - if found := os.IsNotExist(err); found == false { + if found := os.IsNotExist(err); !found { t.Errorf("Error checking exported metadata in Svn: %s", err) } } else { @@ -253,7 +253,7 @@ }() repo, _ := NewSvnRepo("", tempDir) - if repo.CheckLocal() == true { + if repo.CheckLocal() { t.Error("SVN CheckLocal does not identify non-SVN location") }
diff --git a/vendor/github.com/Masterminds/vcs/vcs_local_lookup.go b/vendor/github.com/Masterminds/vcs/vcs_local_lookup.go index f965132..0709f61 100644 --- a/vendor/github.com/Masterminds/vcs/vcs_local_lookup.go +++ b/vendor/github.com/Masterminds/vcs/vcs_local_lookup.go
@@ -15,20 +15,20 @@ return "", ErrCannotDetectVCS } - seperator := string(os.PathSeparator) + separator := string(os.PathSeparator) // Walk through each of the different VCS types to see if // one can be detected. Do this is order of guessed popularity. - if _, err := os.Stat(vcsPath + seperator + ".git"); err == nil { + if _, err := os.Stat(vcsPath + separator + ".git"); err == nil { return Git, nil } - if _, err := os.Stat(vcsPath + seperator + ".svn"); err == nil { + if _, err := os.Stat(vcsPath + separator + ".svn"); err == nil { return Svn, nil } - if _, err := os.Stat(vcsPath + seperator + ".hg"); err == nil { + if _, err := os.Stat(vcsPath + separator + ".hg"); err == nil { return Hg, nil } - if _, err := os.Stat(vcsPath + seperator + ".bzr"); err == nil { + if _, err := os.Stat(vcsPath + separator + ".bzr"); err == nil { return Bzr, nil }
diff --git a/vendor/github.com/Masterminds/vcs/vcs_remote_lookup.go b/vendor/github.com/Masterminds/vcs/vcs_remote_lookup.go index 0567af8..6689f95 100644 --- a/vendor/github.com/Masterminds/vcs/vcs_remote_lookup.go +++ b/vendor/github.com/Masterminds/vcs/vcs_remote_lookup.go
@@ -55,16 +55,10 @@ vcs: Git, pattern: `^(go\.googlesource\.com/[A-Za-z0-9_.\-]+/?)$`, }, - // TODO: Once Google Code becomes fully deprecated this can be removed. { - host: "code.google.com", - addCheck: checkGoogle, - pattern: `^(code\.google\.com/[pr]/(?P<project>[a-z0-9\-]+)(\.(?P<repo>[a-z0-9\-]+))?)(/[A-Za-z0-9_.\-]+)*$`, - }, - // Alternative Google setup. This is the previous structure but it still works... until Google Code goes away. - { - addCheck: checkURL, - pattern: `^([a-z0-9_\-.]+)\.googlecode\.com/(?P<type>git|hg|svn)(/.*)?$`, + host: "git.openstack.org", + vcs: Git, + pattern: `^(git\.openstack\.org/[A-Za-z0-9_.\-]+/[A-Za-z0-9_.\-]+)$`, }, // If none of the previous detect the type they will fall to this looking for the type in a generic sense // by the extension to the path. @@ -158,6 +152,11 @@ } } + // Detect file schemes + if u.Scheme == "file" { + return DetectVcsFromFS(u.Path) + } + if u.Host == "" { return "", ErrCannotDetectVCS } @@ -267,37 +266,6 @@ } -// Google supports Git, Hg, and Svn. The SVN style is only -// supported through their legacy setup at <project>.googlecode.com. -// I wonder if anyone is actually using SVN support. -func checkGoogle(i map[string]string, u *url.URL) (Type, error) { - - // To figure out which of the VCS types is used in Google Code you need - // to parse a web page and find it. Ugh. I mean... ugh. - var hack = regexp.MustCompile(`id="checkoutcmd">(hg|git|svn)`) - - d, err := get(expand(i, "https://code.google.com/p/{project}/source/checkout?repo={repo}")) - if err != nil { - return "", err - } - - if m := hack.FindSubmatch(d); m != nil { - if vcs := string(m[1]); vcs != "" { - if vcs == "svn" { - // While Google supports SVN it can only be used with the legacy - // urls of <project>.googlecode.com. I considered creating a new - // error for this problem but Google Code is going away and there - // is support for the legacy structure. - return "", ErrCannotDetectVCS - } - - return Type(vcs), nil - } - } - - return "", ErrCannotDetectVCS -} - // Expect a type key on i with the exact type detected from the regex. func checkURL(i map[string]string, u *url.URL) (Type, error) { return Type(i["type"]), nil
diff --git a/vendor/github.com/Masterminds/vcs/vcs_remote_lookup_test.go b/vendor/github.com/Masterminds/vcs/vcs_remote_lookup_test.go index e97bba8..395ee79 100644 --- a/vendor/github.com/Masterminds/vcs/vcs_remote_lookup_test.go +++ b/vendor/github.com/Masterminds/vcs/vcs_remote_lookup_test.go
@@ -1,6 +1,9 @@ package vcs import ( + "io/ioutil" + "os" + "os/exec" "strings" "testing" ) @@ -24,8 +27,6 @@ "https://hub.jazz.net/git/user1/pkgname": {work: true, t: Git}, "https://hub.jazz.net/git/user1/pkgname/subpkg/subpkg/subpkg": {work: true, t: Git}, "https://hubs.jazz.net/git/user1/pkgname": {work: false, t: Git}, - "http://farbtastic.googlecode.com/svn/": {work: true, t: Svn}, - "http://farbtastic.googlecode.com/svn/trunk": {work: true, t: Svn}, "https://example.com/foo/bar.git": {work: true, t: Git}, "https://example.com/foo/bar.svn": {work: true, t: Svn}, "https://example.com/foo/bar/baz.bzr": {work: true, t: Bzr}, @@ -33,6 +34,7 @@ "https://gopkg.in/tomb.v1": {work: true, t: Git}, "https://golang.org/x/net": {work: true, t: Git}, "https://speter.net/go/exp/math/dec/inf": {work: true, t: Git}, + "https://git.openstack.org/foo/bar": {work: true, t: Git}, "git@github.com:Masterminds/vcs.git": {work: true, t: Git}, "git@example.com:foo.git": {work: true, t: Git}, "ssh://hg@bitbucket.org/mattfarina/testhgrepo": {work: true, t: Hg}, @@ -47,15 +49,15 @@ for u, c := range urlList { ty, _, err := detectVcsFromRemote(u) - if err == nil && c.work == false { + if err == nil && !c.work { t.Errorf("Error detecting VCS from URL(%s)", u) } - if err == ErrCannotDetectVCS && c.work == true { + if err == ErrCannotDetectVCS && c.work { t.Errorf("Error detecting VCS from URL(%s)", u) } - if err != nil && c.work == true { + if err != nil && c.work { t.Errorf("Error detecting VCS from URL(%s): %s", u, err) } @@ -63,16 +65,45 @@ err != ErrCannotDetectVCS && !strings.HasSuffix(err.Error(), "Not Found") && !strings.HasSuffix(err.Error(), "Access Denied") && - c.work == false { + !c.work { t.Errorf("Unexpected error returned (%s): %s", u, err) } - if c.work == true && ty != c.t { + if c.work && ty != c.t { t.Errorf("Incorrect VCS type returned(%s)", u) } } } +func TestVCSFileLookup(t *testing.T) { + tempDir, err := ioutil.TempDir("", "go-vcs-file-lookup-tests") + if err != nil { + t.Error(err) + } + defer func() { + err = os.RemoveAll(tempDir) + if err != nil { + t.Error(err) + } + }() + + _, err = exec.Command("git", "init", tempDir).CombinedOutput() + if err != nil { + t.Error(err) + } + + pth := "file://" + tempDir + ty, _, err := detectVcsFromRemote(pth) + + if err != nil { + t.Errorf("Unable to detect file:// path: %s", err) + } + + if ty != Git { + t.Errorf("Detected wrong type from file:// path. Found type %v", ty) + } +} + func TestNotFound(t *testing.T) { _, _, err := detectVcsFromRemote("https://mattfarina.com/notfound") if err == nil || !strings.HasSuffix(err.Error(), " Not Found") {
diff --git a/vendor/github.com/codegangsta/cli/.travis.yml b/vendor/github.com/codegangsta/cli/.travis.yml index 273d017..94836d7 100644 --- a/vendor/github.com/codegangsta/cli/.travis.yml +++ b/vendor/github.com/codegangsta/cli/.travis.yml
@@ -7,34 +7,33 @@ - node_modules go: -- 1.2.2 -- 1.3.3 -- 1.4 -- 1.5.4 -- 1.6.2 +- 1.2.x +- 1.3.x +- 1.4.2 +- 1.5.x +- 1.6.x +- 1.7.x - master matrix: allow_failures: - go: master include: - - go: 1.6.2 + - go: 1.6.x os: osx - - go: 1.1.2 - install: go get -v . - before_script: echo skipping gfmxr on $TRAVIS_GO_VERSION - script: - - ./runtests vet - - ./runtests test + - go: 1.7.x + os: osx before_script: -- go get github.com/urfave/gfmxr/... +- go get github.com/urfave/gfmrun/... || true +- go get golang.org/x/tools/... || true - if [ ! -f node_modules/.bin/markdown-toc ] ; then npm install markdown-toc ; fi script: +- ./runtests gen - ./runtests vet - ./runtests test -- ./runtests gfmxr +- ./runtests gfmrun - ./runtests toc
diff --git a/vendor/github.com/codegangsta/cli/CHANGELOG.md b/vendor/github.com/codegangsta/cli/CHANGELOG.md index d1904fe..07f7546 100644 --- a/vendor/github.com/codegangsta/cli/CHANGELOG.md +++ b/vendor/github.com/codegangsta/cli/CHANGELOG.md
@@ -4,6 +4,61 @@ ## [Unreleased] +## [1.19.1] - 2016-11-21 + +### Fixed + +- Fixes regression introduced in 1.19.0 where using an `ActionFunc` as + the `Action` for a command would cause it to error rather than calling the + function. Should not have a affected declarative cases using `func(c + *cli.Context) err)`. +- Shell completion now handles the case where the user specifies + `--generate-bash-completion` immediately after a flag that takes an argument. + Previously it call the application with `--generate-bash-completion` as the + flag value. + +## [1.19.0] - 2016-11-19 +### Added +- `FlagsByName` was added to make it easy to sort flags (e.g. `sort.Sort(cli.FlagsByName(app.Flags))`) +- A `Description` field was added to `App` for a more detailed description of + the application (similar to the existing `Description` field on `Command`) +- Flag type code generation via `go generate` +- Write to stderr and exit 1 if action returns non-nil error +- Added support for TOML to the `altsrc` loader +- `SkipArgReorder` was added to allow users to skip the argument reordering. + This is useful if you want to consider all "flags" after an argument as + arguments rather than flags (the default behavior of the stdlib `flag` + library). This is backported functionality from the [removal of the flag + reordering](https://github.com/urfave/cli/pull/398) in the unreleased version + 2 +- For formatted errors (those implementing `ErrorFormatter`), the errors will + be formatted during output. Compatible with `pkg/errors`. + +### Changed +- Raise minimum tested/supported Go version to 1.2+ + +### Fixed +- Consider empty environment variables as set (previously environment variables + with the equivalent of `""` would be skipped rather than their value used). +- Return an error if the value in a given environment variable cannot be parsed + as the flag type. Previously these errors were silently swallowed. +- Print full error when an invalid flag is specified (which includes the invalid flag) +- `App.Writer` defaults to `stdout` when `nil` +- If no action is specified on a command or app, the help is now printed instead of `panic`ing +- `App.Metadata` is initialized automatically now (previously was `nil` unless initialized) +- Correctly show help message if `-h` is provided to a subcommand +- `context.(Global)IsSet` now respects environment variables. Previously it + would return `false` if a flag was specified in the environment rather than + as an argument +- Removed deprecation warnings to STDERR to avoid them leaking to the end-user +- `altsrc`s import paths were updated to use `gopkg.in/urfave/cli.v1`. This + fixes issues that occurred when `gopkg.in/urfave/cli.v1` was imported as well + as `altsrc` where Go would complain that the types didn't match + +## [1.18.1] - 2016-08-28 +### Fixed +- Removed deprecation warnings to STDERR to avoid them leaking to the end-user (backported) + ## [1.18.0] - 2016-06-27 ### Added - `./runtests` test runner with coverage tracking by default @@ -22,6 +77,10 @@ - No longer swallows `panic`s that occur within the `Action`s themselves when detecting the signature of the `Action` field +## [1.17.1] - 2016-08-28 +### Fixed +- Removed deprecation warnings to STDERR to avoid them leaking to the end-user + ## [1.17.0] - 2016-05-09 ### Added - Pluggable flag-level help text rendering via `cli.DefaultFlagStringFunc` @@ -43,6 +102,10 @@ - cleanups based on [Go Report Card feedback](https://goreportcard.com/report/github.com/urfave/cli) +## [1.16.1] - 2016-08-28 +### Fixed +- Removed deprecation warnings to STDERR to avoid them leaking to the end-user + ## [1.16.0] - 2016-05-02 ### Added - `Hidden` field on all flag struct types to omit from generated help text
diff --git a/vendor/github.com/codegangsta/cli/README.md b/vendor/github.com/codegangsta/cli/README.md index ebb1d74..bb5f61e 100644 --- a/vendor/github.com/codegangsta/cli/README.md +++ b/vendor/github.com/codegangsta/cli/README.md
@@ -23,15 +23,16 @@ - [Installation](#installation) * [Supported platforms](#supported-platforms) * [Using the `v2` branch](#using-the-v2-branch) - * [Pinning to the `v1` branch](#pinning-to-the-v1-branch) + * [Pinning to the `v1` releases](#pinning-to-the-v1-releases) - [Getting Started](#getting-started) - [Examples](#examples) * [Arguments](#arguments) * [Flags](#flags) + [Placeholder Values](#placeholder-values) + [Alternate Names](#alternate-names) + + [Ordering](#ordering) + [Values from the Environment](#values-from-the-environment) - + [Values from alternate input sources (YAML and others)](#values-from-alternate-input-sources-yaml-and-others) + + [Values from alternate input sources (YAML, TOML, and others)](#values-from-alternate-input-sources-yaml-toml-and-others) * [Subcommands](#subcommands) * [Subcommands categories](#subcommands-categories) * [Exit code](#exit-code) @@ -60,18 +61,16 @@ ## Installation -Make sure you have a working Go environment. Go version 1.1+ is required for -core cli, whereas use of the [`./altsrc`](./altsrc) input extensions requires Go -version 1.2+. [See the install -instructions](http://golang.org/doc/install.html). +Make sure you have a working Go environment. Go version 1.2+ is supported. [See +the install instructions for Go](http://golang.org/doc/install.html). To install cli, simply run: ``` $ go get github.com/urfave/cli ``` -Make sure your `PATH` includes to the `$GOPATH/bin` directory so your commands -can be easily used: +Make sure your `PATH` includes the `$GOPATH/bin` directory so your commands can +be easily used: ``` export PATH=$PATH:$GOPATH/bin ``` @@ -106,11 +105,11 @@ ... ``` -### Pinning to the `v1` branch +### Pinning to the `v1` releases Similarly to the section above describing use of the `v2` branch, if one wants to avoid any unexpected compatibility pains once `v2` becomes `master`, then -pinning to the `v1` branch is an acceptable option, e.g.: +pinning to `v1` is an acceptable option, e.g.: ``` $ go get gopkg.in/urfave/cli.v1 @@ -124,6 +123,8 @@ ... ``` +This will pull the latest tagged `v1` release (e.g. `v1.18.1` at the time of writing). + ## Getting Started One of the philosophies behind cli is that an API should be playful and full of @@ -450,6 +451,56 @@ giving two different forms of the same flag in the same command invocation is an error. +#### Ordering + +Flags for the application and commands are shown in the order they are defined. +However, it's possible to sort them from outside this library by using `FlagsByName` +with `sort`. + +For example this: + +<!-- { + "args": ["--help"], + "output": "Load configuration from FILE\n.*Language for the greeting.*" +} --> +``` go +package main + +import ( + "os" + "sort" + + "github.com/urfave/cli" +) + +func main() { + app := cli.NewApp() + + app.Flags = []cli.Flag { + cli.StringFlag{ + Name: "lang, l", + Value: "english", + Usage: "Language for the greeting", + }, + cli.StringFlag{ + Name: "config, c", + Usage: "Load configuration from `FILE`", + }, + } + + sort.Sort(cli.FlagsByName(app.Flags)) + + app.Run(os.Args) +} +``` + +Will result in help output like: + +``` +--config FILE, -c FILE Load configuration from FILE +--lang value, -l value Language for the greeting (default: "english") +``` + #### Values from the Environment You can also have the default value set from the environment via `EnvVar`. e.g. @@ -515,10 +566,14 @@ } ``` -#### Values from alternate input sources (YAML and others) +#### Values from alternate input sources (YAML, TOML, and others) There is a separate package altsrc that adds support for getting flag values -from other input sources like YAML. +from other file input sources. + +Currently supported input source formats: +* YAML +* TOML In order to get values for a flag from an alternate input source the following code would be added to wrap an existing cli.Flag like below: @@ -540,9 +595,9 @@ the "load" flag used would also have to be defined on the command flags in order for this code snipped to work. -Currently only YAML files are supported but developers can add support for other -input sources by implementing the altsrc.InputSourceContext for their given -sources. +Currently only the aboved specified formats are supported but developers can +add support for other input sources by implementing the +altsrc.InputSourceContext for their given sources. Here is a more complete sample of a command using YAML support: @@ -845,7 +900,7 @@ ### Generated Help Text -The default help flag (`-h/--help`) is defined as `cli.HelpFlag` and is checked +The default help flag (`-h/--help`) is defined as `cli.HelpFlag` and is checked by the cli internals in order to print generated help text for the app, command, or subcommand, and break execution. @@ -950,12 +1005,12 @@ #### Customization -The default flag may be cusomized to something other than `-v/--version` by +The default flag may be customized to something other than `-v/--version` by setting `cli.VersionFlag`, e.g.: <!-- { "args": ["--print-version"], - "output": "partay version v19\\.99\\.0" + "output": "partay version 19\\.99\\.0" } --> ``` go package main @@ -974,7 +1029,7 @@ app := cli.NewApp() app.Name = "partay" - app.Version = "v19.99.0" + app.Version = "19.99.0" app.Run(os.Args) } ``` @@ -983,7 +1038,7 @@ <!-- { "args": ["--version"], - "output": "version=v19\\.99\\.0 revision=fafafaf" + "output": "version=19\\.99\\.0 revision=fafafaf" } --> ``` go package main @@ -1006,7 +1061,7 @@ app := cli.NewApp() app.Name = "partay" - app.Version = "v19.99.0" + app.Version = "19.99.0" app.Run(os.Args) } ``` @@ -1085,7 +1140,7 @@ func main() { app := cli.NewApp() app.Name = "kənˈtrīv" - app.Version = "v19.99.0" + app.Version = "19.99.0" app.Compiled = time.Now() app.Authors = []cli.Author{ cli.Author{
diff --git a/vendor/github.com/codegangsta/cli/altsrc/altsrc.go b/vendor/github.com/codegangsta/cli/altsrc/altsrc.go new file mode 100644 index 0000000..ac34bf6 --- /dev/null +++ b/vendor/github.com/codegangsta/cli/altsrc/altsrc.go
@@ -0,0 +1,3 @@ +package altsrc + +//go:generate python ../generate-flag-types altsrc -i ../flag-types.json -o flag_generated.go
diff --git a/vendor/github.com/codegangsta/cli/altsrc/flag.go b/vendor/github.com/codegangsta/cli/altsrc/flag.go index 3e44d02..84ef009 100644 --- a/vendor/github.com/codegangsta/cli/altsrc/flag.go +++ b/vendor/github.com/codegangsta/cli/altsrc/flag.go
@@ -1,13 +1,12 @@ package altsrc import ( - "flag" "fmt" - "os" "strconv" "strings" + "syscall" - "github.com/urfave/cli" + "gopkg.in/urfave/cli.v1" ) // FlagInputSourceExtension is an extension interface of cli.Flag that @@ -63,18 +62,6 @@ } } -// GenericFlag is the flag type that wraps cli.GenericFlag to allow -// for other values to be specified -type GenericFlag struct { - cli.GenericFlag - set *flag.FlagSet -} - -// NewGenericFlag creates a new GenericFlag -func NewGenericFlag(flag cli.GenericFlag) *GenericFlag { - return &GenericFlag{GenericFlag: flag, set: nil} -} - // ApplyInputSourceValue applies a generic value to the flagSet if required func (f *GenericFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error { if f.set != nil { @@ -94,25 +81,6 @@ return nil } -// Apply saves the flagSet for later usage then calls -// the wrapped GenericFlag.Apply -func (f *GenericFlag) Apply(set *flag.FlagSet) { - f.set = set - f.GenericFlag.Apply(set) -} - -// StringSliceFlag is the flag type that wraps cli.StringSliceFlag to allow -// for other values to be specified -type StringSliceFlag struct { - cli.StringSliceFlag - set *flag.FlagSet -} - -// NewStringSliceFlag creates a new StringSliceFlag -func NewStringSliceFlag(flag cli.StringSliceFlag) *StringSliceFlag { - return &StringSliceFlag{StringSliceFlag: flag, set: nil} -} - // ApplyInputSourceValue applies a StringSlice value to the flagSet if required func (f *StringSliceFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error { if f.set != nil { @@ -135,25 +103,6 @@ return nil } -// Apply saves the flagSet for later usage then calls -// the wrapped StringSliceFlag.Apply -func (f *StringSliceFlag) Apply(set *flag.FlagSet) { - f.set = set - f.StringSliceFlag.Apply(set) -} - -// IntSliceFlag is the flag type that wraps cli.IntSliceFlag to allow -// for other values to be specified -type IntSliceFlag struct { - cli.IntSliceFlag - set *flag.FlagSet -} - -// NewIntSliceFlag creates a new IntSliceFlag -func NewIntSliceFlag(flag cli.IntSliceFlag) *IntSliceFlag { - return &IntSliceFlag{IntSliceFlag: flag, set: nil} -} - // ApplyInputSourceValue applies a IntSlice value if required func (f *IntSliceFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error { if f.set != nil { @@ -176,25 +125,6 @@ return nil } -// Apply saves the flagSet for later usage then calls -// the wrapped IntSliceFlag.Apply -func (f *IntSliceFlag) Apply(set *flag.FlagSet) { - f.set = set - f.IntSliceFlag.Apply(set) -} - -// BoolFlag is the flag type that wraps cli.BoolFlag to allow -// for other values to be specified -type BoolFlag struct { - cli.BoolFlag - set *flag.FlagSet -} - -// NewBoolFlag creates a new BoolFlag -func NewBoolFlag(flag cli.BoolFlag) *BoolFlag { - return &BoolFlag{BoolFlag: flag, set: nil} -} - // ApplyInputSourceValue applies a Bool value to the flagSet if required func (f *BoolFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error { if f.set != nil { @@ -213,25 +143,6 @@ return nil } -// Apply saves the flagSet for later usage then calls -// the wrapped BoolFlag.Apply -func (f *BoolFlag) Apply(set *flag.FlagSet) { - f.set = set - f.BoolFlag.Apply(set) -} - -// BoolTFlag is the flag type that wraps cli.BoolTFlag to allow -// for other values to be specified -type BoolTFlag struct { - cli.BoolTFlag - set *flag.FlagSet -} - -// NewBoolTFlag creates a new BoolTFlag -func NewBoolTFlag(flag cli.BoolTFlag) *BoolTFlag { - return &BoolTFlag{BoolTFlag: flag, set: nil} -} - // ApplyInputSourceValue applies a BoolT value to the flagSet if required func (f *BoolTFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error { if f.set != nil { @@ -250,26 +161,6 @@ return nil } -// Apply saves the flagSet for later usage then calls -// the wrapped BoolTFlag.Apply -func (f *BoolTFlag) Apply(set *flag.FlagSet) { - f.set = set - - f.BoolTFlag.Apply(set) -} - -// StringFlag is the flag type that wraps cli.StringFlag to allow -// for other values to be specified -type StringFlag struct { - cli.StringFlag - set *flag.FlagSet -} - -// NewStringFlag creates a new StringFlag -func NewStringFlag(flag cli.StringFlag) *StringFlag { - return &StringFlag{StringFlag: flag, set: nil} -} - // ApplyInputSourceValue applies a String value to the flagSet if required func (f *StringFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error { if f.set != nil { @@ -288,26 +179,6 @@ return nil } -// Apply saves the flagSet for later usage then calls -// the wrapped StringFlag.Apply -func (f *StringFlag) Apply(set *flag.FlagSet) { - f.set = set - - f.StringFlag.Apply(set) -} - -// IntFlag is the flag type that wraps cli.IntFlag to allow -// for other values to be specified -type IntFlag struct { - cli.IntFlag - set *flag.FlagSet -} - -// NewIntFlag creates a new IntFlag -func NewIntFlag(flag cli.IntFlag) *IntFlag { - return &IntFlag{IntFlag: flag, set: nil} -} - // ApplyInputSourceValue applies a int value to the flagSet if required func (f *IntFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error { if f.set != nil { @@ -326,25 +197,6 @@ return nil } -// Apply saves the flagSet for later usage then calls -// the wrapped IntFlag.Apply -func (f *IntFlag) Apply(set *flag.FlagSet) { - f.set = set - f.IntFlag.Apply(set) -} - -// DurationFlag is the flag type that wraps cli.DurationFlag to allow -// for other values to be specified -type DurationFlag struct { - cli.DurationFlag - set *flag.FlagSet -} - -// NewDurationFlag creates a new DurationFlag -func NewDurationFlag(flag cli.DurationFlag) *DurationFlag { - return &DurationFlag{DurationFlag: flag, set: nil} -} - // ApplyInputSourceValue applies a Duration value to the flagSet if required func (f *DurationFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error { if f.set != nil { @@ -363,26 +215,6 @@ return nil } -// Apply saves the flagSet for later usage then calls -// the wrapped DurationFlag.Apply -func (f *DurationFlag) Apply(set *flag.FlagSet) { - f.set = set - - f.DurationFlag.Apply(set) -} - -// Float64Flag is the flag type that wraps cli.Float64Flag to allow -// for other values to be specified -type Float64Flag struct { - cli.Float64Flag - set *flag.FlagSet -} - -// NewFloat64Flag creates a new Float64Flag -func NewFloat64Flag(flag cli.Float64Flag) *Float64Flag { - return &Float64Flag{Float64Flag: flag, set: nil} -} - // ApplyInputSourceValue applies a Float64 value to the flagSet if required func (f *Float64Flag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error { if f.set != nil { @@ -402,24 +234,14 @@ return nil } -// Apply saves the flagSet for later usage then calls -// the wrapped Float64Flag.Apply -func (f *Float64Flag) Apply(set *flag.FlagSet) { - f.set = set - - f.Float64Flag.Apply(set) -} - func isEnvVarSet(envVars string) bool { for _, envVar := range strings.Split(envVars, ",") { envVar = strings.TrimSpace(envVar) - if envVal := os.Getenv(envVar); envVal != "" { + if _, ok := syscall.Getenv(envVar); ok { // TODO: Can't use this for bools as // set means that it was true or false based on // Bool flag type, should work for other types - if len(envVal) > 0 { - return true - } + return true } }
diff --git a/vendor/github.com/codegangsta/cli/altsrc/flag_generated.go b/vendor/github.com/codegangsta/cli/altsrc/flag_generated.go new file mode 100644 index 0000000..0aeb0b0 --- /dev/null +++ b/vendor/github.com/codegangsta/cli/altsrc/flag_generated.go
@@ -0,0 +1,347 @@ +package altsrc + +import ( + "flag" + + "gopkg.in/urfave/cli.v1" +) + +// WARNING: This file is generated! + +// BoolFlag is the flag type that wraps cli.BoolFlag to allow +// for other values to be specified +type BoolFlag struct { + cli.BoolFlag + set *flag.FlagSet +} + +// NewBoolFlag creates a new BoolFlag +func NewBoolFlag(fl cli.BoolFlag) *BoolFlag { + return &BoolFlag{BoolFlag: fl, set: nil} +} + +// Apply saves the flagSet for later usage calls, then calls the +// wrapped BoolFlag.Apply +func (f *BoolFlag) Apply(set *flag.FlagSet) { + f.set = set + f.BoolFlag.Apply(set) +} + +// ApplyWithError saves the flagSet for later usage calls, then calls the +// wrapped BoolFlag.ApplyWithError +func (f *BoolFlag) ApplyWithError(set *flag.FlagSet) error { + f.set = set + return f.BoolFlag.ApplyWithError(set) +} + +// BoolTFlag is the flag type that wraps cli.BoolTFlag to allow +// for other values to be specified +type BoolTFlag struct { + cli.BoolTFlag + set *flag.FlagSet +} + +// NewBoolTFlag creates a new BoolTFlag +func NewBoolTFlag(fl cli.BoolTFlag) *BoolTFlag { + return &BoolTFlag{BoolTFlag: fl, set: nil} +} + +// Apply saves the flagSet for later usage calls, then calls the +// wrapped BoolTFlag.Apply +func (f *BoolTFlag) Apply(set *flag.FlagSet) { + f.set = set + f.BoolTFlag.Apply(set) +} + +// ApplyWithError saves the flagSet for later usage calls, then calls the +// wrapped BoolTFlag.ApplyWithError +func (f *BoolTFlag) ApplyWithError(set *flag.FlagSet) error { + f.set = set + return f.BoolTFlag.ApplyWithError(set) +} + +// DurationFlag is the flag type that wraps cli.DurationFlag to allow +// for other values to be specified +type DurationFlag struct { + cli.DurationFlag + set *flag.FlagSet +} + +// NewDurationFlag creates a new DurationFlag +func NewDurationFlag(fl cli.DurationFlag) *DurationFlag { + return &DurationFlag{DurationFlag: fl, set: nil} +} + +// Apply saves the flagSet for later usage calls, then calls the +// wrapped DurationFlag.Apply +func (f *DurationFlag) Apply(set *flag.FlagSet) { + f.set = set + f.DurationFlag.Apply(set) +} + +// ApplyWithError saves the flagSet for later usage calls, then calls the +// wrapped DurationFlag.ApplyWithError +func (f *DurationFlag) ApplyWithError(set *flag.FlagSet) error { + f.set = set + return f.DurationFlag.ApplyWithError(set) +} + +// Float64Flag is the flag type that wraps cli.Float64Flag to allow +// for other values to be specified +type Float64Flag struct { + cli.Float64Flag + set *flag.FlagSet +} + +// NewFloat64Flag creates a new Float64Flag +func NewFloat64Flag(fl cli.Float64Flag) *Float64Flag { + return &Float64Flag{Float64Flag: fl, set: nil} +} + +// Apply saves the flagSet for later usage calls, then calls the +// wrapped Float64Flag.Apply +func (f *Float64Flag) Apply(set *flag.FlagSet) { + f.set = set + f.Float64Flag.Apply(set) +} + +// ApplyWithError saves the flagSet for later usage calls, then calls the +// wrapped Float64Flag.ApplyWithError +func (f *Float64Flag) ApplyWithError(set *flag.FlagSet) error { + f.set = set + return f.Float64Flag.ApplyWithError(set) +} + +// GenericFlag is the flag type that wraps cli.GenericFlag to allow +// for other values to be specified +type GenericFlag struct { + cli.GenericFlag + set *flag.FlagSet +} + +// NewGenericFlag creates a new GenericFlag +func NewGenericFlag(fl cli.GenericFlag) *GenericFlag { + return &GenericFlag{GenericFlag: fl, set: nil} +} + +// Apply saves the flagSet for later usage calls, then calls the +// wrapped GenericFlag.Apply +func (f *GenericFlag) Apply(set *flag.FlagSet) { + f.set = set + f.GenericFlag.Apply(set) +} + +// ApplyWithError saves the flagSet for later usage calls, then calls the +// wrapped GenericFlag.ApplyWithError +func (f *GenericFlag) ApplyWithError(set *flag.FlagSet) error { + f.set = set + return f.GenericFlag.ApplyWithError(set) +} + +// Int64Flag is the flag type that wraps cli.Int64Flag to allow +// for other values to be specified +type Int64Flag struct { + cli.Int64Flag + set *flag.FlagSet +} + +// NewInt64Flag creates a new Int64Flag +func NewInt64Flag(fl cli.Int64Flag) *Int64Flag { + return &Int64Flag{Int64Flag: fl, set: nil} +} + +// Apply saves the flagSet for later usage calls, then calls the +// wrapped Int64Flag.Apply +func (f *Int64Flag) Apply(set *flag.FlagSet) { + f.set = set + f.Int64Flag.Apply(set) +} + +// ApplyWithError saves the flagSet for later usage calls, then calls the +// wrapped Int64Flag.ApplyWithError +func (f *Int64Flag) ApplyWithError(set *flag.FlagSet) error { + f.set = set + return f.Int64Flag.ApplyWithError(set) +} + +// IntFlag is the flag type that wraps cli.IntFlag to allow +// for other values to be specified +type IntFlag struct { + cli.IntFlag + set *flag.FlagSet +} + +// NewIntFlag creates a new IntFlag +func NewIntFlag(fl cli.IntFlag) *IntFlag { + return &IntFlag{IntFlag: fl, set: nil} +} + +// Apply saves the flagSet for later usage calls, then calls the +// wrapped IntFlag.Apply +func (f *IntFlag) Apply(set *flag.FlagSet) { + f.set = set + f.IntFlag.Apply(set) +} + +// ApplyWithError saves the flagSet for later usage calls, then calls the +// wrapped IntFlag.ApplyWithError +func (f *IntFlag) ApplyWithError(set *flag.FlagSet) error { + f.set = set + return f.IntFlag.ApplyWithError(set) +} + +// IntSliceFlag is the flag type that wraps cli.IntSliceFlag to allow +// for other values to be specified +type IntSliceFlag struct { + cli.IntSliceFlag + set *flag.FlagSet +} + +// NewIntSliceFlag creates a new IntSliceFlag +func NewIntSliceFlag(fl cli.IntSliceFlag) *IntSliceFlag { + return &IntSliceFlag{IntSliceFlag: fl, set: nil} +} + +// Apply saves the flagSet for later usage calls, then calls the +// wrapped IntSliceFlag.Apply +func (f *IntSliceFlag) Apply(set *flag.FlagSet) { + f.set = set + f.IntSliceFlag.Apply(set) +} + +// ApplyWithError saves the flagSet for later usage calls, then calls the +// wrapped IntSliceFlag.ApplyWithError +func (f *IntSliceFlag) ApplyWithError(set *flag.FlagSet) error { + f.set = set + return f.IntSliceFlag.ApplyWithError(set) +} + +// Int64SliceFlag is the flag type that wraps cli.Int64SliceFlag to allow +// for other values to be specified +type Int64SliceFlag struct { + cli.Int64SliceFlag + set *flag.FlagSet +} + +// NewInt64SliceFlag creates a new Int64SliceFlag +func NewInt64SliceFlag(fl cli.Int64SliceFlag) *Int64SliceFlag { + return &Int64SliceFlag{Int64SliceFlag: fl, set: nil} +} + +// Apply saves the flagSet for later usage calls, then calls the +// wrapped Int64SliceFlag.Apply +func (f *Int64SliceFlag) Apply(set *flag.FlagSet) { + f.set = set + f.Int64SliceFlag.Apply(set) +} + +// ApplyWithError saves the flagSet for later usage calls, then calls the +// wrapped Int64SliceFlag.ApplyWithError +func (f *Int64SliceFlag) ApplyWithError(set *flag.FlagSet) error { + f.set = set + return f.Int64SliceFlag.ApplyWithError(set) +} + +// StringFlag is the flag type that wraps cli.StringFlag to allow +// for other values to be specified +type StringFlag struct { + cli.StringFlag + set *flag.FlagSet +} + +// NewStringFlag creates a new StringFlag +func NewStringFlag(fl cli.StringFlag) *StringFlag { + return &StringFlag{StringFlag: fl, set: nil} +} + +// Apply saves the flagSet for later usage calls, then calls the +// wrapped StringFlag.Apply +func (f *StringFlag) Apply(set *flag.FlagSet) { + f.set = set + f.StringFlag.Apply(set) +} + +// ApplyWithError saves the flagSet for later usage calls, then calls the +// wrapped StringFlag.ApplyWithError +func (f *StringFlag) ApplyWithError(set *flag.FlagSet) error { + f.set = set + return f.StringFlag.ApplyWithError(set) +} + +// StringSliceFlag is the flag type that wraps cli.StringSliceFlag to allow +// for other values to be specified +type StringSliceFlag struct { + cli.StringSliceFlag + set *flag.FlagSet +} + +// NewStringSliceFlag creates a new StringSliceFlag +func NewStringSliceFlag(fl cli.StringSliceFlag) *StringSliceFlag { + return &StringSliceFlag{StringSliceFlag: fl, set: nil} +} + +// Apply saves the flagSet for later usage calls, then calls the +// wrapped StringSliceFlag.Apply +func (f *StringSliceFlag) Apply(set *flag.FlagSet) { + f.set = set + f.StringSliceFlag.Apply(set) +} + +// ApplyWithError saves the flagSet for later usage calls, then calls the +// wrapped StringSliceFlag.ApplyWithError +func (f *StringSliceFlag) ApplyWithError(set *flag.FlagSet) error { + f.set = set + return f.StringSliceFlag.ApplyWithError(set) +} + +// Uint64Flag is the flag type that wraps cli.Uint64Flag to allow +// for other values to be specified +type Uint64Flag struct { + cli.Uint64Flag + set *flag.FlagSet +} + +// NewUint64Flag creates a new Uint64Flag +func NewUint64Flag(fl cli.Uint64Flag) *Uint64Flag { + return &Uint64Flag{Uint64Flag: fl, set: nil} +} + +// Apply saves the flagSet for later usage calls, then calls the +// wrapped Uint64Flag.Apply +func (f *Uint64Flag) Apply(set *flag.FlagSet) { + f.set = set + f.Uint64Flag.Apply(set) +} + +// ApplyWithError saves the flagSet for later usage calls, then calls the +// wrapped Uint64Flag.ApplyWithError +func (f *Uint64Flag) ApplyWithError(set *flag.FlagSet) error { + f.set = set + return f.Uint64Flag.ApplyWithError(set) +} + +// UintFlag is the flag type that wraps cli.UintFlag to allow +// for other values to be specified +type UintFlag struct { + cli.UintFlag + set *flag.FlagSet +} + +// NewUintFlag creates a new UintFlag +func NewUintFlag(fl cli.UintFlag) *UintFlag { + return &UintFlag{UintFlag: fl, set: nil} +} + +// Apply saves the flagSet for later usage calls, then calls the +// wrapped UintFlag.Apply +func (f *UintFlag) Apply(set *flag.FlagSet) { + f.set = set + f.UintFlag.Apply(set) +} + +// ApplyWithError saves the flagSet for later usage calls, then calls the +// wrapped UintFlag.ApplyWithError +func (f *UintFlag) ApplyWithError(set *flag.FlagSet) error { + f.set = set + return f.UintFlag.ApplyWithError(set) +}
diff --git a/vendor/github.com/codegangsta/cli/altsrc/flag_test.go b/vendor/github.com/codegangsta/cli/altsrc/flag_test.go index 218e9b8..9e9c96d 100644 --- a/vendor/github.com/codegangsta/cli/altsrc/flag_test.go +++ b/vendor/github.com/codegangsta/cli/altsrc/flag_test.go
@@ -8,7 +8,7 @@ "testing" "time" - "github.com/urfave/cli" + "gopkg.in/urfave/cli.v1" ) type testApplyInputSource struct {
diff --git a/vendor/github.com/codegangsta/cli/altsrc/input_source_context.go b/vendor/github.com/codegangsta/cli/altsrc/input_source_context.go index 8ea7e92..276dcda 100644 --- a/vendor/github.com/codegangsta/cli/altsrc/input_source_context.go +++ b/vendor/github.com/codegangsta/cli/altsrc/input_source_context.go
@@ -3,7 +3,7 @@ import ( "time" - "github.com/urfave/cli" + "gopkg.in/urfave/cli.v1" ) // InputSourceContext is an interface used to allow
diff --git a/vendor/github.com/codegangsta/cli/altsrc/map_input_source.go b/vendor/github.com/codegangsta/cli/altsrc/map_input_source.go index b1c8e4f..b720995 100644 --- a/vendor/github.com/codegangsta/cli/altsrc/map_input_source.go +++ b/vendor/github.com/codegangsta/cli/altsrc/map_input_source.go
@@ -6,7 +6,7 @@ "strings" "time" - "github.com/urfave/cli" + "gopkg.in/urfave/cli.v1" ) // MapInputSource implements InputSourceContext to return
diff --git a/vendor/github.com/codegangsta/cli/altsrc/toml_command_test.go b/vendor/github.com/codegangsta/cli/altsrc/toml_command_test.go new file mode 100644 index 0000000..a5053d4 --- /dev/null +++ b/vendor/github.com/codegangsta/cli/altsrc/toml_command_test.go
@@ -0,0 +1,310 @@ +// Disabling building of toml support in cases where golang is 1.0 or 1.1 +// as the encoding library is not implemented or supported. + +// +build go1.2 + +package altsrc + +import ( + "flag" + "io/ioutil" + "os" + "testing" + + "gopkg.in/urfave/cli.v1" +) + +func TestCommandTomFileTest(t *testing.T) { + app := cli.NewApp() + set := flag.NewFlagSet("test", 0) + ioutil.WriteFile("current.toml", []byte("test = 15"), 0666) + defer os.Remove("current.toml") + test := []string{"test-cmd", "--load", "current.toml"} + set.Parse(test) + + c := cli.NewContext(app, set, nil) + + command := &cli.Command{ + Name: "test-cmd", + Aliases: []string{"tc"}, + Usage: "this is for testing", + Description: "testing", + Action: func(c *cli.Context) error { + val := c.Int("test") + expect(t, val, 15) + return nil + }, + Flags: []cli.Flag{ + NewIntFlag(cli.IntFlag{Name: "test"}), + cli.StringFlag{Name: "load"}}, + } + command.Before = InitInputSourceWithContext(command.Flags, NewTomlSourceFromFlagFunc("load")) + err := command.Run(c) + + expect(t, err, nil) +} + +func TestCommandTomlFileTestGlobalEnvVarWins(t *testing.T) { + app := cli.NewApp() + set := flag.NewFlagSet("test", 0) + ioutil.WriteFile("current.toml", []byte("test = 15"), 0666) + defer os.Remove("current.toml") + + os.Setenv("THE_TEST", "10") + defer os.Setenv("THE_TEST", "") + test := []string{"test-cmd", "--load", "current.toml"} + set.Parse(test) + + c := cli.NewContext(app, set, nil) + + command := &cli.Command{ + Name: "test-cmd", + Aliases: []string{"tc"}, + Usage: "this is for testing", + Description: "testing", + Action: func(c *cli.Context) error { + val := c.Int("test") + expect(t, val, 10) + return nil + }, + Flags: []cli.Flag{ + NewIntFlag(cli.IntFlag{Name: "test", EnvVar: "THE_TEST"}), + cli.StringFlag{Name: "load"}}, + } + command.Before = InitInputSourceWithContext(command.Flags, NewTomlSourceFromFlagFunc("load")) + + err := command.Run(c) + + expect(t, err, nil) +} + +func TestCommandTomlFileTestGlobalEnvVarWinsNested(t *testing.T) { + app := cli.NewApp() + set := flag.NewFlagSet("test", 0) + ioutil.WriteFile("current.toml", []byte("[top]\ntest = 15"), 0666) + defer os.Remove("current.toml") + + os.Setenv("THE_TEST", "10") + defer os.Setenv("THE_TEST", "") + test := []string{"test-cmd", "--load", "current.toml"} + set.Parse(test) + + c := cli.NewContext(app, set, nil) + + command := &cli.Command{ + Name: "test-cmd", + Aliases: []string{"tc"}, + Usage: "this is for testing", + Description: "testing", + Action: func(c *cli.Context) error { + val := c.Int("top.test") + expect(t, val, 10) + return nil + }, + Flags: []cli.Flag{ + NewIntFlag(cli.IntFlag{Name: "top.test", EnvVar: "THE_TEST"}), + cli.StringFlag{Name: "load"}}, + } + command.Before = InitInputSourceWithContext(command.Flags, NewTomlSourceFromFlagFunc("load")) + + err := command.Run(c) + + expect(t, err, nil) +} + +func TestCommandTomlFileTestSpecifiedFlagWins(t *testing.T) { + app := cli.NewApp() + set := flag.NewFlagSet("test", 0) + ioutil.WriteFile("current.toml", []byte("test = 15"), 0666) + defer os.Remove("current.toml") + + test := []string{"test-cmd", "--load", "current.toml", "--test", "7"} + set.Parse(test) + + c := cli.NewContext(app, set, nil) + + command := &cli.Command{ + Name: "test-cmd", + Aliases: []string{"tc"}, + Usage: "this is for testing", + Description: "testing", + Action: func(c *cli.Context) error { + val := c.Int("test") + expect(t, val, 7) + return nil + }, + Flags: []cli.Flag{ + NewIntFlag(cli.IntFlag{Name: "test"}), + cli.StringFlag{Name: "load"}}, + } + command.Before = InitInputSourceWithContext(command.Flags, NewTomlSourceFromFlagFunc("load")) + + err := command.Run(c) + + expect(t, err, nil) +} + +func TestCommandTomlFileTestSpecifiedFlagWinsNested(t *testing.T) { + app := cli.NewApp() + set := flag.NewFlagSet("test", 0) + ioutil.WriteFile("current.toml", []byte(`[top] + test = 15`), 0666) + defer os.Remove("current.toml") + + test := []string{"test-cmd", "--load", "current.toml", "--top.test", "7"} + set.Parse(test) + + c := cli.NewContext(app, set, nil) + + command := &cli.Command{ + Name: "test-cmd", + Aliases: []string{"tc"}, + Usage: "this is for testing", + Description: "testing", + Action: func(c *cli.Context) error { + val := c.Int("top.test") + expect(t, val, 7) + return nil + }, + Flags: []cli.Flag{ + NewIntFlag(cli.IntFlag{Name: "top.test"}), + cli.StringFlag{Name: "load"}}, + } + command.Before = InitInputSourceWithContext(command.Flags, NewTomlSourceFromFlagFunc("load")) + + err := command.Run(c) + + expect(t, err, nil) +} + +func TestCommandTomlFileTestDefaultValueFileWins(t *testing.T) { + app := cli.NewApp() + set := flag.NewFlagSet("test", 0) + ioutil.WriteFile("current.toml", []byte("test = 15"), 0666) + defer os.Remove("current.toml") + + test := []string{"test-cmd", "--load", "current.toml"} + set.Parse(test) + + c := cli.NewContext(app, set, nil) + + command := &cli.Command{ + Name: "test-cmd", + Aliases: []string{"tc"}, + Usage: "this is for testing", + Description: "testing", + Action: func(c *cli.Context) error { + val := c.Int("test") + expect(t, val, 15) + return nil + }, + Flags: []cli.Flag{ + NewIntFlag(cli.IntFlag{Name: "test", Value: 7}), + cli.StringFlag{Name: "load"}}, + } + command.Before = InitInputSourceWithContext(command.Flags, NewTomlSourceFromFlagFunc("load")) + + err := command.Run(c) + + expect(t, err, nil) +} + +func TestCommandTomlFileTestDefaultValueFileWinsNested(t *testing.T) { + app := cli.NewApp() + set := flag.NewFlagSet("test", 0) + ioutil.WriteFile("current.toml", []byte("[top]\ntest = 15"), 0666) + defer os.Remove("current.toml") + + test := []string{"test-cmd", "--load", "current.toml"} + set.Parse(test) + + c := cli.NewContext(app, set, nil) + + command := &cli.Command{ + Name: "test-cmd", + Aliases: []string{"tc"}, + Usage: "this is for testing", + Description: "testing", + Action: func(c *cli.Context) error { + val := c.Int("top.test") + expect(t, val, 15) + return nil + }, + Flags: []cli.Flag{ + NewIntFlag(cli.IntFlag{Name: "top.test", Value: 7}), + cli.StringFlag{Name: "load"}}, + } + command.Before = InitInputSourceWithContext(command.Flags, NewTomlSourceFromFlagFunc("load")) + + err := command.Run(c) + + expect(t, err, nil) +} + +func TestCommandTomlFileFlagHasDefaultGlobalEnvTomlSetGlobalEnvWins(t *testing.T) { + app := cli.NewApp() + set := flag.NewFlagSet("test", 0) + ioutil.WriteFile("current.toml", []byte("test = 15"), 0666) + defer os.Remove("current.toml") + + os.Setenv("THE_TEST", "11") + defer os.Setenv("THE_TEST", "") + + test := []string{"test-cmd", "--load", "current.toml"} + set.Parse(test) + + c := cli.NewContext(app, set, nil) + + command := &cli.Command{ + Name: "test-cmd", + Aliases: []string{"tc"}, + Usage: "this is for testing", + Description: "testing", + Action: func(c *cli.Context) error { + val := c.Int("test") + expect(t, val, 11) + return nil + }, + Flags: []cli.Flag{ + NewIntFlag(cli.IntFlag{Name: "test", Value: 7, EnvVar: "THE_TEST"}), + cli.StringFlag{Name: "load"}}, + } + command.Before = InitInputSourceWithContext(command.Flags, NewTomlSourceFromFlagFunc("load")) + err := command.Run(c) + + expect(t, err, nil) +} + +func TestCommandTomlFileFlagHasDefaultGlobalEnvTomlSetGlobalEnvWinsNested(t *testing.T) { + app := cli.NewApp() + set := flag.NewFlagSet("test", 0) + ioutil.WriteFile("current.toml", []byte("[top]\ntest = 15"), 0666) + defer os.Remove("current.toml") + + os.Setenv("THE_TEST", "11") + defer os.Setenv("THE_TEST", "") + + test := []string{"test-cmd", "--load", "current.toml"} + set.Parse(test) + + c := cli.NewContext(app, set, nil) + + command := &cli.Command{ + Name: "test-cmd", + Aliases: []string{"tc"}, + Usage: "this is for testing", + Description: "testing", + Action: func(c *cli.Context) error { + val := c.Int("top.test") + expect(t, val, 11) + return nil + }, + Flags: []cli.Flag{ + NewIntFlag(cli.IntFlag{Name: "top.test", Value: 7, EnvVar: "THE_TEST"}), + cli.StringFlag{Name: "load"}}, + } + command.Before = InitInputSourceWithContext(command.Flags, NewTomlSourceFromFlagFunc("load")) + err := command.Run(c) + + expect(t, err, nil) +}
diff --git a/vendor/github.com/codegangsta/cli/altsrc/toml_file_loader.go b/vendor/github.com/codegangsta/cli/altsrc/toml_file_loader.go new file mode 100644 index 0000000..39c124f --- /dev/null +++ b/vendor/github.com/codegangsta/cli/altsrc/toml_file_loader.go
@@ -0,0 +1,113 @@ +// Disabling building of toml support in cases where golang is 1.0 or 1.1 +// as the encoding library is not implemented or supported. + +// +build go1.2 + +package altsrc + +import ( + "fmt" + "reflect" + + "github.com/BurntSushi/toml" + "gopkg.in/urfave/cli.v1" +) + +type tomlMap struct { + Map map[interface{}]interface{} +} + +func unmarshalMap(i interface{}) (ret map[interface{}]interface{}, err error) { + ret = make(map[interface{}]interface{}) + m := i.(map[string]interface{}) + for key, val := range m { + v := reflect.ValueOf(val) + switch v.Kind() { + case reflect.Bool: + ret[key] = val.(bool) + case reflect.String: + ret[key] = val.(string) + case reflect.Int: + ret[key] = int(val.(int)) + case reflect.Int8: + ret[key] = int(val.(int8)) + case reflect.Int16: + ret[key] = int(val.(int16)) + case reflect.Int32: + ret[key] = int(val.(int32)) + case reflect.Int64: + ret[key] = int(val.(int64)) + case reflect.Uint: + ret[key] = int(val.(uint)) + case reflect.Uint8: + ret[key] = int(val.(uint8)) + case reflect.Uint16: + ret[key] = int(val.(uint16)) + case reflect.Uint32: + ret[key] = int(val.(uint32)) + case reflect.Uint64: + ret[key] = int(val.(uint64)) + case reflect.Float32: + ret[key] = float64(val.(float32)) + case reflect.Float64: + ret[key] = float64(val.(float64)) + case reflect.Map: + if tmp, err := unmarshalMap(val); err == nil { + ret[key] = tmp + } else { + return nil, err + } + case reflect.Array: + fallthrough // [todo] - Support array type + default: + return nil, fmt.Errorf("Unsupported: type = %#v", v.Kind()) + } + } + return ret, nil +} + +func (self *tomlMap) UnmarshalTOML(i interface{}) error { + if tmp, err := unmarshalMap(i); err == nil { + self.Map = tmp + } else { + return err + } + return nil +} + +type tomlSourceContext struct { + FilePath string +} + +// NewTomlSourceFromFile creates a new TOML InputSourceContext from a filepath. +func NewTomlSourceFromFile(file string) (InputSourceContext, error) { + tsc := &tomlSourceContext{FilePath: file} + var results tomlMap = tomlMap{} + if err := readCommandToml(tsc.FilePath, &results); err != nil { + return nil, fmt.Errorf("Unable to load TOML file '%s': inner error: \n'%v'", tsc.FilePath, err.Error()) + } + return &MapInputSource{valueMap: results.Map}, nil +} + +// NewTomlSourceFromFlagFunc creates a new TOML InputSourceContext from a provided flag name and source context. +func NewTomlSourceFromFlagFunc(flagFileName string) func(context *cli.Context) (InputSourceContext, error) { + return func(context *cli.Context) (InputSourceContext, error) { + filePath := context.String(flagFileName) + return NewTomlSourceFromFile(filePath) + } +} + +func readCommandToml(filePath string, container interface{}) (err error) { + b, err := loadDataFrom(filePath) + if err != nil { + return err + } + + err = toml.Unmarshal(b, container) + if err != nil { + return err + } + + err = nil + return +}
diff --git a/vendor/github.com/codegangsta/cli/altsrc/yaml_command_test.go b/vendor/github.com/codegangsta/cli/altsrc/yaml_command_test.go index 31f78ce..9d3f431 100644 --- a/vendor/github.com/codegangsta/cli/altsrc/yaml_command_test.go +++ b/vendor/github.com/codegangsta/cli/altsrc/yaml_command_test.go
@@ -11,7 +11,7 @@ "os" "testing" - "github.com/urfave/cli" + "gopkg.in/urfave/cli.v1" ) func TestCommandYamlFileTest(t *testing.T) {
diff --git a/vendor/github.com/codegangsta/cli/altsrc/yaml_file_loader.go b/vendor/github.com/codegangsta/cli/altsrc/yaml_file_loader.go index b4e3365..335356f 100644 --- a/vendor/github.com/codegangsta/cli/altsrc/yaml_file_loader.go +++ b/vendor/github.com/codegangsta/cli/altsrc/yaml_file_loader.go
@@ -12,7 +12,7 @@ "net/url" "os" - "github.com/urfave/cli" + "gopkg.in/urfave/cli.v1" "gopkg.in/yaml.v2" )
diff --git a/vendor/github.com/codegangsta/cli/app.go b/vendor/github.com/codegangsta/cli/app.go index a046c01..95ffc0b 100644 --- a/vendor/github.com/codegangsta/cli/app.go +++ b/vendor/github.com/codegangsta/cli/app.go
@@ -6,9 +6,7 @@ "io/ioutil" "os" "path/filepath" - "reflect" "sort" - "strings" "time" ) @@ -19,11 +17,8 @@ contactSysadmin = "This is an error in the application. Please contact the distributor of this application if this is not you." - errNonFuncAction = NewExitError("ERROR invalid Action type. "+ - fmt.Sprintf("Must be a func of type `cli.ActionFunc`. %s", contactSysadmin)+ - fmt.Sprintf("See %s", appActionDeprecationURL), 2) - errInvalidActionSignature = NewExitError("ERROR invalid Action signature. "+ - fmt.Sprintf("Must be `cli.ActionFunc`. %s", contactSysadmin)+ + errInvalidActionType = NewExitError("ERROR invalid Action type. "+ + fmt.Sprintf("Must be `func(*Context`)` or `func(*Context) error). %s", contactSysadmin)+ fmt.Sprintf("See %s", appActionDeprecationURL), 2) ) @@ -42,6 +37,8 @@ ArgsUsage string // Version of the program Version string + // Description of the program + Description string // List of commands to execute Commands []Command // List of flags to parse @@ -62,10 +59,11 @@ // An action to execute after any subcommands are run, but after the subcommand has finished // It is run even if Action() panics After AfterFunc + // The action to execute when no subcommands are specified + // Expects a `cli.ActionFunc` but will accept the *deprecated* signature of `func(*cli.Context) {}` + // *Note*: support for the deprecated `Action` signature will be removed in a future version Action interface{} - // TODO: replace `Action: interface{}` with `Action: ActionFunc` once some kind - // of deprecation period has passed, maybe? // Execute this function if the proper command cannot be found CommandNotFound CommandNotFoundFunc @@ -147,10 +145,6 @@ } } - if a.EnableBashCompletion { - a.appendFlag(BashCompletionFlag) - } - if !a.HideVersion { a.appendFlag(VersionFlag) } @@ -160,6 +154,14 @@ a.categories = a.categories.AddCommand(command.Category, command) } sort.Sort(a.categories) + + if a.Metadata == nil { + a.Metadata = make(map[string]interface{}) + } + + if a.Writer == nil { + a.Writer = os.Stdout + } } // Run is the entry point to the cli app. Parses the arguments slice and routes @@ -167,8 +169,20 @@ func (a *App) Run(arguments []string) (err error) { a.Setup() + // handle the completion flag separately from the flagset since + // completion could be attempted after a flag, but before its value was put + // on the command line. this causes the flagset to interpret the completion + // flag name as the value of the flag before it which is undesirable + // note that we can only do this because the shell autocomplete function + // always appends the completion flag at the end of the command + shellComplete, arguments := checkShellCompleteFlag(a, arguments) + // parse flags - set := flagSet(a.Name, a.Flags) + set, err := flagSet(a.Name, a.Flags) + if err != nil { + return err + } + set.SetOutput(ioutil.Discard) err = set.Parse(arguments[1:]) nerr := normalizeFlags(a.Flags, set) @@ -178,6 +192,7 @@ ShowAppHelp(context) return nerr } + context.shellComplete = shellComplete if checkCompletions(context) { return nil @@ -189,7 +204,7 @@ HandleExitCoder(err) return err } - fmt.Fprintf(a.Writer, "%s\n\n", "Incorrect Usage.") + fmt.Fprintf(a.Writer, "%s %s\n\n", "Incorrect Usage.", err.Error()) ShowAppHelp(context) return err } @@ -236,6 +251,10 @@ } } + if a.Action == nil { + a.Action = helpCommand.Action + } + // Run default Action err = HandleAction(a.Action, context) @@ -243,11 +262,12 @@ return err } -// DEPRECATED: Another entry point to the cli app, takes care of passing arguments and error handling +// RunAndExitOnError calls .Run() and exits non-zero if an error was returned +// +// Deprecated: instead you should return an error that fulfills cli.ExitCoder +// to cli.App.Run. This will cause the application to exit with the given eror +// code in the cli.ExitCoder func (a *App) RunAndExitOnError() { - fmt.Fprintf(a.errWriter(), - "DEPRECATED cli.App.RunAndExitOnError. %s See %s\n", - contactSysadmin, runAndExitOnErrorDeprecationURL) if err := a.Run(os.Args); err != nil { fmt.Fprintln(a.errWriter(), err) OsExiter(1) @@ -276,13 +296,12 @@ } a.Commands = newCmds - // append flags - if a.EnableBashCompletion { - a.appendFlag(BashCompletionFlag) + // parse flags + set, err := flagSet(a.Name, a.Flags) + if err != nil { + return err } - // parse flags - set := flagSet(a.Name, a.Flags) set.SetOutput(ioutil.Discard) err = set.Parse(ctx.Args().Tail()) nerr := normalizeFlags(a.Flags, set) @@ -309,7 +328,7 @@ HandleExitCoder(err) return err } - fmt.Fprintf(a.Writer, "%s\n\n", "Incorrect Usage.") + fmt.Fprintf(a.Writer, "%s %s\n\n", "Incorrect Usage.", err.Error()) ShowSubcommandHelp(context) return err } @@ -450,50 +469,24 @@ func (a Author) String() string { e := "" if a.Email != "" { - e = "<" + a.Email + "> " + e = " <" + a.Email + ">" } - return fmt.Sprintf("%v %v", a.Name, e) + return fmt.Sprintf("%v%v", a.Name, e) } -// HandleAction uses ✧✧✧reflection✧✧✧ to figure out if the given Action is an -// ActionFunc, a func with the legacy signature for Action, or some other -// invalid thing. If it's an ActionFunc or a func with the legacy signature for -// Action, the func is run! +// HandleAction attempts to figure out which Action signature was used. If +// it's an ActionFunc or a func with the legacy signature for Action, the func +// is run! func HandleAction(action interface{}, context *Context) (err error) { - defer func() { - if r := recover(); r != nil { - // Try to detect a known reflection error from *this scope*, rather than - // swallowing all panics that may happen when calling an Action func. - s := fmt.Sprintf("%v", r) - if strings.HasPrefix(s, "reflect: ") && strings.Contains(s, "too many input arguments") { - err = NewExitError(fmt.Sprintf("ERROR unknown Action error: %v. See %s", r, appActionDeprecationURL), 2) - } else { - panic(r) - } - } - }() - - if reflect.TypeOf(action).Kind() != reflect.Func { - return errNonFuncAction - } - - vals := reflect.ValueOf(action).Call([]reflect.Value{reflect.ValueOf(context)}) - - if len(vals) == 0 { - fmt.Fprintf(ErrWriter, - "DEPRECATED Action signature. Must be `cli.ActionFunc`. %s See %s\n", - contactSysadmin, appActionDeprecationURL) + if a, ok := action.(ActionFunc); ok { + return a(context) + } else if a, ok := action.(func(*Context) error); ok { + return a(context) + } else if a, ok := action.(func(*Context)); ok { // deprecated function signature + a(context) return nil + } else { + return errInvalidActionType } - - if len(vals) > 1 { - return errInvalidActionSignature - } - - if retErr, ok := vals[0].Interface().(error); vals[0].IsValid() && ok { - return retErr - } - - return err }
diff --git a/vendor/github.com/codegangsta/cli/app_test.go b/vendor/github.com/codegangsta/cli/app_test.go index 9c6b960..10f1562 100644 --- a/vendor/github.com/codegangsta/cli/app_test.go +++ b/vendor/github.com/codegangsta/cli/app_test.go
@@ -13,6 +13,19 @@ "testing" ) +var ( + lastExitCode = 0 + fakeOsExiter = func(rc int) { + lastExitCode = rc + } + fakeErrWriter = &bytes.Buffer{} +) + +func init() { + OsExiter = fakeOsExiter + ErrWriter = fakeErrWriter +} + type opCounts struct { Total, BashComplete, OnUsageError, Before, CommandNotFound, Action, After, SubCommand int } @@ -77,7 +90,62 @@ // Hello, Jeremy } -func ExampleApp_Run_help() { +func ExampleApp_Run_appHelp() { + // set args for examples sake + os.Args = []string{"greet", "help"} + + app := NewApp() + app.Name = "greet" + app.Version = "0.1.0" + app.Description = "This is how we describe greet the app" + app.Authors = []Author{ + {Name: "Harrison", Email: "harrison@lolwut.com"}, + {Name: "Oliver Allen", Email: "oliver@toyshop.com"}, + } + app.Flags = []Flag{ + StringFlag{Name: "name", Value: "bob", Usage: "a name to say"}, + } + app.Commands = []Command{ + { + Name: "describeit", + Aliases: []string{"d"}, + Usage: "use it to see a description", + Description: "This is how we describe describeit the function", + Action: func(c *Context) error { + fmt.Printf("i like to describe things") + return nil + }, + }, + } + app.Run(os.Args) + // Output: + // NAME: + // greet - A new cli application + // + // USAGE: + // greet [global options] command [command options] [arguments...] + // + // VERSION: + // 0.1.0 + // + // DESCRIPTION: + // This is how we describe greet the app + // + // AUTHORS: + // Harrison <harrison@lolwut.com> + // Oliver Allen <oliver@toyshop.com> + // + // COMMANDS: + // describeit, d use it to see a description + // help, h Shows a list of commands or help for one command + // + // GLOBAL OPTIONS: + // --name value a name to say (default: "bob") + // --help, -h show help + // --version, -v print the version +} + +func ExampleApp_Run_commandHelp() { // set args for examples sake os.Args = []string{"greet", "h", "describeit"} @@ -110,6 +178,49 @@ // This is how we describe describeit the function } +func ExampleApp_Run_noAction() { + app := App{} + app.Name = "greet" + app.Run([]string{"greet"}) + // Output: + // NAME: + // greet + // + // USAGE: + // [global options] command [command options] [arguments...] + // + // COMMANDS: + // help, h Shows a list of commands or help for one command + // + // GLOBAL OPTIONS: + // --help, -h show help + // --version, -v print the version +} + +func ExampleApp_Run_subcommandNoAction() { + app := App{} + app.Name = "greet" + app.Commands = []Command{ + { + Name: "describeit", + Aliases: []string{"d"}, + Usage: "use it to see a description", + Description: "This is how we describe describeit the function", + }, + } + app.Run([]string{"greet", "describeit"}) + // Output: + // NAME: + // describeit - use it to see a description + // + // USAGE: + // describeit [arguments...] + // + // DESCRIPTION: + // This is how we describe describeit the function + +} + func ExampleApp_Run_bashComplete() { // set args for examples sake os.Args = []string{"greet", "--generate-bash-completion"} @@ -189,6 +300,12 @@ } } +func TestApp_Setup_defaultsWriter(t *testing.T) { + app := &App{} + app.Setup() + expect(t, app.Writer, os.Stdout) +} + func TestApp_CommandWithArgBeforeFlags(t *testing.T) { var parsedOption, firstArg string @@ -239,6 +356,23 @@ expect(t, context.String("lang"), "spanish") } +func TestApp_RunAsSubCommandIncorrectUsage(t *testing.T) { + a := App{ + Flags: []Flag{ + StringFlag{Name: "--foo"}, + }, + Writer: bytes.NewBufferString(""), + } + + set := flag.NewFlagSet("", flag.ContinueOnError) + set.Parse([]string{"", "---foo"}) + c := &Context{flagSet: set} + + err := a.RunAsSubcommand(c) + + expect(t, err, errors.New("bad flag syntax: ---foo")) +} + func TestApp_CommandWithFlagBeforeTerminator(t *testing.T) { var parsedOption string var args []string @@ -908,6 +1042,7 @@ Name: "foo", Description: "descriptive wall of text about how it does foo things", Subcommands: []Command{subCmdBar, subCmdBaz}, + Action: func(c *Context) error { return nil }, } app.Commands = []Command{cmd} @@ -1388,7 +1523,39 @@ func TestHandleAction_WithNonFuncAction(t *testing.T) { app := NewApp() app.Action = 42 - err := HandleAction(app.Action, NewContext(app, flagSet(app.Name, app.Flags), nil)) + fs, err := flagSet(app.Name, app.Flags) + if err != nil { + t.Errorf("error creating FlagSet: %s", err) + } + err = HandleAction(app.Action, NewContext(app, fs, nil)) + + if err == nil { + t.Fatalf("expected to receive error from Run, got none") + } + + exitErr, ok := err.(*ExitError) + + if !ok { + t.Fatalf("expected to receive a *ExitError") + } + + if !strings.HasPrefix(exitErr.Error(), "ERROR invalid Action type.") { + t.Fatalf("expected an unknown Action error, but got: %v", exitErr.Error()) + } + + if exitErr.ExitCode() != 2 { + t.Fatalf("expected error exit code to be 2, but got: %v", exitErr.ExitCode()) + } +} + +func TestHandleAction_WithInvalidFuncSignature(t *testing.T) { + app := NewApp() + app.Action = func() string { return "" } + fs, err := flagSet(app.Name, app.Flags) + if err != nil { + t.Errorf("error creating FlagSet: %s", err) + } + err = HandleAction(app.Action, NewContext(app, fs, nil)) if err == nil { t.Fatalf("expected to receive error from Run, got none") @@ -1409,34 +1576,14 @@ } } -func TestHandleAction_WithInvalidFuncSignature(t *testing.T) { - app := NewApp() - app.Action = func() string { return "" } - err := HandleAction(app.Action, NewContext(app, flagSet(app.Name, app.Flags), nil)) - - if err == nil { - t.Fatalf("expected to receive error from Run, got none") - } - - exitErr, ok := err.(*ExitError) - - if !ok { - t.Fatalf("expected to receive a *ExitError") - } - - if !strings.HasPrefix(exitErr.Error(), "ERROR unknown Action error") { - t.Fatalf("expected an unknown Action error, but got: %v", exitErr.Error()) - } - - if exitErr.ExitCode() != 2 { - t.Fatalf("expected error exit code to be 2, but got: %v", exitErr.ExitCode()) - } -} - func TestHandleAction_WithInvalidFuncReturnSignature(t *testing.T) { app := NewApp() app.Action = func(_ *Context) (int, error) { return 0, nil } - err := HandleAction(app.Action, NewContext(app, flagSet(app.Name, app.Flags), nil)) + fs, err := flagSet(app.Name, app.Flags) + if err != nil { + t.Errorf("error creating FlagSet: %s", err) + } + err = HandleAction(app.Action, NewContext(app, fs, nil)) if err == nil { t.Fatalf("expected to receive error from Run, got none") @@ -1448,7 +1595,7 @@ t.Fatalf("expected to receive a *ExitError") } - if !strings.HasPrefix(exitErr.Error(), "ERROR invalid Action signature") { + if !strings.HasPrefix(exitErr.Error(), "ERROR invalid Action type") { t.Fatalf("expected an invalid Action signature error, but got: %v", exitErr.Error()) } @@ -1467,5 +1614,72 @@ fn(ctx) return nil } - HandleAction(app.Action, NewContext(app, flagSet(app.Name, app.Flags), nil)) + fs, err := flagSet(app.Name, app.Flags) + if err != nil { + t.Errorf("error creating FlagSet: %s", err) + } + HandleAction(app.Action, NewContext(app, fs, nil)) +} + +func TestShellCompletionForIncompleteFlags(t *testing.T) { + app := NewApp() + app.Flags = []Flag{ + IntFlag{ + Name: "test-completion", + }, + } + app.EnableBashCompletion = true + app.BashComplete = func(ctx *Context) { + for _, command := range ctx.App.Commands { + if command.Hidden { + continue + } + + for _, name := range command.Names() { + fmt.Fprintln(ctx.App.Writer, name) + } + } + + for _, flag := range ctx.App.Flags { + for _, name := range strings.Split(flag.GetName(), ",") { + if name == BashCompletionFlag.Name { + continue + } + + switch name = strings.TrimSpace(name); len(name) { + case 0: + case 1: + fmt.Fprintln(ctx.App.Writer, "-"+name) + default: + fmt.Fprintln(ctx.App.Writer, "--"+name) + } + } + } + } + app.Action = func(ctx *Context) error { + return fmt.Errorf("should not get here") + } + err := app.Run([]string{"", "--test-completion", "--" + BashCompletionFlag.Name}) + if err != nil { + t.Errorf("app should not return an error: %s", err) + } +} + +func TestHandleActionActuallyWorksWithActions(t *testing.T) { + var f ActionFunc + called := false + f = func(c *Context) error { + called = true + return nil + } + + err := HandleAction(f, nil) + + if err != nil { + t.Errorf("Should not have errored: %v", err) + } + + if !called { + t.Errorf("Function was not called") + } }
diff --git a/vendor/github.com/codegangsta/cli/appveyor.yml b/vendor/github.com/codegangsta/cli/appveyor.yml index 173086e..698b188 100644 --- a/vendor/github.com/codegangsta/cli/appveyor.yml +++ b/vendor/github.com/codegangsta/cli/appveyor.yml
@@ -10,16 +10,15 @@ PYTHON: C:\Python27-x64 PYTHON_VERSION: 2.7.x PYTHON_ARCH: 64 - GFMXR_DEBUG: 1 install: - set PATH=%GOPATH%\bin;C:\go\bin;%PATH% - go version - go env -- go get github.com/urfave/gfmxr/... +- go get github.com/urfave/gfmrun/... - go get -v -t ./... build_script: - python runtests vet - python runtests test -- python runtests gfmxr +- python runtests gfmrun
diff --git a/vendor/github.com/codegangsta/cli/cli.go b/vendor/github.com/codegangsta/cli/cli.go index f0440c5..74fd101 100644 --- a/vendor/github.com/codegangsta/cli/cli.go +++ b/vendor/github.com/codegangsta/cli/cli.go
@@ -17,3 +17,5 @@ // app.Run(os.Args) // } package cli + +//go:generate python ./generate-flag-types cli -i flag-types.json -o flag_generated.go
diff --git a/vendor/github.com/codegangsta/cli/command.go b/vendor/github.com/codegangsta/cli/command.go index 8950cca..2628fbf 100644 --- a/vendor/github.com/codegangsta/cli/command.go +++ b/vendor/github.com/codegangsta/cli/command.go
@@ -46,6 +46,11 @@ Flags []Flag // Treat all flags as normal arguments if true SkipFlagParsing bool + // Skip argument reordering which attempts to move flags before arguments, + // but only works if all flags appear after all arguments. This behavior was + // removed n version 2 since it only works under specific conditions so we + // backport here by exposing it as an option for compatibility. + SkipArgReorder bool // Boolean to hide built-in help command HideHelp bool // Boolean to hide this command from help or completion @@ -82,14 +87,15 @@ ) } - if ctx.App.EnableBashCompletion { - c.Flags = append(c.Flags, BashCompletionFlag) + set, err := flagSet(c.Name, c.Flags) + if err != nil { + return err } - - set := flagSet(c.Name, c.Flags) set.SetOutput(ioutil.Discard) - if !c.SkipFlagParsing { + if c.SkipFlagParsing { + err = set.Parse(append([]string{"--"}, ctx.Args().Tail()...)) + } else if !c.SkipArgReorder { firstFlagIndex := -1 terminatorIndex := -1 for index, arg := range ctx.Args() { @@ -122,21 +128,7 @@ err = set.Parse(ctx.Args().Tail()) } } else { - if c.SkipFlagParsing { - err = set.Parse(append([]string{"--"}, ctx.Args().Tail()...)) - } - } - - if err != nil { - if c.OnUsageError != nil { - err := c.OnUsageError(ctx, err, false) - HandleExitCoder(err) - return err - } - fmt.Fprintln(ctx.App.Writer, "Incorrect Usage.") - fmt.Fprintln(ctx.App.Writer) - ShowCommandHelp(ctx, c.Name) - return err + err = set.Parse(ctx.Args().Tail()) } nerr := normalizeFlags(c.Flags, set) @@ -148,11 +140,22 @@ } context := NewContext(ctx.App, set, ctx) - if checkCommandCompletions(context, c.Name) { return nil } + if err != nil { + if c.OnUsageError != nil { + err := c.OnUsageError(ctx, err, false) + HandleExitCoder(err) + return err + } + fmt.Fprintln(ctx.App.Writer, "Incorrect Usage:", err.Error()) + fmt.Fprintln(ctx.App.Writer) + ShowCommandHelp(ctx, c.Name) + return err + } + if checkCommandHelp(context, c.Name) { return nil } @@ -182,6 +185,10 @@ } } + if c.Action == nil { + c.Action = helpSubcommand.Action + } + context.Command = c err = HandleAction(c.Action, context)
diff --git a/vendor/github.com/codegangsta/cli/command_test.go b/vendor/github.com/codegangsta/cli/command_test.go index 6608254..5e0e8de 100644 --- a/vendor/github.com/codegangsta/cli/command_test.go +++ b/vendor/github.com/codegangsta/cli/command_test.go
@@ -13,12 +13,18 @@ cases := []struct { testArgs []string skipFlagParsing bool + skipArgReorder bool expectedErr error }{ - {[]string{"blah", "blah", "-break"}, false, errors.New("flag provided but not defined: -break")}, // Test normal "not ignoring flags" flow - {[]string{"blah", "blah"}, true, nil}, // Test SkipFlagParsing without any args that look like flags - {[]string{"blah", "-break"}, true, nil}, // Test SkipFlagParsing with random flag arg - {[]string{"blah", "-help"}, true, nil}, // Test SkipFlagParsing with "special" help flag arg + // Test normal "not ignoring flags" flow + {[]string{"test-cmd", "blah", "blah", "-break"}, false, false, errors.New("flag provided but not defined: -break")}, + + // Test no arg reorder + {[]string{"test-cmd", "blah", "blah", "-break"}, false, true, nil}, + + {[]string{"test-cmd", "blah", "blah"}, true, false, nil}, // Test SkipFlagParsing without any args that look like flags + {[]string{"test-cmd", "blah", "-break"}, true, false, nil}, // Test SkipFlagParsing with random flag arg + {[]string{"test-cmd", "blah", "-help"}, true, false, nil}, // Test SkipFlagParsing with "special" help flag arg } for _, c := range cases { @@ -30,15 +36,15 @@ context := NewContext(app, set, nil) command := Command{ - Name: "test-cmd", - Aliases: []string{"tc"}, - Usage: "this is for testing", - Description: "testing", - Action: func(_ *Context) error { return nil }, + Name: "test-cmd", + Aliases: []string{"tc"}, + Usage: "this is for testing", + Description: "testing", + Action: func(_ *Context) error { return nil }, + SkipFlagParsing: c.skipFlagParsing, + SkipArgReorder: c.skipArgReorder, } - command.SkipFlagParsing = c.skipFlagParsing - err := command.Run(context) expect(t, err, c.expectedErr) @@ -73,6 +79,54 @@ } } +func TestCommand_Run_BeforeSavesMetadata(t *testing.T) { + var receivedMsgFromAction string + var receivedMsgFromAfter string + + app := NewApp() + app.Commands = []Command{ + { + Name: "bar", + Before: func(c *Context) error { + c.App.Metadata["msg"] = "hello world" + return nil + }, + Action: func(c *Context) error { + msg, ok := c.App.Metadata["msg"] + if !ok { + return errors.New("msg not found") + } + receivedMsgFromAction = msg.(string) + return nil + }, + After: func(c *Context) error { + msg, ok := c.App.Metadata["msg"] + if !ok { + return errors.New("msg not found") + } + receivedMsgFromAfter = msg.(string) + return nil + }, + }, + } + + err := app.Run([]string{"foo", "bar"}) + if err != nil { + t.Fatalf("expected no error from Run, got %s", err) + } + + expectedMsg := "hello world" + + if receivedMsgFromAction != expectedMsg { + t.Fatalf("expected msg from Action to match. Given: %q\nExpected: %q", + receivedMsgFromAction, expectedMsg) + } + if receivedMsgFromAfter != expectedMsg { + t.Fatalf("expected msg from After to match. Given: %q\nExpected: %q", + receivedMsgFromAction, expectedMsg) + } +} + func TestCommand_OnUsageError_WithWrongFlagValue(t *testing.T) { app := NewApp() app.Commands = []Command{
diff --git a/vendor/github.com/codegangsta/cli/context.go b/vendor/github.com/codegangsta/cli/context.go index 879bae5..cb89e92 100644 --- a/vendor/github.com/codegangsta/cli/context.go +++ b/vendor/github.com/codegangsta/cli/context.go
@@ -3,9 +3,9 @@ import ( "errors" "flag" - "strconv" + "reflect" "strings" - "time" + "syscall" ) // Context is a type that is passed through to @@ -13,201 +13,23 @@ // can be used to retrieve context-specific Args and // parsed command-line options. type Context struct { - App *App - Command Command - flagSet *flag.FlagSet - setFlags map[string]bool - globalSetFlags map[string]bool - parentContext *Context + App *App + Command Command + shellComplete bool + flagSet *flag.FlagSet + setFlags map[string]bool + parentContext *Context } // NewContext creates a new context. For use in when invoking an App or Command action. func NewContext(app *App, set *flag.FlagSet, parentCtx *Context) *Context { - return &Context{App: app, flagSet: set, parentContext: parentCtx} -} + c := &Context{App: app, flagSet: set, parentContext: parentCtx} -// Int looks up the value of a local int flag, returns 0 if no int flag exists -func (c *Context) Int(name string) int { - return lookupInt(name, c.flagSet) -} - -// Int64 looks up the value of a local int flag, returns 0 if no int flag exists -func (c *Context) Int64(name string) int64 { - return lookupInt64(name, c.flagSet) -} - -// Uint looks up the value of a local int flag, returns 0 if no int flag exists -func (c *Context) Uint(name string) uint { - return lookupUint(name, c.flagSet) -} - -// Uint64 looks up the value of a local int flag, returns 0 if no int flag exists -func (c *Context) Uint64(name string) uint64 { - return lookupUint64(name, c.flagSet) -} - -// Duration looks up the value of a local time.Duration flag, returns 0 if no -// time.Duration flag exists -func (c *Context) Duration(name string) time.Duration { - return lookupDuration(name, c.flagSet) -} - -// Float64 looks up the value of a local float64 flag, returns 0 if no float64 -// flag exists -func (c *Context) Float64(name string) float64 { - return lookupFloat64(name, c.flagSet) -} - -// Bool looks up the value of a local bool flag, returns false if no bool flag exists -func (c *Context) Bool(name string) bool { - return lookupBool(name, c.flagSet) -} - -// BoolT looks up the value of a local boolT flag, returns false if no bool flag exists -func (c *Context) BoolT(name string) bool { - return lookupBoolT(name, c.flagSet) -} - -// String looks up the value of a local string flag, returns "" if no string flag exists -func (c *Context) String(name string) string { - return lookupString(name, c.flagSet) -} - -// StringSlice looks up the value of a local string slice flag, returns nil if no -// string slice flag exists -func (c *Context) StringSlice(name string) []string { - return lookupStringSlice(name, c.flagSet) -} - -// IntSlice looks up the value of a local int slice flag, returns nil if no int -// slice flag exists -func (c *Context) IntSlice(name string) []int { - return lookupIntSlice(name, c.flagSet) -} - -// Int64Slice looks up the value of a local int slice flag, returns nil if no int -// slice flag exists -func (c *Context) Int64Slice(name string) []int64 { - return lookupInt64Slice(name, c.flagSet) -} - -// Generic looks up the value of a local generic flag, returns nil if no generic -// flag exists -func (c *Context) Generic(name string) interface{} { - return lookupGeneric(name, c.flagSet) -} - -// GlobalInt looks up the value of a global int flag, returns 0 if no int flag exists -func (c *Context) GlobalInt(name string) int { - if fs := lookupGlobalFlagSet(name, c); fs != nil { - return lookupInt(name, fs) + if parentCtx != nil { + c.shellComplete = parentCtx.shellComplete } - return 0 -} -// GlobalInt64 looks up the value of a global int flag, returns 0 if no int flag exists -func (c *Context) GlobalInt64(name string) int64 { - if fs := lookupGlobalFlagSet(name, c); fs != nil { - return lookupInt64(name, fs) - } - return 0 -} - -// GlobalUint looks up the value of a global int flag, returns 0 if no int flag exists -func (c *Context) GlobalUint(name string) uint { - if fs := lookupGlobalFlagSet(name, c); fs != nil { - return lookupUint(name, fs) - } - return 0 -} - -// GlobalUint64 looks up the value of a global int flag, returns 0 if no int flag exists -func (c *Context) GlobalUint64(name string) uint64 { - if fs := lookupGlobalFlagSet(name, c); fs != nil { - return lookupUint64(name, fs) - } - return 0 -} - -// GlobalFloat64 looks up the value of a global float64 flag, returns float64(0) -// if no float64 flag exists -func (c *Context) GlobalFloat64(name string) float64 { - if fs := lookupGlobalFlagSet(name, c); fs != nil { - return lookupFloat64(name, fs) - } - return float64(0) -} - -// GlobalDuration looks up the value of a global time.Duration flag, returns 0 -// if no time.Duration flag exists -func (c *Context) GlobalDuration(name string) time.Duration { - if fs := lookupGlobalFlagSet(name, c); fs != nil { - return lookupDuration(name, fs) - } - return 0 -} - -// GlobalBool looks up the value of a global bool flag, returns false if no bool -// flag exists -func (c *Context) GlobalBool(name string) bool { - if fs := lookupGlobalFlagSet(name, c); fs != nil { - return lookupBool(name, fs) - } - return false -} - -// GlobalBoolT looks up the value of a global bool flag, returns true if no bool -// flag exists -func (c *Context) GlobalBoolT(name string) bool { - if fs := lookupGlobalFlagSet(name, c); fs != nil { - return lookupBoolT(name, fs) - } - return false -} - -// GlobalString looks up the value of a global string flag, returns "" if no -// string flag exists -func (c *Context) GlobalString(name string) string { - if fs := lookupGlobalFlagSet(name, c); fs != nil { - return lookupString(name, fs) - } - return "" -} - -// GlobalStringSlice looks up the value of a global string slice flag, returns -// nil if no string slice flag exists -func (c *Context) GlobalStringSlice(name string) []string { - if fs := lookupGlobalFlagSet(name, c); fs != nil { - return lookupStringSlice(name, fs) - } - return nil -} - -// GlobalIntSlice looks up the value of a global int slice flag, returns nil if -// no int slice flag exists -func (c *Context) GlobalIntSlice(name string) []int { - if fs := lookupGlobalFlagSet(name, c); fs != nil { - return lookupIntSlice(name, fs) - } - return nil -} - -// GlobalInt64Slice looks up the value of a global int slice flag, returns nil if -// no int slice flag exists -func (c *Context) GlobalInt64Slice(name string) []int64 { - if fs := lookupGlobalFlagSet(name, c); fs != nil { - return lookupInt64Slice(name, fs) - } - return nil -} - -// GlobalGeneric looks up the value of a global generic flag, returns nil if no -// generic flag exists -func (c *Context) GlobalGeneric(name string) interface{} { - if fs := lookupGlobalFlagSet(name, c); fs != nil { - return lookupGeneric(name, fs) - } - return nil + return c } // NumFlags returns the number of flags set @@ -229,28 +51,78 @@ func (c *Context) IsSet(name string) bool { if c.setFlags == nil { c.setFlags = make(map[string]bool) + c.flagSet.Visit(func(f *flag.Flag) { c.setFlags[f.Name] = true }) + + c.flagSet.VisitAll(func(f *flag.Flag) { + if _, ok := c.setFlags[f.Name]; ok { + return + } + c.setFlags[f.Name] = false + }) + + // XXX hack to support IsSet for flags with EnvVar + // + // There isn't an easy way to do this with the current implementation since + // whether a flag was set via an environment variable is very difficult to + // determine here. Instead, we intend to introduce a backwards incompatible + // change in version 2 to add `IsSet` to the Flag interface to push the + // responsibility closer to where the information required to determine + // whether a flag is set by non-standard means such as environment + // variables is avaliable. + // + // See https://github.com/urfave/cli/issues/294 for additional discussion + flags := c.Command.Flags + if c.Command.Name == "" { // cannot == Command{} since it contains slice types + if c.App != nil { + flags = c.App.Flags + } + } + for _, f := range flags { + eachName(f.GetName(), func(name string) { + if isSet, ok := c.setFlags[name]; isSet || !ok { + return + } + + val := reflect.ValueOf(f) + if val.Kind() == reflect.Ptr { + val = val.Elem() + } + + envVarValue := val.FieldByName("EnvVar") + if !envVarValue.IsValid() { + return + } + + eachName(envVarValue.String(), func(envVar string) { + envVar = strings.TrimSpace(envVar) + if _, ok := syscall.Getenv(envVar); ok { + c.setFlags[name] = true + return + } + }) + }) + } } - return c.setFlags[name] == true + + return c.setFlags[name] } // GlobalIsSet determines if the global flag was actually set func (c *Context) GlobalIsSet(name string) bool { - if c.globalSetFlags == nil { - c.globalSetFlags = make(map[string]bool) - ctx := c - if ctx.parentContext != nil { - ctx = ctx.parentContext - } - for ; ctx != nil && c.globalSetFlags[name] == false; ctx = ctx.parentContext { - ctx.flagSet.Visit(func(f *flag.Flag) { - c.globalSetFlags[f.Name] = true - }) + ctx := c + if ctx.parentContext != nil { + ctx = ctx.parentContext + } + + for ; ctx != nil; ctx = ctx.parentContext { + if ctx.IsSet(name) { + return true } } - return c.globalSetFlags[name] + return false } // FlagNames returns a slice of flag names used in this context. @@ -282,6 +154,11 @@ return c.parentContext } +// value returns the value of the flag coressponding to `name` +func (c *Context) value(name string) interface{} { + return c.flagSet.Lookup(name).Value.(flag.Getter).Get() +} + // Args contains apps console arguments type Args []string @@ -357,156 +234,6 @@ return nil } -func lookupInt(name string, set *flag.FlagSet) int { - f := set.Lookup(name) - if f != nil { - val, err := strconv.ParseInt(f.Value.String(), 0, 64) - if err != nil { - return 0 - } - return int(val) - } - - return 0 -} - -func lookupInt64(name string, set *flag.FlagSet) int64 { - f := set.Lookup(name) - if f != nil { - val, err := strconv.ParseInt(f.Value.String(), 0, 64) - if err != nil { - return 0 - } - return val - } - - return 0 -} - -func lookupUint(name string, set *flag.FlagSet) uint { - f := set.Lookup(name) - if f != nil { - val, err := strconv.ParseUint(f.Value.String(), 0, 64) - if err != nil { - return 0 - } - return uint(val) - } - - return 0 -} - -func lookupUint64(name string, set *flag.FlagSet) uint64 { - f := set.Lookup(name) - if f != nil { - val, err := strconv.ParseUint(f.Value.String(), 0, 64) - if err != nil { - return 0 - } - return val - } - - return 0 -} - -func lookupDuration(name string, set *flag.FlagSet) time.Duration { - f := set.Lookup(name) - if f != nil { - val, err := time.ParseDuration(f.Value.String()) - if err == nil { - return val - } - } - - return 0 -} - -func lookupFloat64(name string, set *flag.FlagSet) float64 { - f := set.Lookup(name) - if f != nil { - val, err := strconv.ParseFloat(f.Value.String(), 64) - if err != nil { - return 0 - } - return val - } - - return 0 -} - -func lookupString(name string, set *flag.FlagSet) string { - f := set.Lookup(name) - if f != nil { - return f.Value.String() - } - - return "" -} - -func lookupStringSlice(name string, set *flag.FlagSet) []string { - f := set.Lookup(name) - if f != nil { - return (f.Value.(*StringSlice)).Value() - - } - - return nil -} - -func lookupIntSlice(name string, set *flag.FlagSet) []int { - f := set.Lookup(name) - if f != nil { - return (f.Value.(*IntSlice)).Value() - - } - - return nil -} - -func lookupInt64Slice(name string, set *flag.FlagSet) []int64 { - f := set.Lookup(name) - if f != nil { - return (f.Value.(*Int64Slice)).Value() - - } - - return nil -} - -func lookupGeneric(name string, set *flag.FlagSet) interface{} { - f := set.Lookup(name) - if f != nil { - return f.Value - } - return nil -} - -func lookupBool(name string, set *flag.FlagSet) bool { - f := set.Lookup(name) - if f != nil { - val, err := strconv.ParseBool(f.Value.String()) - if err != nil { - return false - } - return val - } - - return false -} - -func lookupBoolT(name string, set *flag.FlagSet) bool { - f := set.Lookup(name) - if f != nil { - val, err := strconv.ParseBool(f.Value.String()) - if err != nil { - return true - } - return val - } - - return false -} - func copyFlag(name string, ff *flag.Flag, set *flag.FlagSet) { switch ff.Value.(type) { case *StringSlice:
diff --git a/vendor/github.com/codegangsta/cli/context_test.go b/vendor/github.com/codegangsta/cli/context_test.go index 5c68fdd..a1ab05b 100644 --- a/vendor/github.com/codegangsta/cli/context_test.go +++ b/vendor/github.com/codegangsta/cli/context_test.go
@@ -2,6 +2,7 @@ import ( "flag" + "os" "testing" "time" ) @@ -180,6 +181,52 @@ expect(t, c.IsSet("myflagGlobal"), false) } +// XXX Corresponds to hack in context.IsSet for flags with EnvVar field +// Should be moved to `flag_test` in v2 +func TestContext_IsSet_fromEnv(t *testing.T) { + var ( + timeoutIsSet, tIsSet bool + noEnvVarIsSet, nIsSet bool + passwordIsSet, pIsSet bool + unparsableIsSet, uIsSet bool + ) + + clearenv() + os.Setenv("APP_TIMEOUT_SECONDS", "15.5") + os.Setenv("APP_PASSWORD", "") + a := App{ + Flags: []Flag{ + Float64Flag{Name: "timeout, t", EnvVar: "APP_TIMEOUT_SECONDS"}, + StringFlag{Name: "password, p", EnvVar: "APP_PASSWORD"}, + Float64Flag{Name: "unparsable, u", EnvVar: "APP_UNPARSABLE"}, + Float64Flag{Name: "no-env-var, n"}, + }, + Action: func(ctx *Context) error { + timeoutIsSet = ctx.IsSet("timeout") + tIsSet = ctx.IsSet("t") + passwordIsSet = ctx.IsSet("password") + pIsSet = ctx.IsSet("p") + unparsableIsSet = ctx.IsSet("unparsable") + uIsSet = ctx.IsSet("u") + noEnvVarIsSet = ctx.IsSet("no-env-var") + nIsSet = ctx.IsSet("n") + return nil + }, + } + a.Run([]string{"run"}) + expect(t, timeoutIsSet, true) + expect(t, tIsSet, true) + expect(t, passwordIsSet, true) + expect(t, pIsSet, true) + expect(t, noEnvVarIsSet, false) + expect(t, nIsSet, false) + + os.Setenv("APP_UNPARSABLE", "foobar") + a.Run([]string{"run"}) + expect(t, unparsableIsSet, false) + expect(t, uIsSet, false) +} + func TestContext_GlobalIsSet(t *testing.T) { set := flag.NewFlagSet("test", 0) set.Bool("myflag", false, "doc") @@ -199,6 +246,61 @@ expect(t, c.GlobalIsSet("bogusGlobal"), false) } +// XXX Corresponds to hack in context.IsSet for flags with EnvVar field +// Should be moved to `flag_test` in v2 +func TestContext_GlobalIsSet_fromEnv(t *testing.T) { + var ( + timeoutIsSet, tIsSet bool + noEnvVarIsSet, nIsSet bool + passwordIsSet, pIsSet bool + unparsableIsSet, uIsSet bool + ) + + clearenv() + os.Setenv("APP_TIMEOUT_SECONDS", "15.5") + os.Setenv("APP_PASSWORD", "") + a := App{ + Flags: []Flag{ + Float64Flag{Name: "timeout, t", EnvVar: "APP_TIMEOUT_SECONDS"}, + StringFlag{Name: "password, p", EnvVar: "APP_PASSWORD"}, + Float64Flag{Name: "no-env-var, n"}, + Float64Flag{Name: "unparsable, u", EnvVar: "APP_UNPARSABLE"}, + }, + Commands: []Command{ + { + Name: "hello", + Action: func(ctx *Context) error { + timeoutIsSet = ctx.GlobalIsSet("timeout") + tIsSet = ctx.GlobalIsSet("t") + passwordIsSet = ctx.GlobalIsSet("password") + pIsSet = ctx.GlobalIsSet("p") + unparsableIsSet = ctx.GlobalIsSet("unparsable") + uIsSet = ctx.GlobalIsSet("u") + noEnvVarIsSet = ctx.GlobalIsSet("no-env-var") + nIsSet = ctx.GlobalIsSet("n") + return nil + }, + }, + }, + } + if err := a.Run([]string{"run", "hello"}); err != nil { + t.Logf("error running Run(): %+v", err) + } + expect(t, timeoutIsSet, true) + expect(t, tIsSet, true) + expect(t, passwordIsSet, true) + expect(t, pIsSet, true) + expect(t, noEnvVarIsSet, false) + expect(t, nIsSet, false) + + os.Setenv("APP_UNPARSABLE", "foobar") + if err := a.Run([]string{"run"}); err != nil { + t.Logf("error running Run(): %+v", err) + } + expect(t, unparsableIsSet, false) + expect(t, uIsSet, false) +} + func TestContext_NumFlags(t *testing.T) { set := flag.NewFlagSet("test", 0) set.Bool("myflag", false, "doc")
diff --git a/vendor/github.com/codegangsta/cli/errors.go b/vendor/github.com/codegangsta/cli/errors.go index ea551be..0206ff4 100644 --- a/vendor/github.com/codegangsta/cli/errors.go +++ b/vendor/github.com/codegangsta/cli/errors.go
@@ -24,7 +24,7 @@ return MultiError{Errors: err} } -// Error implents the error interface. +// Error implements the error interface. func (m MultiError) Error() string { errs := make([]string, len(m.Errors)) for i, err := range m.Errors { @@ -34,6 +34,10 @@ return strings.Join(errs, "\n") } +type ErrorFormatter interface { + Format(s fmt.State, verb rune) +} + // ExitCoder is the interface checked by `App` and `Command` for a custom exit // code type ExitCoder interface { @@ -44,11 +48,11 @@ // ExitError fulfills both the builtin `error` interface and `ExitCoder` type ExitError struct { exitCode int - message string + message interface{} } // NewExitError makes a new *ExitError -func NewExitError(message string, exitCode int) *ExitError { +func NewExitError(message interface{}, exitCode int) *ExitError { return &ExitError{ exitCode: exitCode, message: message, @@ -58,7 +62,7 @@ // Error returns the string message, fulfilling the interface required by // `error` func (ee *ExitError) Error() string { - return ee.message + return fmt.Sprintf("%v", ee.message) } // ExitCode returns the exit code, fulfilling the interface required by @@ -78,7 +82,11 @@ if exitErr, ok := err.(ExitCoder); ok { if err.Error() != "" { - fmt.Fprintln(ErrWriter, err) + if _, ok := exitErr.(ErrorFormatter); ok { + fmt.Fprintf(ErrWriter, "%+v\n", err) + } else { + fmt.Fprintln(ErrWriter, err) + } } OsExiter(exitErr.ExitCode()) return @@ -88,5 +96,15 @@ for _, merr := range multiErr.Errors { HandleExitCoder(merr) } + return } + + if err.Error() != "" { + if _, ok := err.(ErrorFormatter); ok { + fmt.Fprintf(ErrWriter, "%+v\n", err) + } else { + fmt.Fprintln(ErrWriter, err) + } + } + OsExiter(1) }
diff --git a/vendor/github.com/codegangsta/cli/errors_test.go b/vendor/github.com/codegangsta/cli/errors_test.go index 8f5f284..131bd38 100644 --- a/vendor/github.com/codegangsta/cli/errors_test.go +++ b/vendor/github.com/codegangsta/cli/errors_test.go
@@ -1,8 +1,9 @@ package cli import ( + "bytes" "errors" - "os" + "fmt" "testing" ) @@ -15,7 +16,7 @@ called = true } - defer func() { OsExiter = os.Exit }() + defer func() { OsExiter = fakeOsExiter }() HandleExitCoder(nil) @@ -32,7 +33,7 @@ called = true } - defer func() { OsExiter = os.Exit }() + defer func() { OsExiter = fakeOsExiter }() HandleExitCoder(NewExitError("galactic perimeter breach", 9)) @@ -49,7 +50,7 @@ called = true } - defer func() { OsExiter = os.Exit }() + defer func() { OsExiter = fakeOsExiter }() exitErr := NewExitError("galactic perimeter breach", 9) err := NewMultiError(errors.New("wowsa"), errors.New("egad"), exitErr) @@ -58,3 +59,99 @@ expect(t, exitCode, 9) expect(t, called, true) } + +func TestHandleExitCoder_ErrorWithMessage(t *testing.T) { + exitCode := 0 + called := false + + OsExiter = func(rc int) { + exitCode = rc + called = true + } + ErrWriter = &bytes.Buffer{} + + defer func() { + OsExiter = fakeOsExiter + ErrWriter = fakeErrWriter + }() + + err := errors.New("gourd havens") + HandleExitCoder(err) + + expect(t, exitCode, 1) + expect(t, called, true) + expect(t, ErrWriter.(*bytes.Buffer).String(), "gourd havens\n") +} + +func TestHandleExitCoder_ErrorWithoutMessage(t *testing.T) { + exitCode := 0 + called := false + + OsExiter = func(rc int) { + exitCode = rc + called = true + } + ErrWriter = &bytes.Buffer{} + + defer func() { + OsExiter = fakeOsExiter + ErrWriter = fakeErrWriter + }() + + err := errors.New("") + HandleExitCoder(err) + + expect(t, exitCode, 1) + expect(t, called, true) + expect(t, ErrWriter.(*bytes.Buffer).String(), "") +} + +// make a stub to not import pkg/errors +type ErrorWithFormat struct { + error +} + +func NewErrorWithFormat(m string) *ErrorWithFormat { + return &ErrorWithFormat{error: errors.New(m)} +} + +func (f *ErrorWithFormat) Format(s fmt.State, verb rune) { + fmt.Fprintf(s, "This the format: %v", f.error) +} + +func TestHandleExitCoder_ErrorWithFormat(t *testing.T) { + called := false + + OsExiter = func(rc int) { + called = true + } + ErrWriter = &bytes.Buffer{} + + defer func() { + OsExiter = fakeOsExiter + ErrWriter = fakeErrWriter + }() + + err := NewErrorWithFormat("I am formatted") + HandleExitCoder(err) + + expect(t, called, true) + expect(t, ErrWriter.(*bytes.Buffer).String(), "This the format: I am formatted\n") +} + +func TestHandleExitCoder_MultiErrorWithFormat(t *testing.T) { + called := false + + OsExiter = func(rc int) { + called = true + } + ErrWriter = &bytes.Buffer{} + + defer func() { OsExiter = fakeOsExiter }() + + err := NewMultiError(NewErrorWithFormat("err1"), NewErrorWithFormat("err2")) + HandleExitCoder(err) + + expect(t, called, true) + expect(t, ErrWriter.(*bytes.Buffer).String(), "This the format: err1\nThis the format: err2\n") +}
diff --git a/vendor/github.com/codegangsta/cli/flag-types.json b/vendor/github.com/codegangsta/cli/flag-types.json new file mode 100644 index 0000000..1223107 --- /dev/null +++ b/vendor/github.com/codegangsta/cli/flag-types.json
@@ -0,0 +1,93 @@ +[ + { + "name": "Bool", + "type": "bool", + "value": false, + "context_default": "false", + "parser": "strconv.ParseBool(f.Value.String())" + }, + { + "name": "BoolT", + "type": "bool", + "value": false, + "doctail": " that is true by default", + "context_default": "false", + "parser": "strconv.ParseBool(f.Value.String())" + }, + { + "name": "Duration", + "type": "time.Duration", + "doctail": " (see https://golang.org/pkg/time/#ParseDuration)", + "context_default": "0", + "parser": "time.ParseDuration(f.Value.String())" + }, + { + "name": "Float64", + "type": "float64", + "context_default": "0", + "parser": "strconv.ParseFloat(f.Value.String(), 64)" + }, + { + "name": "Generic", + "type": "Generic", + "dest": false, + "context_default": "nil", + "context_type": "interface{}" + }, + { + "name": "Int64", + "type": "int64", + "context_default": "0", + "parser": "strconv.ParseInt(f.Value.String(), 0, 64)" + }, + { + "name": "Int", + "type": "int", + "context_default": "0", + "parser": "strconv.ParseInt(f.Value.String(), 0, 64)", + "parser_cast": "int(parsed)" + }, + { + "name": "IntSlice", + "type": "*IntSlice", + "dest": false, + "context_default": "nil", + "context_type": "[]int", + "parser": "(f.Value.(*IntSlice)).Value(), error(nil)" + }, + { + "name": "Int64Slice", + "type": "*Int64Slice", + "dest": false, + "context_default": "nil", + "context_type": "[]int64", + "parser": "(f.Value.(*Int64Slice)).Value(), error(nil)" + }, + { + "name": "String", + "type": "string", + "context_default": "\"\"", + "parser": "f.Value.String(), error(nil)" + }, + { + "name": "StringSlice", + "type": "*StringSlice", + "dest": false, + "context_default": "nil", + "context_type": "[]string", + "parser": "(f.Value.(*StringSlice)).Value(), error(nil)" + }, + { + "name": "Uint64", + "type": "uint64", + "context_default": "0", + "parser": "strconv.ParseUint(f.Value.String(), 0, 64)" + }, + { + "name": "Uint", + "type": "uint", + "context_default": "0", + "parser": "strconv.ParseUint(f.Value.String(), 0, 64)", + "parser_cast": "uint(parsed)" + } +]
diff --git a/vendor/github.com/codegangsta/cli/flag.go b/vendor/github.com/codegangsta/cli/flag.go index f8a28d1..7dd8a2c 100644 --- a/vendor/github.com/codegangsta/cli/flag.go +++ b/vendor/github.com/codegangsta/cli/flag.go
@@ -3,11 +3,11 @@ import ( "flag" "fmt" - "os" "reflect" "runtime" "strconv" "strings" + "syscall" "time" ) @@ -37,6 +37,21 @@ // to display a flag. var FlagStringer FlagStringFunc = stringifyFlag +// FlagsByName is a slice of Flag. +type FlagsByName []Flag + +func (f FlagsByName) Len() int { + return len(f) +} + +func (f FlagsByName) Less(i, j int) bool { + return f[i].GetName() < f[j].GetName() +} + +func (f FlagsByName) Swap(i, j int) { + f[i], f[j] = f[j], f[i] +} + // Flag is a common interface related to parsing flags in cli. // For more advanced flag parsing techniques, it is recommended that // this interface be implemented. @@ -47,13 +62,29 @@ GetName() string } -func flagSet(name string, flags []Flag) *flag.FlagSet { +// errorableFlag is an interface that allows us to return errors during apply +// it allows flags defined in this library to return errors in a fashion backwards compatible +// TODO remove in v2 and modify the existing Flag interface to return errors +type errorableFlag interface { + Flag + + ApplyWithError(*flag.FlagSet) error +} + +func flagSet(name string, flags []Flag) (*flag.FlagSet, error) { set := flag.NewFlagSet(name, flag.ContinueOnError) for _, f := range flags { - f.Apply(set) + //TODO remove in v2 when errorableFlag is removed + if ef, ok := f.(errorableFlag); ok { + if err := ef.ApplyWithError(set); err != nil { + return nil, err + } + } else { + f.Apply(set) + } } - return set + return set, nil } func eachName(longName string, fn func(string)) { @@ -70,31 +101,24 @@ String() string } -// GenericFlag is the flag type for types implementing Generic -type GenericFlag struct { - Name string - Value Generic - Usage string - EnvVar string - Hidden bool -} - -// String returns the string representation of the generic flag to display the -// help text to the user (uses the String() method of the generic flag to show -// the value) -func (f GenericFlag) String() string { - return FlagStringer(f) -} - // Apply takes the flagset and calls Set on the generic flag with the value // provided by the user for parsing by the flag +// Ignores parsing errors func (f GenericFlag) Apply(set *flag.FlagSet) { + f.ApplyWithError(set) +} + +// ApplyWithError takes the flagset and calls Set on the generic flag with the value +// provided by the user for parsing by the flag +func (f GenericFlag) ApplyWithError(set *flag.FlagSet) error { val := f.Value if f.EnvVar != "" { for _, envVar := range strings.Split(f.EnvVar, ",") { envVar = strings.TrimSpace(envVar) - if envVal := os.Getenv(envVar); envVal != "" { - val.Set(envVal) + if envVal, ok := syscall.Getenv(envVar); ok { + if err := val.Set(envVal); err != nil { + return fmt.Errorf("could not parse %s as value for flag %s: %s", envVal, f.Name, err) + } break } } @@ -103,14 +127,11 @@ eachName(f.Name, func(name string) { set.Var(f.Value, name, f.Usage) }) + + return nil } -// GetName returns the name of a flag. -func (f GenericFlag) GetName() string { - return f.Name -} - -// StringSlice is an opaque type for []string to satisfy flag.Value +// StringSlice is an opaque type for []string to satisfy flag.Value and flag.Getter type StringSlice []string // Set appends the string value to the list of values @@ -129,31 +150,29 @@ return *f } -// StringSliceFlag is a string flag that can be specified multiple times on the -// command-line -type StringSliceFlag struct { - Name string - Value *StringSlice - Usage string - EnvVar string - Hidden bool -} - -// String returns the usage -func (f StringSliceFlag) String() string { - return FlagStringer(f) +// Get returns the slice of strings set by this flag +func (f *StringSlice) Get() interface{} { + return *f } // Apply populates the flag given the flag set and environment +// Ignores errors func (f StringSliceFlag) Apply(set *flag.FlagSet) { + f.ApplyWithError(set) +} + +// ApplyWithError populates the flag given the flag set and environment +func (f StringSliceFlag) ApplyWithError(set *flag.FlagSet) error { if f.EnvVar != "" { for _, envVar := range strings.Split(f.EnvVar, ",") { envVar = strings.TrimSpace(envVar) - if envVal := os.Getenv(envVar); envVal != "" { + if envVal, ok := syscall.Getenv(envVar); ok { newVal := &StringSlice{} for _, s := range strings.Split(envVal, ",") { s = strings.TrimSpace(s) - newVal.Set(s) + if err := newVal.Set(s); err != nil { + return fmt.Errorf("could not parse %s as string value for flag %s: %s", envVal, f.Name, err) + } } f.Value = newVal break @@ -167,14 +186,11 @@ } set.Var(f.Value, name, f.Usage) }) + + return nil } -// GetName returns the name of a flag. -func (f StringSliceFlag) GetName() string { - return f.Name -} - -// IntSlice is an opaque type for []int to satisfy flag.Value +// IntSlice is an opaque type for []int to satisfy flag.Value and flag.Getter type IntSlice []int // Set parses the value into an integer and appends it to the list of values @@ -197,33 +213,28 @@ return *f } -// IntSliceFlag is an int flag that can be specified multiple times on the -// command-line -type IntSliceFlag struct { - Name string - Value *IntSlice - Usage string - EnvVar string - Hidden bool -} - -// String returns the usage -func (f IntSliceFlag) String() string { - return FlagStringer(f) +// Get returns the slice of ints set by this flag +func (f *IntSlice) Get() interface{} { + return *f } // Apply populates the flag given the flag set and environment +// Ignores errors func (f IntSliceFlag) Apply(set *flag.FlagSet) { + f.ApplyWithError(set) +} + +// ApplyWithError populates the flag given the flag set and environment +func (f IntSliceFlag) ApplyWithError(set *flag.FlagSet) error { if f.EnvVar != "" { for _, envVar := range strings.Split(f.EnvVar, ",") { envVar = strings.TrimSpace(envVar) - if envVal := os.Getenv(envVar); envVal != "" { + if envVal, ok := syscall.Getenv(envVar); ok { newVal := &IntSlice{} for _, s := range strings.Split(envVal, ",") { s = strings.TrimSpace(s) - err := newVal.Set(s) - if err != nil { - fmt.Fprintf(ErrWriter, err.Error()) + if err := newVal.Set(s); err != nil { + return fmt.Errorf("could not parse %s as int slice value for flag %s: %s", envVal, f.Name, err) } } f.Value = newVal @@ -238,14 +249,11 @@ } set.Var(f.Value, name, f.Usage) }) + + return nil } -// GetName returns the name of the flag. -func (f IntSliceFlag) GetName() string { - return f.Name -} - -// Int64Slice is an opaque type for []int to satisfy flag.Value +// Int64Slice is an opaque type for []int to satisfy flag.Value and flag.Getter type Int64Slice []int64 // Set parses the value into an integer and appends it to the list of values @@ -268,33 +276,28 @@ return *f } -// Int64SliceFlag is an int flag that can be specified multiple times on the -// command-line -type Int64SliceFlag struct { - Name string - Value *Int64Slice - Usage string - EnvVar string - Hidden bool -} - -// String returns the usage -func (f Int64SliceFlag) String() string { - return FlagStringer(f) +// Get returns the slice of ints set by this flag +func (f *Int64Slice) Get() interface{} { + return *f } // Apply populates the flag given the flag set and environment +// Ignores errors func (f Int64SliceFlag) Apply(set *flag.FlagSet) { + f.ApplyWithError(set) +} + +// ApplyWithError populates the flag given the flag set and environment +func (f Int64SliceFlag) ApplyWithError(set *flag.FlagSet) error { if f.EnvVar != "" { for _, envVar := range strings.Split(f.EnvVar, ",") { envVar = strings.TrimSpace(envVar) - if envVal := os.Getenv(envVar); envVal != "" { + if envVal, ok := syscall.Getenv(envVar); ok { newVal := &Int64Slice{} for _, s := range strings.Split(envVal, ",") { s = strings.TrimSpace(s) - err := newVal.Set(s) - if err != nil { - fmt.Fprintf(ErrWriter, err.Error()) + if err := newVal.Set(s); err != nil { + return fmt.Errorf("could not parse %s as int64 slice value for flag %s: %s", envVal, f.Name, err) } } f.Value = newVal @@ -309,38 +312,33 @@ } set.Var(f.Value, name, f.Usage) }) -} - -// GetName returns the name of the flag. -func (f Int64SliceFlag) GetName() string { - return f.Name -} - -// BoolFlag is a switch that defaults to false -type BoolFlag struct { - Name string - Usage string - EnvVar string - Destination *bool - Hidden bool -} - -// String returns a readable representation of this value (for usage defaults) -func (f BoolFlag) String() string { - return FlagStringer(f) + return nil } // Apply populates the flag given the flag set and environment +// Ignores errors func (f BoolFlag) Apply(set *flag.FlagSet) { + f.ApplyWithError(set) +} + +// ApplyWithError populates the flag given the flag set and environment +func (f BoolFlag) ApplyWithError(set *flag.FlagSet) error { val := false if f.EnvVar != "" { for _, envVar := range strings.Split(f.EnvVar, ",") { envVar = strings.TrimSpace(envVar) - if envVal := os.Getenv(envVar); envVal != "" { - envValBool, err := strconv.ParseBool(envVal) - if err == nil { - val = envValBool + if envVal, ok := syscall.Getenv(envVar); ok { + if envVal == "" { + val = false + break } + + envValBool, err := strconv.ParseBool(envVal) + if err != nil { + return fmt.Errorf("could not parse %s as bool value for flag %s: %s", envVal, f.Name, err) + } + + val = envValBool break } } @@ -353,40 +351,35 @@ } set.Bool(name, val, f.Usage) }) -} -// GetName returns the name of the flag. -func (f BoolFlag) GetName() string { - return f.Name -} - -// BoolTFlag this represents a boolean flag that is true by default, but can -// still be set to false by --some-flag=false -type BoolTFlag struct { - Name string - Usage string - EnvVar string - Destination *bool - Hidden bool -} - -// String returns a readable representation of this value (for usage defaults) -func (f BoolTFlag) String() string { - return FlagStringer(f) + return nil } // Apply populates the flag given the flag set and environment +// Ignores errors func (f BoolTFlag) Apply(set *flag.FlagSet) { + f.ApplyWithError(set) +} + +// ApplyWithError populates the flag given the flag set and environment +func (f BoolTFlag) ApplyWithError(set *flag.FlagSet) error { val := true if f.EnvVar != "" { for _, envVar := range strings.Split(f.EnvVar, ",") { envVar = strings.TrimSpace(envVar) - if envVal := os.Getenv(envVar); envVal != "" { - envValBool, err := strconv.ParseBool(envVal) - if err == nil { - val = envValBool + if envVal, ok := syscall.Getenv(envVar); ok { + if envVal == "" { + val = false break } + + envValBool, err := strconv.ParseBool(envVal) + if err != nil { + return fmt.Errorf("could not parse %s as bool value for flag %s: %s", envVal, f.Name, err) + } + + val = envValBool + break } } } @@ -398,34 +391,22 @@ } set.Bool(name, val, f.Usage) }) -} -// GetName returns the name of the flag. -func (f BoolTFlag) GetName() string { - return f.Name -} - -// StringFlag represents a flag that takes as string value -type StringFlag struct { - Name string - Value string - Usage string - EnvVar string - Destination *string - Hidden bool -} - -// String returns the usage -func (f StringFlag) String() string { - return FlagStringer(f) + return nil } // Apply populates the flag given the flag set and environment +// Ignores errors func (f StringFlag) Apply(set *flag.FlagSet) { + f.ApplyWithError(set) +} + +// ApplyWithError populates the flag given the flag set and environment +func (f StringFlag) ApplyWithError(set *flag.FlagSet) error { if f.EnvVar != "" { for _, envVar := range strings.Split(f.EnvVar, ",") { envVar = strings.TrimSpace(envVar) - if envVal := os.Getenv(envVar); envVal != "" { + if envVal, ok := syscall.Getenv(envVar); ok { f.Value = envVal break } @@ -439,39 +420,28 @@ } set.String(name, f.Value, f.Usage) }) -} -// GetName returns the name of the flag. -func (f StringFlag) GetName() string { - return f.Name -} - -// IntFlag is a flag that takes an integer -type IntFlag struct { - Name string - Value int - Usage string - EnvVar string - Destination *int - Hidden bool -} - -// String returns the usage -func (f IntFlag) String() string { - return FlagStringer(f) + return nil } // Apply populates the flag given the flag set and environment +// Ignores errors func (f IntFlag) Apply(set *flag.FlagSet) { + f.ApplyWithError(set) +} + +// ApplyWithError populates the flag given the flag set and environment +func (f IntFlag) ApplyWithError(set *flag.FlagSet) error { if f.EnvVar != "" { for _, envVar := range strings.Split(f.EnvVar, ",") { envVar = strings.TrimSpace(envVar) - if envVal := os.Getenv(envVar); envVal != "" { + if envVal, ok := syscall.Getenv(envVar); ok { envValInt, err := strconv.ParseInt(envVal, 0, 64) - if err == nil { - f.Value = int(envValInt) - break + if err != nil { + return fmt.Errorf("could not parse %s as int value for flag %s: %s", envVal, f.Name, err) } + f.Value = int(envValInt) + break } } } @@ -483,39 +453,29 @@ } set.Int(name, f.Value, f.Usage) }) -} -// GetName returns the name of the flag. -func (f IntFlag) GetName() string { - return f.Name -} - -// Int64Flag is a flag that takes a 64-bit integer -type Int64Flag struct { - Name string - Value int64 - Usage string - EnvVar string - Destination *int64 - Hidden bool -} - -// String returns the usage -func (f Int64Flag) String() string { - return FlagStringer(f) + return nil } // Apply populates the flag given the flag set and environment +// Ignores errors func (f Int64Flag) Apply(set *flag.FlagSet) { + f.ApplyWithError(set) +} + +// ApplyWithError populates the flag given the flag set and environment +func (f Int64Flag) ApplyWithError(set *flag.FlagSet) error { if f.EnvVar != "" { for _, envVar := range strings.Split(f.EnvVar, ",") { envVar = strings.TrimSpace(envVar) - if envVal := os.Getenv(envVar); envVal != "" { + if envVal, ok := syscall.Getenv(envVar); ok { envValInt, err := strconv.ParseInt(envVal, 0, 64) - if err == nil { - f.Value = envValInt - break + if err != nil { + return fmt.Errorf("could not parse %s as int value for flag %s: %s", envVal, f.Name, err) } + + f.Value = envValInt + break } } } @@ -527,39 +487,29 @@ } set.Int64(name, f.Value, f.Usage) }) -} -// GetName returns the name of the flag. -func (f Int64Flag) GetName() string { - return f.Name -} - -// UintFlag is a flag that takes an unsigned integer -type UintFlag struct { - Name string - Value uint - Usage string - EnvVar string - Destination *uint - Hidden bool -} - -// String returns the usage -func (f UintFlag) String() string { - return FlagStringer(f) + return nil } // Apply populates the flag given the flag set and environment +// Ignores errors func (f UintFlag) Apply(set *flag.FlagSet) { + f.ApplyWithError(set) +} + +// ApplyWithError populates the flag given the flag set and environment +func (f UintFlag) ApplyWithError(set *flag.FlagSet) error { if f.EnvVar != "" { for _, envVar := range strings.Split(f.EnvVar, ",") { envVar = strings.TrimSpace(envVar) - if envVal := os.Getenv(envVar); envVal != "" { + if envVal, ok := syscall.Getenv(envVar); ok { envValInt, err := strconv.ParseUint(envVal, 0, 64) - if err == nil { - f.Value = uint(envValInt) - break + if err != nil { + return fmt.Errorf("could not parse %s as uint value for flag %s: %s", envVal, f.Name, err) } + + f.Value = uint(envValInt) + break } } } @@ -571,39 +521,29 @@ } set.Uint(name, f.Value, f.Usage) }) -} -// GetName returns the name of the flag. -func (f UintFlag) GetName() string { - return f.Name -} - -// Uint64Flag is a flag that takes an unsigned 64-bit integer -type Uint64Flag struct { - Name string - Value uint64 - Usage string - EnvVar string - Destination *uint64 - Hidden bool -} - -// String returns the usage -func (f Uint64Flag) String() string { - return FlagStringer(f) + return nil } // Apply populates the flag given the flag set and environment +// Ignores errors func (f Uint64Flag) Apply(set *flag.FlagSet) { + f.ApplyWithError(set) +} + +// ApplyWithError populates the flag given the flag set and environment +func (f Uint64Flag) ApplyWithError(set *flag.FlagSet) error { if f.EnvVar != "" { for _, envVar := range strings.Split(f.EnvVar, ",") { envVar = strings.TrimSpace(envVar) - if envVal := os.Getenv(envVar); envVal != "" { + if envVal, ok := syscall.Getenv(envVar); ok { envValInt, err := strconv.ParseUint(envVal, 0, 64) - if err == nil { - f.Value = uint64(envValInt) - break + if err != nil { + return fmt.Errorf("could not parse %s as uint64 value for flag %s: %s", envVal, f.Name, err) } + + f.Value = uint64(envValInt) + break } } } @@ -615,40 +555,29 @@ } set.Uint64(name, f.Value, f.Usage) }) -} -// GetName returns the name of the flag. -func (f Uint64Flag) GetName() string { - return f.Name -} - -// DurationFlag is a flag that takes a duration specified in Go's duration -// format: https://golang.org/pkg/time/#ParseDuration -type DurationFlag struct { - Name string - Value time.Duration - Usage string - EnvVar string - Destination *time.Duration - Hidden bool -} - -// String returns a readable representation of this value (for usage defaults) -func (f DurationFlag) String() string { - return FlagStringer(f) + return nil } // Apply populates the flag given the flag set and environment +// Ignores errors func (f DurationFlag) Apply(set *flag.FlagSet) { + f.ApplyWithError(set) +} + +// ApplyWithError populates the flag given the flag set and environment +func (f DurationFlag) ApplyWithError(set *flag.FlagSet) error { if f.EnvVar != "" { for _, envVar := range strings.Split(f.EnvVar, ",") { envVar = strings.TrimSpace(envVar) - if envVal := os.Getenv(envVar); envVal != "" { + if envVal, ok := syscall.Getenv(envVar); ok { envValDuration, err := time.ParseDuration(envVal) - if err == nil { - f.Value = envValDuration - break + if err != nil { + return fmt.Errorf("could not parse %s as duration for flag %s: %s", envVal, f.Name, err) } + + f.Value = envValDuration + break } } } @@ -660,38 +589,29 @@ } set.Duration(name, f.Value, f.Usage) }) -} -// GetName returns the name of the flag. -func (f DurationFlag) GetName() string { - return f.Name -} - -// Float64Flag is a flag that takes an float value -type Float64Flag struct { - Name string - Value float64 - Usage string - EnvVar string - Destination *float64 - Hidden bool -} - -// String returns the usage -func (f Float64Flag) String() string { - return FlagStringer(f) + return nil } // Apply populates the flag given the flag set and environment +// Ignores errors func (f Float64Flag) Apply(set *flag.FlagSet) { + f.ApplyWithError(set) +} + +// ApplyWithError populates the flag given the flag set and environment +func (f Float64Flag) ApplyWithError(set *flag.FlagSet) error { if f.EnvVar != "" { for _, envVar := range strings.Split(f.EnvVar, ",") { envVar = strings.TrimSpace(envVar) - if envVal := os.Getenv(envVar); envVal != "" { + if envVal, ok := syscall.Getenv(envVar); ok { envValFloat, err := strconv.ParseFloat(envVal, 10) - if err == nil { - f.Value = float64(envValFloat) + if err != nil { + return fmt.Errorf("could not parse %s as float64 value for flag %s: %s", envVal, f.Name, err) } + + f.Value = float64(envValFloat) + break } } } @@ -703,11 +623,8 @@ } set.Float64(name, f.Value, f.Usage) }) -} -// GetName returns the name of the flag. -func (f Float64Flag) GetName() string { - return f.Name + return nil } func visibleFlags(fl []Flag) []Flag {
diff --git a/vendor/github.com/codegangsta/cli/flag_generated.go b/vendor/github.com/codegangsta/cli/flag_generated.go new file mode 100644 index 0000000..491b619 --- /dev/null +++ b/vendor/github.com/codegangsta/cli/flag_generated.go
@@ -0,0 +1,627 @@ +package cli + +import ( + "flag" + "strconv" + "time" +) + +// WARNING: This file is generated! + +// BoolFlag is a flag with type bool +type BoolFlag struct { + Name string + Usage string + EnvVar string + Hidden bool + Destination *bool +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f BoolFlag) String() string { + return FlagStringer(f) +} + +// GetName returns the name of the flag +func (f BoolFlag) GetName() string { + return f.Name +} + +// Bool looks up the value of a local BoolFlag, returns +// false if not found +func (c *Context) Bool(name string) bool { + return lookupBool(name, c.flagSet) +} + +// GlobalBool looks up the value of a global BoolFlag, returns +// false if not found +func (c *Context) GlobalBool(name string) bool { + if fs := lookupGlobalFlagSet(name, c); fs != nil { + return lookupBool(name, fs) + } + return false +} + +func lookupBool(name string, set *flag.FlagSet) bool { + f := set.Lookup(name) + if f != nil { + parsed, err := strconv.ParseBool(f.Value.String()) + if err != nil { + return false + } + return parsed + } + return false +} + +// BoolTFlag is a flag with type bool that is true by default +type BoolTFlag struct { + Name string + Usage string + EnvVar string + Hidden bool + Destination *bool +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f BoolTFlag) String() string { + return FlagStringer(f) +} + +// GetName returns the name of the flag +func (f BoolTFlag) GetName() string { + return f.Name +} + +// BoolT looks up the value of a local BoolTFlag, returns +// false if not found +func (c *Context) BoolT(name string) bool { + return lookupBoolT(name, c.flagSet) +} + +// GlobalBoolT looks up the value of a global BoolTFlag, returns +// false if not found +func (c *Context) GlobalBoolT(name string) bool { + if fs := lookupGlobalFlagSet(name, c); fs != nil { + return lookupBoolT(name, fs) + } + return false +} + +func lookupBoolT(name string, set *flag.FlagSet) bool { + f := set.Lookup(name) + if f != nil { + parsed, err := strconv.ParseBool(f.Value.String()) + if err != nil { + return false + } + return parsed + } + return false +} + +// DurationFlag is a flag with type time.Duration (see https://golang.org/pkg/time/#ParseDuration) +type DurationFlag struct { + Name string + Usage string + EnvVar string + Hidden bool + Value time.Duration + Destination *time.Duration +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f DurationFlag) String() string { + return FlagStringer(f) +} + +// GetName returns the name of the flag +func (f DurationFlag) GetName() string { + return f.Name +} + +// Duration looks up the value of a local DurationFlag, returns +// 0 if not found +func (c *Context) Duration(name string) time.Duration { + return lookupDuration(name, c.flagSet) +} + +// GlobalDuration looks up the value of a global DurationFlag, returns +// 0 if not found +func (c *Context) GlobalDuration(name string) time.Duration { + if fs := lookupGlobalFlagSet(name, c); fs != nil { + return lookupDuration(name, fs) + } + return 0 +} + +func lookupDuration(name string, set *flag.FlagSet) time.Duration { + f := set.Lookup(name) + if f != nil { + parsed, err := time.ParseDuration(f.Value.String()) + if err != nil { + return 0 + } + return parsed + } + return 0 +} + +// Float64Flag is a flag with type float64 +type Float64Flag struct { + Name string + Usage string + EnvVar string + Hidden bool + Value float64 + Destination *float64 +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f Float64Flag) String() string { + return FlagStringer(f) +} + +// GetName returns the name of the flag +func (f Float64Flag) GetName() string { + return f.Name +} + +// Float64 looks up the value of a local Float64Flag, returns +// 0 if not found +func (c *Context) Float64(name string) float64 { + return lookupFloat64(name, c.flagSet) +} + +// GlobalFloat64 looks up the value of a global Float64Flag, returns +// 0 if not found +func (c *Context) GlobalFloat64(name string) float64 { + if fs := lookupGlobalFlagSet(name, c); fs != nil { + return lookupFloat64(name, fs) + } + return 0 +} + +func lookupFloat64(name string, set *flag.FlagSet) float64 { + f := set.Lookup(name) + if f != nil { + parsed, err := strconv.ParseFloat(f.Value.String(), 64) + if err != nil { + return 0 + } + return parsed + } + return 0 +} + +// GenericFlag is a flag with type Generic +type GenericFlag struct { + Name string + Usage string + EnvVar string + Hidden bool + Value Generic +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f GenericFlag) String() string { + return FlagStringer(f) +} + +// GetName returns the name of the flag +func (f GenericFlag) GetName() string { + return f.Name +} + +// Generic looks up the value of a local GenericFlag, returns +// nil if not found +func (c *Context) Generic(name string) interface{} { + return lookupGeneric(name, c.flagSet) +} + +// GlobalGeneric looks up the value of a global GenericFlag, returns +// nil if not found +func (c *Context) GlobalGeneric(name string) interface{} { + if fs := lookupGlobalFlagSet(name, c); fs != nil { + return lookupGeneric(name, fs) + } + return nil +} + +func lookupGeneric(name string, set *flag.FlagSet) interface{} { + f := set.Lookup(name) + if f != nil { + parsed, err := f.Value, error(nil) + if err != nil { + return nil + } + return parsed + } + return nil +} + +// Int64Flag is a flag with type int64 +type Int64Flag struct { + Name string + Usage string + EnvVar string + Hidden bool + Value int64 + Destination *int64 +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f Int64Flag) String() string { + return FlagStringer(f) +} + +// GetName returns the name of the flag +func (f Int64Flag) GetName() string { + return f.Name +} + +// Int64 looks up the value of a local Int64Flag, returns +// 0 if not found +func (c *Context) Int64(name string) int64 { + return lookupInt64(name, c.flagSet) +} + +// GlobalInt64 looks up the value of a global Int64Flag, returns +// 0 if not found +func (c *Context) GlobalInt64(name string) int64 { + if fs := lookupGlobalFlagSet(name, c); fs != nil { + return lookupInt64(name, fs) + } + return 0 +} + +func lookupInt64(name string, set *flag.FlagSet) int64 { + f := set.Lookup(name) + if f != nil { + parsed, err := strconv.ParseInt(f.Value.String(), 0, 64) + if err != nil { + return 0 + } + return parsed + } + return 0 +} + +// IntFlag is a flag with type int +type IntFlag struct { + Name string + Usage string + EnvVar string + Hidden bool + Value int + Destination *int +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f IntFlag) String() string { + return FlagStringer(f) +} + +// GetName returns the name of the flag +func (f IntFlag) GetName() string { + return f.Name +} + +// Int looks up the value of a local IntFlag, returns +// 0 if not found +func (c *Context) Int(name string) int { + return lookupInt(name, c.flagSet) +} + +// GlobalInt looks up the value of a global IntFlag, returns +// 0 if not found +func (c *Context) GlobalInt(name string) int { + if fs := lookupGlobalFlagSet(name, c); fs != nil { + return lookupInt(name, fs) + } + return 0 +} + +func lookupInt(name string, set *flag.FlagSet) int { + f := set.Lookup(name) + if f != nil { + parsed, err := strconv.ParseInt(f.Value.String(), 0, 64) + if err != nil { + return 0 + } + return int(parsed) + } + return 0 +} + +// IntSliceFlag is a flag with type *IntSlice +type IntSliceFlag struct { + Name string + Usage string + EnvVar string + Hidden bool + Value *IntSlice +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f IntSliceFlag) String() string { + return FlagStringer(f) +} + +// GetName returns the name of the flag +func (f IntSliceFlag) GetName() string { + return f.Name +} + +// IntSlice looks up the value of a local IntSliceFlag, returns +// nil if not found +func (c *Context) IntSlice(name string) []int { + return lookupIntSlice(name, c.flagSet) +} + +// GlobalIntSlice looks up the value of a global IntSliceFlag, returns +// nil if not found +func (c *Context) GlobalIntSlice(name string) []int { + if fs := lookupGlobalFlagSet(name, c); fs != nil { + return lookupIntSlice(name, fs) + } + return nil +} + +func lookupIntSlice(name string, set *flag.FlagSet) []int { + f := set.Lookup(name) + if f != nil { + parsed, err := (f.Value.(*IntSlice)).Value(), error(nil) + if err != nil { + return nil + } + return parsed + } + return nil +} + +// Int64SliceFlag is a flag with type *Int64Slice +type Int64SliceFlag struct { + Name string + Usage string + EnvVar string + Hidden bool + Value *Int64Slice +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f Int64SliceFlag) String() string { + return FlagStringer(f) +} + +// GetName returns the name of the flag +func (f Int64SliceFlag) GetName() string { + return f.Name +} + +// Int64Slice looks up the value of a local Int64SliceFlag, returns +// nil if not found +func (c *Context) Int64Slice(name string) []int64 { + return lookupInt64Slice(name, c.flagSet) +} + +// GlobalInt64Slice looks up the value of a global Int64SliceFlag, returns +// nil if not found +func (c *Context) GlobalInt64Slice(name string) []int64 { + if fs := lookupGlobalFlagSet(name, c); fs != nil { + return lookupInt64Slice(name, fs) + } + return nil +} + +func lookupInt64Slice(name string, set *flag.FlagSet) []int64 { + f := set.Lookup(name) + if f != nil { + parsed, err := (f.Value.(*Int64Slice)).Value(), error(nil) + if err != nil { + return nil + } + return parsed + } + return nil +} + +// StringFlag is a flag with type string +type StringFlag struct { + Name string + Usage string + EnvVar string + Hidden bool + Value string + Destination *string +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f StringFlag) String() string { + return FlagStringer(f) +} + +// GetName returns the name of the flag +func (f StringFlag) GetName() string { + return f.Name +} + +// String looks up the value of a local StringFlag, returns +// "" if not found +func (c *Context) String(name string) string { + return lookupString(name, c.flagSet) +} + +// GlobalString looks up the value of a global StringFlag, returns +// "" if not found +func (c *Context) GlobalString(name string) string { + if fs := lookupGlobalFlagSet(name, c); fs != nil { + return lookupString(name, fs) + } + return "" +} + +func lookupString(name string, set *flag.FlagSet) string { + f := set.Lookup(name) + if f != nil { + parsed, err := f.Value.String(), error(nil) + if err != nil { + return "" + } + return parsed + } + return "" +} + +// StringSliceFlag is a flag with type *StringSlice +type StringSliceFlag struct { + Name string + Usage string + EnvVar string + Hidden bool + Value *StringSlice +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f StringSliceFlag) String() string { + return FlagStringer(f) +} + +// GetName returns the name of the flag +func (f StringSliceFlag) GetName() string { + return f.Name +} + +// StringSlice looks up the value of a local StringSliceFlag, returns +// nil if not found +func (c *Context) StringSlice(name string) []string { + return lookupStringSlice(name, c.flagSet) +} + +// GlobalStringSlice looks up the value of a global StringSliceFlag, returns +// nil if not found +func (c *Context) GlobalStringSlice(name string) []string { + if fs := lookupGlobalFlagSet(name, c); fs != nil { + return lookupStringSlice(name, fs) + } + return nil +} + +func lookupStringSlice(name string, set *flag.FlagSet) []string { + f := set.Lookup(name) + if f != nil { + parsed, err := (f.Value.(*StringSlice)).Value(), error(nil) + if err != nil { + return nil + } + return parsed + } + return nil +} + +// Uint64Flag is a flag with type uint64 +type Uint64Flag struct { + Name string + Usage string + EnvVar string + Hidden bool + Value uint64 + Destination *uint64 +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f Uint64Flag) String() string { + return FlagStringer(f) +} + +// GetName returns the name of the flag +func (f Uint64Flag) GetName() string { + return f.Name +} + +// Uint64 looks up the value of a local Uint64Flag, returns +// 0 if not found +func (c *Context) Uint64(name string) uint64 { + return lookupUint64(name, c.flagSet) +} + +// GlobalUint64 looks up the value of a global Uint64Flag, returns +// 0 if not found +func (c *Context) GlobalUint64(name string) uint64 { + if fs := lookupGlobalFlagSet(name, c); fs != nil { + return lookupUint64(name, fs) + } + return 0 +} + +func lookupUint64(name string, set *flag.FlagSet) uint64 { + f := set.Lookup(name) + if f != nil { + parsed, err := strconv.ParseUint(f.Value.String(), 0, 64) + if err != nil { + return 0 + } + return parsed + } + return 0 +} + +// UintFlag is a flag with type uint +type UintFlag struct { + Name string + Usage string + EnvVar string + Hidden bool + Value uint + Destination *uint +} + +// String returns a readable representation of this value +// (for usage defaults) +func (f UintFlag) String() string { + return FlagStringer(f) +} + +// GetName returns the name of the flag +func (f UintFlag) GetName() string { + return f.Name +} + +// Uint looks up the value of a local UintFlag, returns +// 0 if not found +func (c *Context) Uint(name string) uint { + return lookupUint(name, c.flagSet) +} + +// GlobalUint looks up the value of a global UintFlag, returns +// 0 if not found +func (c *Context) GlobalUint(name string) uint { + if fs := lookupGlobalFlagSet(name, c); fs != nil { + return lookupUint(name, fs) + } + return 0 +} + +func lookupUint(name string, set *flag.FlagSet) uint { + f := set.Lookup(name) + if f != nil { + parsed, err := strconv.ParseUint(f.Value.String(), 0, 64) + if err != nil { + return 0 + } + return uint(parsed) + } + return 0 +}
diff --git a/vendor/github.com/codegangsta/cli/flag_test.go b/vendor/github.com/codegangsta/cli/flag_test.go index a7afcc4..0dd8654 100644 --- a/vendor/github.com/codegangsta/cli/flag_test.go +++ b/vendor/github.com/codegangsta/cli/flag_test.go
@@ -29,6 +29,81 @@ } } +func TestFlagsFromEnv(t *testing.T) { + var flagTests = []struct { + input string + output interface{} + flag Flag + err error + }{ + {"", false, BoolFlag{Name: "debug", EnvVar: "DEBUG"}, nil}, + {"1", true, BoolFlag{Name: "debug", EnvVar: "DEBUG"}, nil}, + {"false", false, BoolFlag{Name: "debug", EnvVar: "DEBUG"}, nil}, + {"foobar", true, BoolFlag{Name: "debug", EnvVar: "DEBUG"}, fmt.Errorf(`could not parse foobar as bool value for flag debug: strconv.ParseBool: parsing "foobar": invalid syntax`)}, + + {"", false, BoolTFlag{Name: "debug", EnvVar: "DEBUG"}, nil}, + {"1", true, BoolTFlag{Name: "debug", EnvVar: "DEBUG"}, nil}, + {"false", false, BoolTFlag{Name: "debug", EnvVar: "DEBUG"}, nil}, + {"foobar", true, BoolTFlag{Name: "debug", EnvVar: "DEBUG"}, fmt.Errorf(`could not parse foobar as bool value for flag debug: strconv.ParseBool: parsing "foobar": invalid syntax`)}, + + {"1s", 1 * time.Second, DurationFlag{Name: "time", EnvVar: "TIME"}, nil}, + {"foobar", false, DurationFlag{Name: "time", EnvVar: "TIME"}, fmt.Errorf(`could not parse foobar as duration for flag time: time: invalid duration foobar`)}, + + {"1.2", 1.2, Float64Flag{Name: "seconds", EnvVar: "SECONDS"}, nil}, + {"1", 1.0, Float64Flag{Name: "seconds", EnvVar: "SECONDS"}, nil}, + {"foobar", 0, Float64Flag{Name: "seconds", EnvVar: "SECONDS"}, fmt.Errorf(`could not parse foobar as float64 value for flag seconds: strconv.ParseFloat: parsing "foobar": invalid syntax`)}, + + {"1", int64(1), Int64Flag{Name: "seconds", EnvVar: "SECONDS"}, nil}, + {"1.2", 0, Int64Flag{Name: "seconds", EnvVar: "SECONDS"}, fmt.Errorf(`could not parse 1.2 as int value for flag seconds: strconv.ParseInt: parsing "1.2": invalid syntax`)}, + {"foobar", 0, Int64Flag{Name: "seconds", EnvVar: "SECONDS"}, fmt.Errorf(`could not parse foobar as int value for flag seconds: strconv.ParseInt: parsing "foobar": invalid syntax`)}, + + {"1", 1, IntFlag{Name: "seconds", EnvVar: "SECONDS"}, nil}, + {"1.2", 0, IntFlag{Name: "seconds", EnvVar: "SECONDS"}, fmt.Errorf(`could not parse 1.2 as int value for flag seconds: strconv.ParseInt: parsing "1.2": invalid syntax`)}, + {"foobar", 0, IntFlag{Name: "seconds", EnvVar: "SECONDS"}, fmt.Errorf(`could not parse foobar as int value for flag seconds: strconv.ParseInt: parsing "foobar": invalid syntax`)}, + + {"1,2", IntSlice{1, 2}, IntSliceFlag{Name: "seconds", EnvVar: "SECONDS"}, nil}, + {"1.2,2", IntSlice{}, IntSliceFlag{Name: "seconds", EnvVar: "SECONDS"}, fmt.Errorf(`could not parse 1.2,2 as int slice value for flag seconds: strconv.ParseInt: parsing "1.2": invalid syntax`)}, + {"foobar", IntSlice{}, IntSliceFlag{Name: "seconds", EnvVar: "SECONDS"}, fmt.Errorf(`could not parse foobar as int slice value for flag seconds: strconv.ParseInt: parsing "foobar": invalid syntax`)}, + + {"1,2", Int64Slice{1, 2}, Int64SliceFlag{Name: "seconds", EnvVar: "SECONDS"}, nil}, + {"1.2,2", Int64Slice{}, Int64SliceFlag{Name: "seconds", EnvVar: "SECONDS"}, fmt.Errorf(`could not parse 1.2,2 as int64 slice value for flag seconds: strconv.ParseInt: parsing "1.2": invalid syntax`)}, + {"foobar", Int64Slice{}, Int64SliceFlag{Name: "seconds", EnvVar: "SECONDS"}, fmt.Errorf(`could not parse foobar as int64 slice value for flag seconds: strconv.ParseInt: parsing "foobar": invalid syntax`)}, + + {"foo", "foo", StringFlag{Name: "name", EnvVar: "NAME"}, nil}, + + {"foo,bar", StringSlice{"foo", "bar"}, StringSliceFlag{Name: "names", EnvVar: "NAMES"}, nil}, + + {"1", uint(1), UintFlag{Name: "seconds", EnvVar: "SECONDS"}, nil}, + {"1.2", 0, UintFlag{Name: "seconds", EnvVar: "SECONDS"}, fmt.Errorf(`could not parse 1.2 as uint value for flag seconds: strconv.ParseUint: parsing "1.2": invalid syntax`)}, + {"foobar", 0, UintFlag{Name: "seconds", EnvVar: "SECONDS"}, fmt.Errorf(`could not parse foobar as uint value for flag seconds: strconv.ParseUint: parsing "foobar": invalid syntax`)}, + + {"1", uint64(1), Uint64Flag{Name: "seconds", EnvVar: "SECONDS"}, nil}, + {"1.2", 0, Uint64Flag{Name: "seconds", EnvVar: "SECONDS"}, fmt.Errorf(`could not parse 1.2 as uint64 value for flag seconds: strconv.ParseUint: parsing "1.2": invalid syntax`)}, + {"foobar", 0, Uint64Flag{Name: "seconds", EnvVar: "SECONDS"}, fmt.Errorf(`could not parse foobar as uint64 value for flag seconds: strconv.ParseUint: parsing "foobar": invalid syntax`)}, + + {"foo,bar", &Parser{"foo", "bar"}, GenericFlag{Name: "names", Value: &Parser{}, EnvVar: "NAMES"}, nil}, + } + + for _, test := range flagTests { + os.Clearenv() + os.Setenv(reflect.ValueOf(test.flag).FieldByName("EnvVar").String(), test.input) + a := App{ + Flags: []Flag{test.flag}, + Action: func(ctx *Context) error { + if !reflect.DeepEqual(ctx.value(test.flag.GetName()), test.output) { + t.Errorf("expected %+v to be parsed as %+v, instead was %+v", test.input, test.output, ctx.value(test.flag.GetName())) + } + return nil + }, + } + + err := a.Run([]string{"run"}) + if !reflect.DeepEqual(test.err, err) { + t.Errorf("expected error %s, got error %s", test.err, err) + } + } +} + var stringFlagTests = []struct { name string usage string @@ -941,6 +1016,38 @@ a.Run([]string{"run"}) } +func TestParseBoolTFromEnv(t *testing.T) { + var boolTFlagTests = []struct { + input string + output bool + }{ + {"", false}, + {"1", true}, + {"false", false}, + {"true", true}, + } + + for _, test := range boolTFlagTests { + os.Clearenv() + os.Setenv("DEBUG", test.input) + a := App{ + Flags: []Flag{ + BoolTFlag{Name: "debug, d", EnvVar: "DEBUG"}, + }, + Action: func(ctx *Context) error { + if ctx.Bool("debug") != test.output { + t.Errorf("expected %+v to be parsed as %+v, instead was %+v", test.input, test.output, ctx.Bool("debug")) + } + if ctx.Bool("d") != test.output { + t.Errorf("expected %+v to be parsed as %+v, instead was %+v", test.input, test.output, ctx.Bool("d")) + } + return nil + }, + } + a.Run([]string{"run"}) + } +} + func TestParseMultiBoolT(t *testing.T) { a := App{ Flags: []Flag{ @@ -1036,6 +1143,10 @@ return fmt.Sprintf("%s,%s", p[0], p[1]) } +func (p *Parser) Get() interface{} { + return p +} + func TestParseGeneric(t *testing.T) { a := App{ Flags: []Flag{
diff --git a/vendor/github.com/codegangsta/cli/generate-flag-types b/vendor/github.com/codegangsta/cli/generate-flag-types new file mode 100755 index 0000000..7147381 --- /dev/null +++ b/vendor/github.com/codegangsta/cli/generate-flag-types
@@ -0,0 +1,255 @@ +#!/usr/bin/env python +""" +The flag types that ship with the cli library have many things in common, and +so we can take advantage of the `go generate` command to create much of the +source code from a list of definitions. These definitions attempt to cover +the parts that vary between flag types, and should evolve as needed. + +An example of the minimum definition needed is: + + { + "name": "SomeType", + "type": "sometype", + "context_default": "nil" + } + +In this example, the code generated for the `cli` package will include a type +named `SomeTypeFlag` that is expected to wrap a value of type `sometype`. +Fetching values by name via `*cli.Context` will default to a value of `nil`. + +A more complete, albeit somewhat redundant, example showing all available +definition keys is: + + { + "name": "VeryMuchType", + "type": "*VeryMuchType", + "value": true, + "dest": false, + "doctail": " which really only wraps a []float64, oh well!", + "context_type": "[]float64", + "context_default": "nil", + "parser": "parseVeryMuchType(f.Value.String())", + "parser_cast": "[]float64(parsed)" + } + +The meaning of each field is as follows: + + name (string) - The type "name", which will be suffixed with + `Flag` when generating the type definition + for `cli` and the wrapper type for `altsrc` + type (string) - The type that the generated `Flag` type for `cli` + is expected to "contain" as its `.Value` member + value (bool) - Should the generated `cli` type have a `Value` + member? + dest (bool) - Should the generated `cli` type support a + destination pointer? + doctail (string) - Additional docs for the `cli` flag type comment + context_type (string) - The literal type used in the `*cli.Context` + reader func signature + context_default (string) - The literal value used as the default by the + `*cli.Context` reader funcs when no value is + present + parser (string) - Literal code used to parse the flag `f`, + expected to have a return signature of + (value, error) + parser_cast (string) - Literal code used to cast the `parsed` value + returned from the `parser` code +""" + +from __future__ import print_function, unicode_literals + +import argparse +import json +import os +import subprocess +import sys +import tempfile +import textwrap + + +class _FancyFormatter(argparse.ArgumentDefaultsHelpFormatter, + argparse.RawDescriptionHelpFormatter): + pass + + +def main(sysargs=sys.argv[:]): + parser = argparse.ArgumentParser( + description='Generate flag type code!', + formatter_class=_FancyFormatter) + parser.add_argument( + 'package', + type=str, default='cli', choices=_WRITEFUNCS.keys(), + help='Package for which flag types will be generated' + ) + parser.add_argument( + '-i', '--in-json', + type=argparse.FileType('r'), + default=sys.stdin, + help='Input JSON file which defines each type to be generated' + ) + parser.add_argument( + '-o', '--out-go', + type=argparse.FileType('w'), + default=sys.stdout, + help='Output file/stream to which generated source will be written' + ) + parser.epilog = __doc__ + + args = parser.parse_args(sysargs[1:]) + _generate_flag_types(_WRITEFUNCS[args.package], args.out_go, args.in_json) + return 0 + + +def _generate_flag_types(writefunc, output_go, input_json): + types = json.load(input_json) + + tmp = tempfile.NamedTemporaryFile(suffix='.go', delete=False) + writefunc(tmp, types) + tmp.close() + + new_content = subprocess.check_output( + ['goimports', tmp.name] + ).decode('utf-8') + + print(new_content, file=output_go, end='') + output_go.flush() + os.remove(tmp.name) + + +def _set_typedef_defaults(typedef): + typedef.setdefault('doctail', '') + typedef.setdefault('context_type', typedef['type']) + typedef.setdefault('dest', True) + typedef.setdefault('value', True) + typedef.setdefault('parser', 'f.Value, error(nil)') + typedef.setdefault('parser_cast', 'parsed') + + +def _write_cli_flag_types(outfile, types): + _fwrite(outfile, """\ + package cli + + // WARNING: This file is generated! + + """) + + for typedef in types: + _set_typedef_defaults(typedef) + + _fwrite(outfile, """\ + // {name}Flag is a flag with type {type}{doctail} + type {name}Flag struct {{ + Name string + Usage string + EnvVar string + Hidden bool + """.format(**typedef)) + + if typedef['value']: + _fwrite(outfile, """\ + Value {type} + """.format(**typedef)) + + if typedef['dest']: + _fwrite(outfile, """\ + Destination *{type} + """.format(**typedef)) + + _fwrite(outfile, "\n}\n\n") + + _fwrite(outfile, """\ + // String returns a readable representation of this value + // (for usage defaults) + func (f {name}Flag) String() string {{ + return FlagStringer(f) + }} + + // GetName returns the name of the flag + func (f {name}Flag) GetName() string {{ + return f.Name + }} + + // {name} looks up the value of a local {name}Flag, returns + // {context_default} if not found + func (c *Context) {name}(name string) {context_type} {{ + return lookup{name}(name, c.flagSet) + }} + + // Global{name} looks up the value of a global {name}Flag, returns + // {context_default} if not found + func (c *Context) Global{name}(name string) {context_type} {{ + if fs := lookupGlobalFlagSet(name, c); fs != nil {{ + return lookup{name}(name, fs) + }} + return {context_default} + }} + + func lookup{name}(name string, set *flag.FlagSet) {context_type} {{ + f := set.Lookup(name) + if f != nil {{ + parsed, err := {parser} + if err != nil {{ + return {context_default} + }} + return {parser_cast} + }} + return {context_default} + }} + """.format(**typedef)) + + +def _write_altsrc_flag_types(outfile, types): + _fwrite(outfile, """\ + package altsrc + + import ( + "gopkg.in/urfave/cli.v1" + ) + + // WARNING: This file is generated! + + """) + + for typedef in types: + _set_typedef_defaults(typedef) + + _fwrite(outfile, """\ + // {name}Flag is the flag type that wraps cli.{name}Flag to allow + // for other values to be specified + type {name}Flag struct {{ + cli.{name}Flag + set *flag.FlagSet + }} + + // New{name}Flag creates a new {name}Flag + func New{name}Flag(fl cli.{name}Flag) *{name}Flag {{ + return &{name}Flag{{{name}Flag: fl, set: nil}} + }} + + // Apply saves the flagSet for later usage calls, then calls the + // wrapped {name}Flag.Apply + func (f *{name}Flag) Apply(set *flag.FlagSet) {{ + f.set = set + f.{name}Flag.Apply(set) + }} + + // ApplyWithError saves the flagSet for later usage calls, then calls the + // wrapped {name}Flag.ApplyWithError + func (f *{name}Flag) ApplyWithError(set *flag.FlagSet) error {{ + f.set = set + return f.{name}Flag.ApplyWithError(set) + }} + """.format(**typedef)) + + +def _fwrite(outfile, text): + print(textwrap.dedent(text), end='', file=outfile) + + +_WRITEFUNCS = { + 'cli': _write_cli_flag_types, + 'altsrc': _write_altsrc_flag_types +} + +if __name__ == '__main__': + sys.exit(main())
diff --git a/vendor/github.com/codegangsta/cli/help.go b/vendor/github.com/codegangsta/cli/help.go index 0f4cf14..c8c1aee 100644 --- a/vendor/github.com/codegangsta/cli/help.go +++ b/vendor/github.com/codegangsta/cli/help.go
@@ -13,27 +13,31 @@ // cli.go uses text/template to render templates. You can // render custom help text by setting this variable. var AppHelpTemplate = `NAME: - {{.Name}} - {{.Usage}} + {{.Name}}{{if .Usage}} - {{.Usage}}{{end}} USAGE: - {{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}} {{if .VisibleFlags}}[global options]{{end}}{{if .Commands}} command [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}} - {{if .Version}}{{if not .HideVersion}} + {{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}} {{if .VisibleFlags}}[global options]{{end}}{{if .Commands}} command [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Version}}{{if not .HideVersion}} + VERSION: - {{.Version}} - {{end}}{{end}}{{if len .Authors}} -AUTHOR(S): - {{range .Authors}}{{.}}{{end}} - {{end}}{{if .VisibleCommands}} + {{.Version}}{{end}}{{end}}{{if .Description}} + +DESCRIPTION: + {{.Description}}{{end}}{{if len .Authors}} + +AUTHOR{{with $length := len .Authors}}{{if ne 1 $length}}S{{end}}{{end}}: + {{range $index, $author := .Authors}}{{if $index}} + {{end}}{{$author}}{{end}}{{end}}{{if .VisibleCommands}} + COMMANDS:{{range .VisibleCategories}}{{if .Name}} {{.Name}}:{{end}}{{range .VisibleCommands}} - {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}} -{{end}}{{end}}{{if .VisibleFlags}} + {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{end}}{{end}}{{if .VisibleFlags}} + GLOBAL OPTIONS: - {{range .VisibleFlags}}{{.}} - {{end}}{{end}}{{if .Copyright}} + {{range $index, $option := .VisibleFlags}}{{if $index}} + {{end}}{{$option}}{{end}}{{end}}{{if .Copyright}} + COPYRIGHT: - {{.Copyright}} - {{end}} + {{.Copyright}}{{end}} ` // CommandHelpTemplate is the text template for the command help topic. @@ -240,7 +244,7 @@ } func checkSubcommandHelp(c *Context) bool { - if c.GlobalBool("h") || c.GlobalBool("help") { + if c.Bool("h") || c.Bool("help") { ShowSubcommandHelp(c) return true } @@ -248,20 +252,43 @@ return false } -func checkCompletions(c *Context) bool { - if (c.GlobalBool(BashCompletionFlag.Name) || c.Bool(BashCompletionFlag.Name)) && c.App.EnableBashCompletion { - ShowCompletions(c) - return true +func checkShellCompleteFlag(a *App, arguments []string) (bool, []string) { + if !a.EnableBashCompletion { + return false, arguments } - return false + pos := len(arguments) - 1 + lastArg := arguments[pos] + + if lastArg != "--"+BashCompletionFlag.Name { + return false, arguments + } + + return true, arguments[:pos] +} + +func checkCompletions(c *Context) bool { + if !c.shellComplete { + return false + } + + if args := c.Args(); args.Present() { + name := args.First() + if cmd := c.App.Command(name); cmd != nil { + // let the command handle the completion + return false + } + } + + ShowCompletions(c) + return true } func checkCommandCompletions(c *Context, name string) bool { - if c.Bool(BashCompletionFlag.Name) && c.App.EnableBashCompletion { - ShowCommandCompletions(c, name) - return true + if !c.shellComplete { + return false } - return false + ShowCommandCompletions(c, name) + return true }
diff --git a/vendor/github.com/codegangsta/cli/helpers_unix_test.go b/vendor/github.com/codegangsta/cli/helpers_unix_test.go new file mode 100644 index 0000000..ae27fc5 --- /dev/null +++ b/vendor/github.com/codegangsta/cli/helpers_unix_test.go
@@ -0,0 +1,9 @@ +// +build darwin dragonfly freebsd linux netbsd openbsd solaris + +package cli + +import "os" + +func clearenv() { + os.Clearenv() +}
diff --git a/vendor/github.com/codegangsta/cli/helpers_windows_test.go b/vendor/github.com/codegangsta/cli/helpers_windows_test.go new file mode 100644 index 0000000..4eb84f9 --- /dev/null +++ b/vendor/github.com/codegangsta/cli/helpers_windows_test.go
@@ -0,0 +1,20 @@ +package cli + +import ( + "os" + "syscall" +) + +// os.Clearenv() doesn't actually unset variables on Windows +// See: https://github.com/golang/go/issues/17902 +func clearenv() { + for _, s := range os.Environ() { + for j := 1; j < len(s); j++ { + if s[j] == '=' { + keyp, _ := syscall.UTF16PtrFromString(s[0:j]) + syscall.SetEnvironmentVariable(keyp, nil) + break + } + } + } +}
diff --git a/vendor/github.com/codegangsta/cli/runtests b/vendor/github.com/codegangsta/cli/runtests index 0a7b483..ee22bde 100755 --- a/vendor/github.com/codegangsta/cli/runtests +++ b/vendor/github.com/codegangsta/cli/runtests
@@ -18,8 +18,9 @@ targets = { 'vet': _vet, 'test': _test, - 'gfmxr': _gfmxr, + 'gfmrun': _gfmrun, 'toc': _toc, + 'gen': _gen, } parser = argparse.ArgumentParser() @@ -34,7 +35,7 @@ def _test(): if check_output('go version'.split()).split()[2] < 'go1.2': - _run('go test -v .'.split()) + _run('go test -v .') return coverprofiles = [] @@ -51,29 +52,45 @@ ]) combined_name = _combine_coverprofiles(coverprofiles) - _run('go tool cover -func={}'.format(combined_name).split()) + _run('go tool cover -func={}'.format(combined_name)) os.remove(combined_name) -def _gfmxr(): - _run(['gfmxr', '-c', str(_gfmxr_count()), '-s', 'README.md']) +def _gfmrun(): + go_version = check_output('go version'.split()).split()[2] + if go_version < 'go1.3': + print('runtests: skip on {}'.format(go_version), file=sys.stderr) + return + _run(['gfmrun', '-c', str(_gfmrun_count()), '-s', 'README.md']) def _vet(): - _run('go vet ./...'.split()) + _run('go vet ./...') def _toc(): - _run(['node_modules/.bin/markdown-toc', '-i', 'README.md']) - _run(['git', 'diff', '--quiet']) + _run('node_modules/.bin/markdown-toc -i README.md') + _run('git diff --exit-code') + + +def _gen(): + go_version = check_output('go version'.split()).split()[2] + if go_version < 'go1.5': + print('runtests: skip on {}'.format(go_version), file=sys.stderr) + return + + _run('go generate ./...') + _run('git diff --exit-code') def _run(command): + if hasattr(command, 'split'): + command = command.split() print('runtests: {}'.format(' '.join(command)), file=sys.stderr) check_call(command) -def _gfmxr_count(): +def _gfmrun_count(): with open('README.md') as infile: lines = infile.read().splitlines() return len(filter(_is_go_runnable, lines))
diff --git a/vendor/github.com/mitchellh/go-homedir/LICENSE b/vendor/github.com/mitchellh/go-homedir/LICENSE new file mode 100644 index 0000000..f9c841a --- /dev/null +++ b/vendor/github.com/mitchellh/go-homedir/LICENSE
@@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2013 Mitchell Hashimoto + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE.
diff --git a/vendor/github.com/mitchellh/go-homedir/README.md b/vendor/github.com/mitchellh/go-homedir/README.md new file mode 100644 index 0000000..d70706d --- /dev/null +++ b/vendor/github.com/mitchellh/go-homedir/README.md
@@ -0,0 +1,14 @@ +# go-homedir + +This is a Go library for detecting the user's home directory without +the use of cgo, so the library can be used in cross-compilation environments. + +Usage is incredibly simple, just call `homedir.Dir()` to get the home directory +for a user, and `homedir.Expand()` to expand the `~` in a path to the home +directory. + +**Why not just use `os/user`?** The built-in `os/user` package requires +cgo on Darwin systems. This means that any Go code that uses that package +cannot cross compile. But 99% of the time the use for `os/user` is just to +retrieve the home directory, which we can do for the current user without +cgo. This library does that, enabling cross-compilation.
diff --git a/vendor/github.com/mitchellh/go-homedir/homedir.go b/vendor/github.com/mitchellh/go-homedir/homedir.go new file mode 100644 index 0000000..47e1f9e --- /dev/null +++ b/vendor/github.com/mitchellh/go-homedir/homedir.go
@@ -0,0 +1,137 @@ +package homedir + +import ( + "bytes" + "errors" + "os" + "os/exec" + "path/filepath" + "runtime" + "strconv" + "strings" + "sync" +) + +// DisableCache will disable caching of the home directory. Caching is enabled +// by default. +var DisableCache bool + +var homedirCache string +var cacheLock sync.RWMutex + +// Dir returns the home directory for the executing user. +// +// This uses an OS-specific method for discovering the home directory. +// An error is returned if a home directory cannot be detected. +func Dir() (string, error) { + if !DisableCache { + cacheLock.RLock() + cached := homedirCache + cacheLock.RUnlock() + if cached != "" { + return cached, nil + } + } + + cacheLock.Lock() + defer cacheLock.Unlock() + + var result string + var err error + if runtime.GOOS == "windows" { + result, err = dirWindows() + } else { + // Unix-like system, so just assume Unix + result, err = dirUnix() + } + + if err != nil { + return "", err + } + homedirCache = result + return result, nil +} + +// Expand expands the path to include the home directory if the path +// is prefixed with `~`. If it isn't prefixed with `~`, the path is +// returned as-is. +func Expand(path string) (string, error) { + if len(path) == 0 { + return path, nil + } + + if path[0] != '~' { + return path, nil + } + + if len(path) > 1 && path[1] != '/' && path[1] != '\\' { + return "", errors.New("cannot expand user-specific home dir") + } + + dir, err := Dir() + if err != nil { + return "", err + } + + return filepath.Join(dir, path[1:]), nil +} + +func dirUnix() (string, error) { + // First prefer the HOME environmental variable + if home := os.Getenv("HOME"); home != "" { + return home, nil + } + + // If that fails, try getent + var stdout bytes.Buffer + cmd := exec.Command("getent", "passwd", strconv.Itoa(os.Getuid())) + cmd.Stdout = &stdout + if err := cmd.Run(); err != nil { + // If the error is ErrNotFound, we ignore it. Otherwise, return it. + if err != exec.ErrNotFound { + return "", err + } + } else { + if passwd := strings.TrimSpace(stdout.String()); passwd != "" { + // username:password:uid:gid:gecos:home:shell + passwdParts := strings.SplitN(passwd, ":", 7) + if len(passwdParts) > 5 { + return passwdParts[5], nil + } + } + } + + // If all else fails, try the shell + stdout.Reset() + cmd = exec.Command("sh", "-c", "cd && pwd") + cmd.Stdout = &stdout + if err := cmd.Run(); err != nil { + return "", err + } + + result := strings.TrimSpace(stdout.String()) + if result == "" { + return "", errors.New("blank output when reading home directory") + } + + return result, nil +} + +func dirWindows() (string, error) { + // First prefer the HOME environmental variable + if home := os.Getenv("HOME"); home != "" { + return home, nil + } + + drive := os.Getenv("HOMEDRIVE") + path := os.Getenv("HOMEPATH") + home := drive + path + if drive == "" || path == "" { + home = os.Getenv("USERPROFILE") + } + if home == "" { + return "", errors.New("HOMEDRIVE, HOMEPATH, and USERPROFILE are blank") + } + + return home, nil +}
diff --git a/vendor/github.com/mitchellh/go-homedir/homedir_test.go b/vendor/github.com/mitchellh/go-homedir/homedir_test.go new file mode 100644 index 0000000..e4054e7 --- /dev/null +++ b/vendor/github.com/mitchellh/go-homedir/homedir_test.go
@@ -0,0 +1,112 @@ +package homedir + +import ( + "os" + "os/user" + "path/filepath" + "testing" +) + +func patchEnv(key, value string) func() { + bck := os.Getenv(key) + deferFunc := func() { + os.Setenv(key, bck) + } + + os.Setenv(key, value) + return deferFunc +} + +func BenchmarkDir(b *testing.B) { + // We do this for any "warmups" + for i := 0; i < 10; i++ { + Dir() + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + Dir() + } +} + +func TestDir(t *testing.T) { + u, err := user.Current() + if err != nil { + t.Fatalf("err: %s", err) + } + + dir, err := Dir() + if err != nil { + t.Fatalf("err: %s", err) + } + + if u.HomeDir != dir { + t.Fatalf("%#v != %#v", u.HomeDir, dir) + } +} + +func TestExpand(t *testing.T) { + u, err := user.Current() + if err != nil { + t.Fatalf("err: %s", err) + } + + cases := []struct { + Input string + Output string + Err bool + }{ + { + "/foo", + "/foo", + false, + }, + + { + "~/foo", + filepath.Join(u.HomeDir, "foo"), + false, + }, + + { + "", + "", + false, + }, + + { + "~", + u.HomeDir, + false, + }, + + { + "~foo/foo", + "", + true, + }, + } + + for _, tc := range cases { + actual, err := Expand(tc.Input) + if (err != nil) != tc.Err { + t.Fatalf("Input: %#v\n\nErr: %s", tc.Input, err) + } + + if actual != tc.Output { + t.Fatalf("Input: %#v\n\nOutput: %#v", tc.Input, actual) + } + } + + DisableCache = true + defer func() { DisableCache = false }() + defer patchEnv("HOME", "/custom/path/")() + expected := filepath.Join("/", "custom", "path", "foo/bar") + actual, err := Expand("~/foo/bar") + + if err != nil { + t.Errorf("No error is expected, got: %v", err) + } else if actual != expected { + t.Errorf("Expected: %v; actual: %v", expected, actual) + } +}
diff --git a/vendor/gopkg.in/yaml.v2/README.md b/vendor/gopkg.in/yaml.v2/README.md index 7b8bd86..1884de6 100644 --- a/vendor/gopkg.in/yaml.v2/README.md +++ b/vendor/gopkg.in/yaml.v2/README.md
@@ -42,7 +42,7 @@ License ------- -The yaml package is licensed under the LGPL with an exception that allows it to be linked statically. Please see the LICENSE file for details. +The yaml package is licensed under the Apache License 2.0. Please see the LICENSE file for details. Example
diff --git a/vendor/gopkg.in/yaml.v2/decode.go b/vendor/gopkg.in/yaml.v2/decode.go index 085cddc..b13ab9f 100644 --- a/vendor/gopkg.in/yaml.v2/decode.go +++ b/vendor/gopkg.in/yaml.v2/decode.go
@@ -251,7 +251,7 @@ // // If n holds a null value, prepare returns before doing anything. func (d *decoder) prepare(n *node, out reflect.Value) (newout reflect.Value, unmarshaled, good bool) { - if n.tag == yaml_NULL_TAG || n.kind == scalarNode && n.tag == "" && (n.value == "null" || n.value == "") { + if n.tag == yaml_NULL_TAG || n.kind == scalarNode && n.tag == "" && (n.value == "null" || n.value == "" && n.implicit) { return out, false, false } again := true
diff --git a/vendor/gopkg.in/yaml.v2/decode_test.go b/vendor/gopkg.in/yaml.v2/decode_test.go index c159760..3da6fad 100644 --- a/vendor/gopkg.in/yaml.v2/decode_test.go +++ b/vendor/gopkg.in/yaml.v2/decode_test.go
@@ -660,6 +660,7 @@ {`_: BAR!`, "!!str", "BAR!"}, {`_: "BAR!"`, "!!str", "BAR!"}, {"_: !!foo 'BAR!'", "!!foo", "BAR!"}, + {`_: ""`, "!!str", ""}, } var unmarshalerResult = map[int]error{}