Merge pull request #711 from mh-cbon/patch-2
Update glide.yaml.md
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 668b25d..beb3356 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,7 +1,11 @@
# Release 0.13.0 (unreleased)
+## Changed
- #697: Preserve vendor/.git, if it exists.
+## Fixed
+- #736: Find home dir without using cgo (thanks @krancour)
+
# Release 0.12.3 (2016-10-03)
## Fixed
diff --git a/glide.go b/glide.go
index 5f9c14f..ebe0aa0 100644
--- a/glide.go
+++ b/glide.go
@@ -250,7 +250,7 @@
msg.Warn("The --update-vendored flag is deprecated. This now works by default.")
}
if c.String("file") != "" {
- msg.Warn("The --flag flag is deprecated.")
+ msg.Warn("The --file flag is deprecated.")
}
if c.Bool("cache") {
msg.Warn("The --cache flag is deprecated. This now works by default.")
@@ -423,8 +423,8 @@
Name: "install",
ShortName: "i",
Usage: "Install a project's dependencies",
- Description: `This uses the native VCS of each packages to install
- the appropriate version. There are two ways a projects dependencies can
+ Description: `This uses the native VCS of each package to install
+ the appropriate version. There are two ways a project's dependencies can
be installed. When there is a glide.yaml file defining the dependencies but
no lock file (glide.lock) the dependencies are installed using the "update"
command and a glide.lock file is generated pinning all dependencies. If a
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{}