vendor: remove dep and use vndr

Signed-off-by: Antonio Murdaca <runcom@redhat.com>
This commit is contained in:
Antonio Murdaca 2017-06-06 09:19:04 +02:00
parent 16f44674a4
commit 148e72d81e
No known key found for this signature in database
GPG key ID: B2BEAD150DE936B9
16131 changed files with 73815 additions and 4235138 deletions

View file

@ -1,2 +0,0 @@
*.coverprofile
node_modules/

View file

@ -1,39 +0,0 @@
language: go
sudo: false
cache:
directories:
- node_modules
go:
- 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.x
os: osx
- go: 1.7.x
os: osx
before_script:
- 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 gfmrun
- ./runtests toc

View file

@ -1,392 +0,0 @@
# Change Log
**ATTN**: This project uses [semantic versioning](http://semver.org/).
## [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
- testing on OS X
- testing on Windows
- `UintFlag`, `Uint64Flag`, and `Int64Flag` types and supporting code
### Changed
- Use spaces for alignment in help/usage output instead of tabs, making the
output alignment consistent regardless of tab width
### Fixed
- Printing of command aliases in help text
- Printing of visible flags for both struct and struct pointer flags
- Display the `help` subcommand when using `CommandCategories`
- 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`
- `context.GlobalBoolT` was added as an analogue to `context.GlobalBool`
- Support for hiding commands by setting `Hidden: true` -- this will hide the
commands in help output
### Changed
- `Float64Flag`, `IntFlag`, and `DurationFlag` default values are no longer
quoted in help text output.
- All flag types now include `(default: {value})` strings following usage when a
default value can be (reasonably) detected.
- `IntSliceFlag` and `StringSliceFlag` usage strings are now more consistent
with non-slice flag types
- Apps now exit with a code of 3 if an unknown subcommand is specified
(previously they printed "No help topic for...", but still exited 0. This
makes it easier to script around apps built using `cli` since they can trust
that a 0 exit code indicated a successful execution.
- 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
### Changed
- `BashCompletionFlag` (`--enable-bash-completion`) is now omitted from
generated help text via the `Hidden` field
### Fixed
- handling of error values in `HandleAction` and `HandleExitCoder`
## [1.15.0] - 2016-04-30
### Added
- This file!
- Support for placeholders in flag usage strings
- `App.Metadata` map for arbitrary data/state management
- `Set` and `GlobalSet` methods on `*cli.Context` for altering values after
parsing.
- Support for nested lookup of dot-delimited keys in structures loaded from
YAML.
### Changed
- The `App.Action` and `Command.Action` now prefer a return signature of
`func(*cli.Context) error`, as defined by `cli.ActionFunc`. If a non-nil
`error` is returned, there may be two outcomes:
- If the error fulfills `cli.ExitCoder`, then `os.Exit` will be called
automatically
- Else the error is bubbled up and returned from `App.Run`
- Specifying an `Action` with the legacy return signature of
`func(*cli.Context)` will produce a deprecation message to stderr
- Specifying an `Action` that is not a `func` type will produce a non-zero exit
from `App.Run`
- Specifying an `Action` func that has an invalid (input) signature will
produce a non-zero exit from `App.Run`
### Deprecated
- <a name="deprecated-cli-app-runandexitonerror"></a>
`cli.App.RunAndExitOnError`, which should now be done by returning an error
that fulfills `cli.ExitCoder` to `cli.App.Run`.
- <a name="deprecated-cli-app-action-signature"></a> the legacy signature for
`cli.App.Action` of `func(*cli.Context)`, which should now have a return
signature of `func(*cli.Context) error`, as defined by `cli.ActionFunc`.
### Fixed
- Added missing `*cli.Context.GlobalFloat64` method
## [1.14.0] - 2016-04-03 (backfilled 2016-04-25)
### Added
- Codebeat badge
- Support for categorization via `CategorizedHelp` and `Categories` on app.
### Changed
- Use `filepath.Base` instead of `path.Base` in `Name` and `HelpName`.
### Fixed
- Ensure version is not shown in help text when `HideVersion` set.
## [1.13.0] - 2016-03-06 (backfilled 2016-04-25)
### Added
- YAML file input support.
- `NArg` method on context.
## [1.12.0] - 2016-02-17 (backfilled 2016-04-25)
### Added
- Custom usage error handling.
- Custom text support in `USAGE` section of help output.
- Improved help messages for empty strings.
- AppVeyor CI configuration.
### Changed
- Removed `panic` from default help printer func.
- De-duping and optimizations.
### Fixed
- Correctly handle `Before`/`After` at command level when no subcommands.
- Case of literal `-` argument causing flag reordering.
- Environment variable hints on Windows.
- Docs updates.
## [1.11.1] - 2015-12-21 (backfilled 2016-04-25)
### Changed
- Use `path.Base` in `Name` and `HelpName`
- Export `GetName` on flag types.
### Fixed
- Flag parsing when skipping is enabled.
- Test output cleanup.
- Move completion check to account for empty input case.
## [1.11.0] - 2015-11-15 (backfilled 2016-04-25)
### Added
- Destination scan support for flags.
- Testing against `tip` in Travis CI config.
### Changed
- Go version in Travis CI config.
### Fixed
- Removed redundant tests.
- Use correct example naming in tests.
## [1.10.2] - 2015-10-29 (backfilled 2016-04-25)
### Fixed
- Remove unused var in bash completion.
## [1.10.1] - 2015-10-21 (backfilled 2016-04-25)
### Added
- Coverage and reference logos in README.
### Fixed
- Use specified values in help and version parsing.
- Only display app version and help message once.
## [1.10.0] - 2015-10-06 (backfilled 2016-04-25)
### Added
- More tests for existing functionality.
- `ArgsUsage` at app and command level for help text flexibility.
### Fixed
- Honor `HideHelp` and `HideVersion` in `App.Run`.
- Remove juvenile word from README.
## [1.9.0] - 2015-09-08 (backfilled 2016-04-25)
### Added
- `FullName` on command with accompanying help output update.
- Set default `$PROG` in bash completion.
### Changed
- Docs formatting.
### Fixed
- Removed self-referential imports in tests.
## [1.8.0] - 2015-06-30 (backfilled 2016-04-25)
### Added
- Support for `Copyright` at app level.
- `Parent` func at context level to walk up context lineage.
### Fixed
- Global flag processing at top level.
## [1.7.1] - 2015-06-11 (backfilled 2016-04-25)
### Added
- Aggregate errors from `Before`/`After` funcs.
- Doc comments on flag structs.
- Include non-global flags when checking version and help.
- Travis CI config updates.
### Fixed
- Ensure slice type flags have non-nil values.
- Collect global flags from the full command hierarchy.
- Docs prose.
## [1.7.0] - 2015-05-03 (backfilled 2016-04-25)
### Changed
- `HelpPrinter` signature includes output writer.
### Fixed
- Specify go 1.1+ in docs.
- Set `Writer` when running command as app.
## [1.6.0] - 2015-03-23 (backfilled 2016-04-25)
### Added
- Multiple author support.
- `NumFlags` at context level.
- `Aliases` at command level.
### Deprecated
- `ShortName` at command level.
### Fixed
- Subcommand help output.
- Backward compatible support for deprecated `Author` and `Email` fields.
- Docs regarding `Names`/`Aliases`.
## [1.5.0] - 2015-02-20 (backfilled 2016-04-25)
### Added
- `After` hook func support at app and command level.
### Fixed
- Use parsed context when running command as subcommand.
- Docs prose.
## [1.4.1] - 2015-01-09 (backfilled 2016-04-25)
### Added
- Support for hiding `-h / --help` flags, but not `help` subcommand.
- Stop flag parsing after `--`.
### Fixed
- Help text for generic flags to specify single value.
- Use double quotes in output for defaults.
- Use `ParseInt` instead of `ParseUint` for int environment var values.
- Use `0` as base when parsing int environment var values.
## [1.4.0] - 2014-12-12 (backfilled 2016-04-25)
### Added
- Support for environment variable lookup "cascade".
- Support for `Stdout` on app for output redirection.
### Fixed
- Print command help instead of app help in `ShowCommandHelp`.
## [1.3.1] - 2014-11-13 (backfilled 2016-04-25)
### Added
- Docs and example code updates.
### Changed
- Default `-v / --version` flag made optional.
## [1.3.0] - 2014-08-10 (backfilled 2016-04-25)
### Added
- `FlagNames` at context level.
- Exposed `VersionPrinter` var for more control over version output.
- Zsh completion hook.
- `AUTHOR` section in default app help template.
- Contribution guidelines.
- `DurationFlag` type.
## [1.2.0] - 2014-08-02
### Added
- Support for environment variable defaults on flags plus tests.
## [1.1.0] - 2014-07-15
### Added
- Bash completion.
- Optional hiding of built-in help command.
- Optional skipping of flag parsing at command level.
- `Author`, `Email`, and `Compiled` metadata on app.
- `Before` hook func support at app and command level.
- `CommandNotFound` func support at app level.
- Command reference available on context.
- `GenericFlag` type.
- `Float64Flag` type.
- `BoolTFlag` type.
- `IsSet` flag helper on context.
- More flag lookup funcs at context level.
- More tests &amp; docs.
### Changed
- Help template updates to account for presence/absence of flags.
- Separated subcommand help template.
- Exposed `HelpPrinter` var for more control over help output.
## [1.0.0] - 2013-11-01
### Added
- `help` flag in default app flag set and each command flag set.
- Custom handling of argument parsing errors.
- Command lookup by name at app level.
- `StringSliceFlag` type and supporting `StringSlice` type.
- `IntSliceFlag` type and supporting `IntSlice` type.
- Slice type flag lookups by name at context level.
- Export of app and command help functions.
- More tests &amp; docs.
## 0.1.0 - 2013-07-22
### Added
- Initial implementation.
[Unreleased]: https://github.com/urfave/cli/compare/v1.18.0...HEAD
[1.18.0]: https://github.com/urfave/cli/compare/v1.17.0...v1.18.0
[1.17.0]: https://github.com/urfave/cli/compare/v1.16.0...v1.17.0
[1.16.0]: https://github.com/urfave/cli/compare/v1.15.0...v1.16.0
[1.15.0]: https://github.com/urfave/cli/compare/v1.14.0...v1.15.0
[1.14.0]: https://github.com/urfave/cli/compare/v1.13.0...v1.14.0
[1.13.0]: https://github.com/urfave/cli/compare/v1.12.0...v1.13.0
[1.12.0]: https://github.com/urfave/cli/compare/v1.11.1...v1.12.0
[1.11.1]: https://github.com/urfave/cli/compare/v1.11.0...v1.11.1
[1.11.0]: https://github.com/urfave/cli/compare/v1.10.2...v1.11.0
[1.10.2]: https://github.com/urfave/cli/compare/v1.10.1...v1.10.2
[1.10.1]: https://github.com/urfave/cli/compare/v1.10.0...v1.10.1
[1.10.0]: https://github.com/urfave/cli/compare/v1.9.0...v1.10.0
[1.9.0]: https://github.com/urfave/cli/compare/v1.8.0...v1.9.0
[1.8.0]: https://github.com/urfave/cli/compare/v1.7.1...v1.8.0
[1.7.1]: https://github.com/urfave/cli/compare/v1.7.0...v1.7.1
[1.7.0]: https://github.com/urfave/cli/compare/v1.6.0...v1.7.0
[1.6.0]: https://github.com/urfave/cli/compare/v1.5.0...v1.6.0
[1.5.0]: https://github.com/urfave/cli/compare/v1.4.1...v1.5.0
[1.4.1]: https://github.com/urfave/cli/compare/v1.4.0...v1.4.1
[1.4.0]: https://github.com/urfave/cli/compare/v1.3.1...v1.4.0
[1.3.1]: https://github.com/urfave/cli/compare/v1.3.0...v1.3.1
[1.3.0]: https://github.com/urfave/cli/compare/v1.2.0...v1.3.0
[1.2.0]: https://github.com/urfave/cli/compare/v1.1.0...v1.2.0
[1.1.0]: https://github.com/urfave/cli/compare/v1.0.0...v1.1.0
[1.0.0]: https://github.com/urfave/cli/compare/v0.1.0...v1.0.0

View file

@ -1,3 +0,0 @@
package altsrc
//go:generate python ../generate-flag-types altsrc -i ../flag-types.json -o flag_generated.go

View file

@ -1,261 +0,0 @@
package altsrc
import (
"fmt"
"strconv"
"strings"
"syscall"
"gopkg.in/urfave/cli.v1"
)
// FlagInputSourceExtension is an extension interface of cli.Flag that
// allows a value to be set on the existing parsed flags.
type FlagInputSourceExtension interface {
cli.Flag
ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error
}
// ApplyInputSourceValues iterates over all provided flags and
// executes ApplyInputSourceValue on flags implementing the
// FlagInputSourceExtension interface to initialize these flags
// to an alternate input source.
func ApplyInputSourceValues(context *cli.Context, inputSourceContext InputSourceContext, flags []cli.Flag) error {
for _, f := range flags {
inputSourceExtendedFlag, isType := f.(FlagInputSourceExtension)
if isType {
err := inputSourceExtendedFlag.ApplyInputSourceValue(context, inputSourceContext)
if err != nil {
return err
}
}
}
return nil
}
// InitInputSource is used to to setup an InputSourceContext on a cli.Command Before method. It will create a new
// input source based on the func provided. If there is no error it will then apply the new input source to any flags
// that are supported by the input source
func InitInputSource(flags []cli.Flag, createInputSource func() (InputSourceContext, error)) cli.BeforeFunc {
return func(context *cli.Context) error {
inputSource, err := createInputSource()
if err != nil {
return fmt.Errorf("Unable to create input source: inner error: \n'%v'", err.Error())
}
return ApplyInputSourceValues(context, inputSource, flags)
}
}
// InitInputSourceWithContext is used to to setup an InputSourceContext on a cli.Command Before method. It will create a new
// input source based on the func provided with potentially using existing cli.Context values to initialize itself. If there is
// no error it will then apply the new input source to any flags that are supported by the input source
func InitInputSourceWithContext(flags []cli.Flag, createInputSource func(context *cli.Context) (InputSourceContext, error)) cli.BeforeFunc {
return func(context *cli.Context) error {
inputSource, err := createInputSource(context)
if err != nil {
return fmt.Errorf("Unable to create input source with context: inner error: \n'%v'", err.Error())
}
return ApplyInputSourceValues(context, inputSource, flags)
}
}
// ApplyInputSourceValue applies a generic value to the flagSet if required
func (f *GenericFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error {
if f.set != nil {
if !context.IsSet(f.Name) && !isEnvVarSet(f.EnvVar) {
value, err := isc.Generic(f.GenericFlag.Name)
if err != nil {
return err
}
if value != nil {
eachName(f.Name, func(name string) {
f.set.Set(f.Name, value.String())
})
}
}
}
return 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 {
if !context.IsSet(f.Name) && !isEnvVarSet(f.EnvVar) {
value, err := isc.StringSlice(f.StringSliceFlag.Name)
if err != nil {
return err
}
if value != nil {
var sliceValue cli.StringSlice = value
eachName(f.Name, func(name string) {
underlyingFlag := f.set.Lookup(f.Name)
if underlyingFlag != nil {
underlyingFlag.Value = &sliceValue
}
})
}
}
}
return nil
}
// ApplyInputSourceValue applies a IntSlice value if required
func (f *IntSliceFlag) ApplyInputSourceValue(context *cli.Context, isc InputSourceContext) error {
if f.set != nil {
if !context.IsSet(f.Name) && !isEnvVarSet(f.EnvVar) {
value, err := isc.IntSlice(f.IntSliceFlag.Name)
if err != nil {
return err
}
if value != nil {
var sliceValue cli.IntSlice = value
eachName(f.Name, func(name string) {
underlyingFlag := f.set.Lookup(f.Name)
if underlyingFlag != nil {
underlyingFlag.Value = &sliceValue
}
})
}
}
}
return 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 {
if !context.IsSet(f.Name) && !isEnvVarSet(f.EnvVar) {
value, err := isc.Bool(f.BoolFlag.Name)
if err != nil {
return err
}
if value {
eachName(f.Name, func(name string) {
f.set.Set(f.Name, strconv.FormatBool(value))
})
}
}
}
return 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 {
if !context.IsSet(f.Name) && !isEnvVarSet(f.EnvVar) {
value, err := isc.BoolT(f.BoolTFlag.Name)
if err != nil {
return err
}
if !value {
eachName(f.Name, func(name string) {
f.set.Set(f.Name, strconv.FormatBool(value))
})
}
}
}
return 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 {
if !(context.IsSet(f.Name) || isEnvVarSet(f.EnvVar)) {
value, err := isc.String(f.StringFlag.Name)
if err != nil {
return err
}
if value != "" {
eachName(f.Name, func(name string) {
f.set.Set(f.Name, value)
})
}
}
}
return 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 {
if !(context.IsSet(f.Name) || isEnvVarSet(f.EnvVar)) {
value, err := isc.Int(f.IntFlag.Name)
if err != nil {
return err
}
if value > 0 {
eachName(f.Name, func(name string) {
f.set.Set(f.Name, strconv.FormatInt(int64(value), 10))
})
}
}
}
return 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 {
if !(context.IsSet(f.Name) || isEnvVarSet(f.EnvVar)) {
value, err := isc.Duration(f.DurationFlag.Name)
if err != nil {
return err
}
if value > 0 {
eachName(f.Name, func(name string) {
f.set.Set(f.Name, value.String())
})
}
}
}
return 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 {
if !(context.IsSet(f.Name) || isEnvVarSet(f.EnvVar)) {
value, err := isc.Float64(f.Float64Flag.Name)
if err != nil {
return err
}
if value > 0 {
floatStr := float64ToString(value)
eachName(f.Name, func(name string) {
f.set.Set(f.Name, floatStr)
})
}
}
}
return nil
}
func isEnvVarSet(envVars string) bool {
for _, envVar := range strings.Split(envVars, ",") {
envVar = strings.TrimSpace(envVar)
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
return true
}
}
return false
}
func float64ToString(f float64) string {
return fmt.Sprintf("%v", f)
}
func eachName(longName string, fn func(string)) {
parts := strings.Split(longName, ",")
for _, name := range parts {
name = strings.Trim(name, " ")
fn(name)
}
}

View file

@ -1,347 +0,0 @@
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)
}

View file

@ -1,336 +0,0 @@
package altsrc
import (
"flag"
"fmt"
"os"
"strings"
"testing"
"time"
"gopkg.in/urfave/cli.v1"
)
type testApplyInputSource struct {
Flag FlagInputSourceExtension
FlagName string
FlagSetName string
Expected string
ContextValueString string
ContextValue flag.Value
EnvVarValue string
EnvVarName string
MapValue interface{}
}
func TestGenericApplyInputSourceValue(t *testing.T) {
v := &Parser{"abc", "def"}
c := runTest(t, testApplyInputSource{
Flag: NewGenericFlag(cli.GenericFlag{Name: "test", Value: &Parser{}}),
FlagName: "test",
MapValue: v,
})
expect(t, v, c.Generic("test"))
}
func TestGenericApplyInputSourceMethodContextSet(t *testing.T) {
p := &Parser{"abc", "def"}
c := runTest(t, testApplyInputSource{
Flag: NewGenericFlag(cli.GenericFlag{Name: "test", Value: &Parser{}}),
FlagName: "test",
MapValue: &Parser{"efg", "hig"},
ContextValueString: p.String(),
})
expect(t, p, c.Generic("test"))
}
func TestGenericApplyInputSourceMethodEnvVarSet(t *testing.T) {
c := runTest(t, testApplyInputSource{
Flag: NewGenericFlag(cli.GenericFlag{Name: "test", Value: &Parser{}, EnvVar: "TEST"}),
FlagName: "test",
MapValue: &Parser{"efg", "hij"},
EnvVarName: "TEST",
EnvVarValue: "abc,def",
})
expect(t, &Parser{"abc", "def"}, c.Generic("test"))
}
func TestStringSliceApplyInputSourceValue(t *testing.T) {
c := runTest(t, testApplyInputSource{
Flag: NewStringSliceFlag(cli.StringSliceFlag{Name: "test"}),
FlagName: "test",
MapValue: []string{"hello", "world"},
})
expect(t, c.StringSlice("test"), []string{"hello", "world"})
}
func TestStringSliceApplyInputSourceMethodContextSet(t *testing.T) {
c := runTest(t, testApplyInputSource{
Flag: NewStringSliceFlag(cli.StringSliceFlag{Name: "test"}),
FlagName: "test",
MapValue: []string{"hello", "world"},
ContextValueString: "ohno",
})
expect(t, c.StringSlice("test"), []string{"ohno"})
}
func TestStringSliceApplyInputSourceMethodEnvVarSet(t *testing.T) {
c := runTest(t, testApplyInputSource{
Flag: NewStringSliceFlag(cli.StringSliceFlag{Name: "test", EnvVar: "TEST"}),
FlagName: "test",
MapValue: []string{"hello", "world"},
EnvVarName: "TEST",
EnvVarValue: "oh,no",
})
expect(t, c.StringSlice("test"), []string{"oh", "no"})
}
func TestIntSliceApplyInputSourceValue(t *testing.T) {
c := runTest(t, testApplyInputSource{
Flag: NewIntSliceFlag(cli.IntSliceFlag{Name: "test"}),
FlagName: "test",
MapValue: []int{1, 2},
})
expect(t, c.IntSlice("test"), []int{1, 2})
}
func TestIntSliceApplyInputSourceMethodContextSet(t *testing.T) {
c := runTest(t, testApplyInputSource{
Flag: NewIntSliceFlag(cli.IntSliceFlag{Name: "test"}),
FlagName: "test",
MapValue: []int{1, 2},
ContextValueString: "3",
})
expect(t, c.IntSlice("test"), []int{3})
}
func TestIntSliceApplyInputSourceMethodEnvVarSet(t *testing.T) {
c := runTest(t, testApplyInputSource{
Flag: NewIntSliceFlag(cli.IntSliceFlag{Name: "test", EnvVar: "TEST"}),
FlagName: "test",
MapValue: []int{1, 2},
EnvVarName: "TEST",
EnvVarValue: "3,4",
})
expect(t, c.IntSlice("test"), []int{3, 4})
}
func TestBoolApplyInputSourceMethodSet(t *testing.T) {
c := runTest(t, testApplyInputSource{
Flag: NewBoolFlag(cli.BoolFlag{Name: "test"}),
FlagName: "test",
MapValue: true,
})
expect(t, true, c.Bool("test"))
}
func TestBoolApplyInputSourceMethodContextSet(t *testing.T) {
c := runTest(t, testApplyInputSource{
Flag: NewBoolFlag(cli.BoolFlag{Name: "test"}),
FlagName: "test",
MapValue: false,
ContextValueString: "true",
})
expect(t, true, c.Bool("test"))
}
func TestBoolApplyInputSourceMethodEnvVarSet(t *testing.T) {
c := runTest(t, testApplyInputSource{
Flag: NewBoolFlag(cli.BoolFlag{Name: "test", EnvVar: "TEST"}),
FlagName: "test",
MapValue: false,
EnvVarName: "TEST",
EnvVarValue: "true",
})
expect(t, true, c.Bool("test"))
}
func TestBoolTApplyInputSourceMethodSet(t *testing.T) {
c := runTest(t, testApplyInputSource{
Flag: NewBoolTFlag(cli.BoolTFlag{Name: "test"}),
FlagName: "test",
MapValue: false,
})
expect(t, false, c.BoolT("test"))
}
func TestBoolTApplyInputSourceMethodContextSet(t *testing.T) {
c := runTest(t, testApplyInputSource{
Flag: NewBoolTFlag(cli.BoolTFlag{Name: "test"}),
FlagName: "test",
MapValue: true,
ContextValueString: "false",
})
expect(t, false, c.BoolT("test"))
}
func TestBoolTApplyInputSourceMethodEnvVarSet(t *testing.T) {
c := runTest(t, testApplyInputSource{
Flag: NewBoolTFlag(cli.BoolTFlag{Name: "test", EnvVar: "TEST"}),
FlagName: "test",
MapValue: true,
EnvVarName: "TEST",
EnvVarValue: "false",
})
expect(t, false, c.BoolT("test"))
}
func TestStringApplyInputSourceMethodSet(t *testing.T) {
c := runTest(t, testApplyInputSource{
Flag: NewStringFlag(cli.StringFlag{Name: "test"}),
FlagName: "test",
MapValue: "hello",
})
expect(t, "hello", c.String("test"))
}
func TestStringApplyInputSourceMethodContextSet(t *testing.T) {
c := runTest(t, testApplyInputSource{
Flag: NewStringFlag(cli.StringFlag{Name: "test"}),
FlagName: "test",
MapValue: "hello",
ContextValueString: "goodbye",
})
expect(t, "goodbye", c.String("test"))
}
func TestStringApplyInputSourceMethodEnvVarSet(t *testing.T) {
c := runTest(t, testApplyInputSource{
Flag: NewStringFlag(cli.StringFlag{Name: "test", EnvVar: "TEST"}),
FlagName: "test",
MapValue: "hello",
EnvVarName: "TEST",
EnvVarValue: "goodbye",
})
expect(t, "goodbye", c.String("test"))
}
func TestIntApplyInputSourceMethodSet(t *testing.T) {
c := runTest(t, testApplyInputSource{
Flag: NewIntFlag(cli.IntFlag{Name: "test"}),
FlagName: "test",
MapValue: 15,
})
expect(t, 15, c.Int("test"))
}
func TestIntApplyInputSourceMethodContextSet(t *testing.T) {
c := runTest(t, testApplyInputSource{
Flag: NewIntFlag(cli.IntFlag{Name: "test"}),
FlagName: "test",
MapValue: 15,
ContextValueString: "7",
})
expect(t, 7, c.Int("test"))
}
func TestIntApplyInputSourceMethodEnvVarSet(t *testing.T) {
c := runTest(t, testApplyInputSource{
Flag: NewIntFlag(cli.IntFlag{Name: "test", EnvVar: "TEST"}),
FlagName: "test",
MapValue: 15,
EnvVarName: "TEST",
EnvVarValue: "12",
})
expect(t, 12, c.Int("test"))
}
func TestDurationApplyInputSourceMethodSet(t *testing.T) {
c := runTest(t, testApplyInputSource{
Flag: NewDurationFlag(cli.DurationFlag{Name: "test"}),
FlagName: "test",
MapValue: time.Duration(30 * time.Second),
})
expect(t, time.Duration(30*time.Second), c.Duration("test"))
}
func TestDurationApplyInputSourceMethodContextSet(t *testing.T) {
c := runTest(t, testApplyInputSource{
Flag: NewDurationFlag(cli.DurationFlag{Name: "test"}),
FlagName: "test",
MapValue: time.Duration(30 * time.Second),
ContextValueString: time.Duration(15 * time.Second).String(),
})
expect(t, time.Duration(15*time.Second), c.Duration("test"))
}
func TestDurationApplyInputSourceMethodEnvVarSet(t *testing.T) {
c := runTest(t, testApplyInputSource{
Flag: NewDurationFlag(cli.DurationFlag{Name: "test", EnvVar: "TEST"}),
FlagName: "test",
MapValue: time.Duration(30 * time.Second),
EnvVarName: "TEST",
EnvVarValue: time.Duration(15 * time.Second).String(),
})
expect(t, time.Duration(15*time.Second), c.Duration("test"))
}
func TestFloat64ApplyInputSourceMethodSet(t *testing.T) {
c := runTest(t, testApplyInputSource{
Flag: NewFloat64Flag(cli.Float64Flag{Name: "test"}),
FlagName: "test",
MapValue: 1.3,
})
expect(t, 1.3, c.Float64("test"))
}
func TestFloat64ApplyInputSourceMethodContextSet(t *testing.T) {
c := runTest(t, testApplyInputSource{
Flag: NewFloat64Flag(cli.Float64Flag{Name: "test"}),
FlagName: "test",
MapValue: 1.3,
ContextValueString: fmt.Sprintf("%v", 1.4),
})
expect(t, 1.4, c.Float64("test"))
}
func TestFloat64ApplyInputSourceMethodEnvVarSet(t *testing.T) {
c := runTest(t, testApplyInputSource{
Flag: NewFloat64Flag(cli.Float64Flag{Name: "test", EnvVar: "TEST"}),
FlagName: "test",
MapValue: 1.3,
EnvVarName: "TEST",
EnvVarValue: fmt.Sprintf("%v", 1.4),
})
expect(t, 1.4, c.Float64("test"))
}
func runTest(t *testing.T, test testApplyInputSource) *cli.Context {
inputSource := &MapInputSource{valueMap: map[interface{}]interface{}{test.FlagName: test.MapValue}}
set := flag.NewFlagSet(test.FlagSetName, flag.ContinueOnError)
c := cli.NewContext(nil, set, nil)
if test.EnvVarName != "" && test.EnvVarValue != "" {
os.Setenv(test.EnvVarName, test.EnvVarValue)
defer os.Setenv(test.EnvVarName, "")
}
test.Flag.Apply(set)
if test.ContextValue != nil {
flag := set.Lookup(test.FlagName)
flag.Value = test.ContextValue
}
if test.ContextValueString != "" {
set.Set(test.FlagName, test.ContextValueString)
}
test.Flag.ApplyInputSourceValue(c, inputSource)
return c
}
type Parser [2]string
func (p *Parser) Set(value string) error {
parts := strings.Split(value, ",")
if len(parts) != 2 {
return fmt.Errorf("invalid format")
}
(*p)[0] = parts[0]
(*p)[1] = parts[1]
return nil
}
func (p *Parser) String() string {
return fmt.Sprintf("%s,%s", p[0], p[1])
}

View file

@ -1,18 +0,0 @@
package altsrc
import (
"reflect"
"testing"
)
func expect(t *testing.T, a interface{}, b interface{}) {
if !reflect.DeepEqual(b, a) {
t.Errorf("Expected %#v (type %v) - Got %#v (type %v)", b, reflect.TypeOf(b), a, reflect.TypeOf(a))
}
}
func refute(t *testing.T, a interface{}, b interface{}) {
if a == b {
t.Errorf("Did not expect %v (type %v) - Got %v (type %v)", b, reflect.TypeOf(b), a, reflect.TypeOf(a))
}
}

View file

@ -1,21 +0,0 @@
package altsrc
import (
"time"
"gopkg.in/urfave/cli.v1"
)
// InputSourceContext is an interface used to allow
// other input sources to be implemented as needed.
type InputSourceContext interface {
Int(name string) (int, error)
Duration(name string) (time.Duration, error)
Float64(name string) (float64, error)
String(name string) (string, error)
StringSlice(name string) ([]string, error)
IntSlice(name string) ([]int, error)
Generic(name string) (cli.Generic, error)
Bool(name string) (bool, error)
BoolT(name string) (bool, error)
}

View file

@ -1,248 +0,0 @@
package altsrc
import (
"fmt"
"reflect"
"strings"
"time"
"gopkg.in/urfave/cli.v1"
)
// MapInputSource implements InputSourceContext to return
// data from the map that is loaded.
type MapInputSource struct {
valueMap map[interface{}]interface{}
}
// nestedVal checks if the name has '.' delimiters.
// If so, it tries to traverse the tree by the '.' delimited sections to find
// a nested value for the key.
func nestedVal(name string, tree map[interface{}]interface{}) (interface{}, bool) {
if sections := strings.Split(name, "."); len(sections) > 1 {
node := tree
for _, section := range sections[:len(sections)-1] {
if child, ok := node[section]; !ok {
return nil, false
} else {
if ctype, ok := child.(map[interface{}]interface{}); !ok {
return nil, false
} else {
node = ctype
}
}
}
if val, ok := node[sections[len(sections)-1]]; ok {
return val, true
}
}
return nil, false
}
// Int returns an int from the map if it exists otherwise returns 0
func (fsm *MapInputSource) Int(name string) (int, error) {
otherGenericValue, exists := fsm.valueMap[name]
if exists {
otherValue, isType := otherGenericValue.(int)
if !isType {
return 0, incorrectTypeForFlagError(name, "int", otherGenericValue)
}
return otherValue, nil
}
nestedGenericValue, exists := nestedVal(name, fsm.valueMap)
if exists {
otherValue, isType := nestedGenericValue.(int)
if !isType {
return 0, incorrectTypeForFlagError(name, "int", nestedGenericValue)
}
return otherValue, nil
}
return 0, nil
}
// Duration returns a duration from the map if it exists otherwise returns 0
func (fsm *MapInputSource) Duration(name string) (time.Duration, error) {
otherGenericValue, exists := fsm.valueMap[name]
if exists {
otherValue, isType := otherGenericValue.(time.Duration)
if !isType {
return 0, incorrectTypeForFlagError(name, "duration", otherGenericValue)
}
return otherValue, nil
}
nestedGenericValue, exists := nestedVal(name, fsm.valueMap)
if exists {
otherValue, isType := nestedGenericValue.(time.Duration)
if !isType {
return 0, incorrectTypeForFlagError(name, "duration", nestedGenericValue)
}
return otherValue, nil
}
return 0, nil
}
// Float64 returns an float64 from the map if it exists otherwise returns 0
func (fsm *MapInputSource) Float64(name string) (float64, error) {
otherGenericValue, exists := fsm.valueMap[name]
if exists {
otherValue, isType := otherGenericValue.(float64)
if !isType {
return 0, incorrectTypeForFlagError(name, "float64", otherGenericValue)
}
return otherValue, nil
}
nestedGenericValue, exists := nestedVal(name, fsm.valueMap)
if exists {
otherValue, isType := nestedGenericValue.(float64)
if !isType {
return 0, incorrectTypeForFlagError(name, "float64", nestedGenericValue)
}
return otherValue, nil
}
return 0, nil
}
// String returns a string from the map if it exists otherwise returns an empty string
func (fsm *MapInputSource) String(name string) (string, error) {
otherGenericValue, exists := fsm.valueMap[name]
if exists {
otherValue, isType := otherGenericValue.(string)
if !isType {
return "", incorrectTypeForFlagError(name, "string", otherGenericValue)
}
return otherValue, nil
}
nestedGenericValue, exists := nestedVal(name, fsm.valueMap)
if exists {
otherValue, isType := nestedGenericValue.(string)
if !isType {
return "", incorrectTypeForFlagError(name, "string", nestedGenericValue)
}
return otherValue, nil
}
return "", nil
}
// StringSlice returns an []string from the map if it exists otherwise returns nil
func (fsm *MapInputSource) StringSlice(name string) ([]string, error) {
otherGenericValue, exists := fsm.valueMap[name]
if exists {
otherValue, isType := otherGenericValue.([]string)
if !isType {
return nil, incorrectTypeForFlagError(name, "[]string", otherGenericValue)
}
return otherValue, nil
}
nestedGenericValue, exists := nestedVal(name, fsm.valueMap)
if exists {
otherValue, isType := nestedGenericValue.([]string)
if !isType {
return nil, incorrectTypeForFlagError(name, "[]string", nestedGenericValue)
}
return otherValue, nil
}
return nil, nil
}
// IntSlice returns an []int from the map if it exists otherwise returns nil
func (fsm *MapInputSource) IntSlice(name string) ([]int, error) {
otherGenericValue, exists := fsm.valueMap[name]
if exists {
otherValue, isType := otherGenericValue.([]int)
if !isType {
return nil, incorrectTypeForFlagError(name, "[]int", otherGenericValue)
}
return otherValue, nil
}
nestedGenericValue, exists := nestedVal(name, fsm.valueMap)
if exists {
otherValue, isType := nestedGenericValue.([]int)
if !isType {
return nil, incorrectTypeForFlagError(name, "[]int", nestedGenericValue)
}
return otherValue, nil
}
return nil, nil
}
// Generic returns an cli.Generic from the map if it exists otherwise returns nil
func (fsm *MapInputSource) Generic(name string) (cli.Generic, error) {
otherGenericValue, exists := fsm.valueMap[name]
if exists {
otherValue, isType := otherGenericValue.(cli.Generic)
if !isType {
return nil, incorrectTypeForFlagError(name, "cli.Generic", otherGenericValue)
}
return otherValue, nil
}
nestedGenericValue, exists := nestedVal(name, fsm.valueMap)
if exists {
otherValue, isType := nestedGenericValue.(cli.Generic)
if !isType {
return nil, incorrectTypeForFlagError(name, "cli.Generic", nestedGenericValue)
}
return otherValue, nil
}
return nil, nil
}
// Bool returns an bool from the map otherwise returns false
func (fsm *MapInputSource) Bool(name string) (bool, error) {
otherGenericValue, exists := fsm.valueMap[name]
if exists {
otherValue, isType := otherGenericValue.(bool)
if !isType {
return false, incorrectTypeForFlagError(name, "bool", otherGenericValue)
}
return otherValue, nil
}
nestedGenericValue, exists := nestedVal(name, fsm.valueMap)
if exists {
otherValue, isType := nestedGenericValue.(bool)
if !isType {
return false, incorrectTypeForFlagError(name, "bool", nestedGenericValue)
}
return otherValue, nil
}
return false, nil
}
// BoolT returns an bool from the map otherwise returns true
func (fsm *MapInputSource) BoolT(name string) (bool, error) {
otherGenericValue, exists := fsm.valueMap[name]
if exists {
otherValue, isType := otherGenericValue.(bool)
if !isType {
return true, incorrectTypeForFlagError(name, "bool", otherGenericValue)
}
return otherValue, nil
}
nestedGenericValue, exists := nestedVal(name, fsm.valueMap)
if exists {
otherValue, isType := nestedGenericValue.(bool)
if !isType {
return true, incorrectTypeForFlagError(name, "bool", nestedGenericValue)
}
return otherValue, nil
}
return true, nil
}
func incorrectTypeForFlagError(name, expectedTypeName string, value interface{}) error {
valueType := reflect.TypeOf(value)
valueTypeName := ""
if valueType != nil {
valueTypeName = valueType.Name()
}
return fmt.Errorf("Mismatched type for flag '%s'. Expected '%s' but actual is '%s'", name, expectedTypeName, valueTypeName)
}

View file

@ -1,310 +0,0 @@
// 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)
}

View file

@ -1,113 +0,0 @@
// 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
}

View file

@ -1,313 +0,0 @@
// Disabling building of yaml 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 TestCommandYamlFileTest(t *testing.T) {
app := cli.NewApp()
set := flag.NewFlagSet("test", 0)
ioutil.WriteFile("current.yaml", []byte("test: 15"), 0666)
defer os.Remove("current.yaml")
test := []string{"test-cmd", "--load", "current.yaml"}
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, NewYamlSourceFromFlagFunc("load"))
err := command.Run(c)
expect(t, err, nil)
}
func TestCommandYamlFileTestGlobalEnvVarWins(t *testing.T) {
app := cli.NewApp()
set := flag.NewFlagSet("test", 0)
ioutil.WriteFile("current.yaml", []byte("test: 15"), 0666)
defer os.Remove("current.yaml")
os.Setenv("THE_TEST", "10")
defer os.Setenv("THE_TEST", "")
test := []string{"test-cmd", "--load", "current.yaml"}
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, NewYamlSourceFromFlagFunc("load"))
err := command.Run(c)
expect(t, err, nil)
}
func TestCommandYamlFileTestGlobalEnvVarWinsNested(t *testing.T) {
app := cli.NewApp()
set := flag.NewFlagSet("test", 0)
ioutil.WriteFile("current.yaml", []byte(`top:
test: 15`), 0666)
defer os.Remove("current.yaml")
os.Setenv("THE_TEST", "10")
defer os.Setenv("THE_TEST", "")
test := []string{"test-cmd", "--load", "current.yaml"}
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, NewYamlSourceFromFlagFunc("load"))
err := command.Run(c)
expect(t, err, nil)
}
func TestCommandYamlFileTestSpecifiedFlagWins(t *testing.T) {
app := cli.NewApp()
set := flag.NewFlagSet("test", 0)
ioutil.WriteFile("current.yaml", []byte("test: 15"), 0666)
defer os.Remove("current.yaml")
test := []string{"test-cmd", "--load", "current.yaml", "--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, NewYamlSourceFromFlagFunc("load"))
err := command.Run(c)
expect(t, err, nil)
}
func TestCommandYamlFileTestSpecifiedFlagWinsNested(t *testing.T) {
app := cli.NewApp()
set := flag.NewFlagSet("test", 0)
ioutil.WriteFile("current.yaml", []byte(`top:
test: 15`), 0666)
defer os.Remove("current.yaml")
test := []string{"test-cmd", "--load", "current.yaml", "--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, NewYamlSourceFromFlagFunc("load"))
err := command.Run(c)
expect(t, err, nil)
}
func TestCommandYamlFileTestDefaultValueFileWins(t *testing.T) {
app := cli.NewApp()
set := flag.NewFlagSet("test", 0)
ioutil.WriteFile("current.yaml", []byte("test: 15"), 0666)
defer os.Remove("current.yaml")
test := []string{"test-cmd", "--load", "current.yaml"}
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, NewYamlSourceFromFlagFunc("load"))
err := command.Run(c)
expect(t, err, nil)
}
func TestCommandYamlFileTestDefaultValueFileWinsNested(t *testing.T) {
app := cli.NewApp()
set := flag.NewFlagSet("test", 0)
ioutil.WriteFile("current.yaml", []byte(`top:
test: 15`), 0666)
defer os.Remove("current.yaml")
test := []string{"test-cmd", "--load", "current.yaml"}
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, NewYamlSourceFromFlagFunc("load"))
err := command.Run(c)
expect(t, err, nil)
}
func TestCommandYamlFileFlagHasDefaultGlobalEnvYamlSetGlobalEnvWins(t *testing.T) {
app := cli.NewApp()
set := flag.NewFlagSet("test", 0)
ioutil.WriteFile("current.yaml", []byte("test: 15"), 0666)
defer os.Remove("current.yaml")
os.Setenv("THE_TEST", "11")
defer os.Setenv("THE_TEST", "")
test := []string{"test-cmd", "--load", "current.yaml"}
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, NewYamlSourceFromFlagFunc("load"))
err := command.Run(c)
expect(t, err, nil)
}
func TestCommandYamlFileFlagHasDefaultGlobalEnvYamlSetGlobalEnvWinsNested(t *testing.T) {
app := cli.NewApp()
set := flag.NewFlagSet("test", 0)
ioutil.WriteFile("current.yaml", []byte(`top:
test: 15`), 0666)
defer os.Remove("current.yaml")
os.Setenv("THE_TEST", "11")
defer os.Setenv("THE_TEST", "")
test := []string{"test-cmd", "--load", "current.yaml"}
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, NewYamlSourceFromFlagFunc("load"))
err := command.Run(c)
expect(t, err, nil)
}

View file

@ -1,84 +0,0 @@
// Disabling building of yaml 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"
"io/ioutil"
"net/http"
"net/url"
"os"
"gopkg.in/urfave/cli.v1"
"gopkg.in/yaml.v2"
)
type yamlSourceContext struct {
FilePath string
}
// NewYamlSourceFromFile creates a new Yaml InputSourceContext from a filepath.
func NewYamlSourceFromFile(file string) (InputSourceContext, error) {
ysc := &yamlSourceContext{FilePath: file}
var results map[interface{}]interface{}
err := readCommandYaml(ysc.FilePath, &results)
if err != nil {
return nil, fmt.Errorf("Unable to load Yaml file '%s': inner error: \n'%v'", ysc.FilePath, err.Error())
}
return &MapInputSource{valueMap: results}, nil
}
// NewYamlSourceFromFlagFunc creates a new Yaml InputSourceContext from a provided flag name and source context.
func NewYamlSourceFromFlagFunc(flagFileName string) func(context *cli.Context) (InputSourceContext, error) {
return func(context *cli.Context) (InputSourceContext, error) {
filePath := context.String(flagFileName)
return NewYamlSourceFromFile(filePath)
}
}
func readCommandYaml(filePath string, container interface{}) (err error) {
b, err := loadDataFrom(filePath)
if err != nil {
return err
}
err = yaml.Unmarshal(b, container)
if err != nil {
return err
}
err = nil
return
}
func loadDataFrom(filePath string) ([]byte, error) {
u, err := url.Parse(filePath)
if err != nil {
return nil, err
}
if u.Host != "" { // i have a host, now do i support the scheme?
switch u.Scheme {
case "http", "https":
res, err := http.Get(filePath)
if err != nil {
return nil, err
}
return ioutil.ReadAll(res.Body)
default:
return nil, fmt.Errorf("scheme of %s is unsupported", filePath)
}
} else if u.Path != "" { // i dont have a host, but I have a path. I am a local file.
if _, notFoundFileErr := os.Stat(filePath); notFoundFileErr != nil {
return nil, fmt.Errorf("Cannot read from file: '%s' because it does not exist.", filePath)
}
return ioutil.ReadFile(filePath)
} else {
return nil, fmt.Errorf("unable to determine how to load from path %s", filePath)
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,24 +0,0 @@
version: "{build}"
os: Windows Server 2012 R2
clone_folder: c:\gopath\src\github.com\urfave\cli
environment:
GOPATH: C:\gopath
GOVERSION: 1.6
PYTHON: C:\Python27-x64
PYTHON_VERSION: 2.7.x
PYTHON_ARCH: 64
install:
- set PATH=%GOPATH%\bin;C:\go\bin;%PATH%
- go version
- go env
- go get github.com/urfave/gfmrun/...
- go get -v -t ./...
build_script:
- python runtests vet
- python runtests test
- python runtests gfmrun

View file

@ -1,14 +0,0 @@
#! /bin/bash
: ${PROG:=$(basename ${BASH_SOURCE})}
_cli_bash_autocomplete() {
local cur opts base
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
opts=$( ${COMP_WORDS[@]:0:$COMP_CWORD} --generate-bash-completion )
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
return 0
}
complete -F _cli_bash_autocomplete $PROG

View file

@ -1,5 +0,0 @@
autoload -U compinit && compinit
autoload -U bashcompinit && bashcompinit
script_dir=$(dirname $0)
source ${script_dir}/bash_autocomplete

View file

@ -1,155 +0,0 @@
package cli
import (
"errors"
"flag"
"fmt"
"io/ioutil"
"strings"
"testing"
)
func TestCommandFlagParsing(t *testing.T) {
cases := []struct {
testArgs []string
skipFlagParsing bool
skipArgReorder bool
expectedErr error
}{
// 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 {
app := NewApp()
app.Writer = ioutil.Discard
set := flag.NewFlagSet("test", 0)
set.Parse(c.testArgs)
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 },
SkipFlagParsing: c.skipFlagParsing,
SkipArgReorder: c.skipArgReorder,
}
err := command.Run(context)
expect(t, err, c.expectedErr)
expect(t, []string(context.Args()), c.testArgs)
}
}
func TestCommand_Run_DoesNotOverwriteErrorFromBefore(t *testing.T) {
app := NewApp()
app.Commands = []Command{
{
Name: "bar",
Before: func(c *Context) error {
return fmt.Errorf("before error")
},
After: func(c *Context) error {
return fmt.Errorf("after error")
},
},
}
err := app.Run([]string{"foo", "bar"})
if err == nil {
t.Fatalf("expected to receive error from Run, got none")
}
if !strings.Contains(err.Error(), "before error") {
t.Errorf("expected text of error from Before method, but got none in \"%v\"", err)
}
if !strings.Contains(err.Error(), "after error") {
t.Errorf("expected text of error from After method, but got none in \"%v\"", err)
}
}
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{
{
Name: "bar",
Flags: []Flag{
IntFlag{Name: "flag"},
},
OnUsageError: func(c *Context, err error, _ bool) error {
if !strings.HasPrefix(err.Error(), "invalid value \"wrong\"") {
t.Errorf("Expect an invalid value error, but got \"%v\"", err)
}
return errors.New("intercepted: " + err.Error())
},
},
}
err := app.Run([]string{"foo", "bar", "--flag=wrong"})
if err == nil {
t.Fatalf("expected to receive error from Run, got none")
}
if !strings.HasPrefix(err.Error(), "intercepted: invalid value") {
t.Errorf("Expect an intercepted error, but got \"%v\"", err)
}
}

View file

@ -1,399 +0,0 @@
package cli
import (
"flag"
"os"
"testing"
"time"
)
func TestNewContext(t *testing.T) {
set := flag.NewFlagSet("test", 0)
set.Int("myflag", 12, "doc")
set.Int64("myflagInt64", int64(12), "doc")
set.Uint("myflagUint", uint(93), "doc")
set.Uint64("myflagUint64", uint64(93), "doc")
set.Float64("myflag64", float64(17), "doc")
globalSet := flag.NewFlagSet("test", 0)
globalSet.Int("myflag", 42, "doc")
globalSet.Int64("myflagInt64", int64(42), "doc")
globalSet.Uint("myflagUint", uint(33), "doc")
globalSet.Uint64("myflagUint64", uint64(33), "doc")
globalSet.Float64("myflag64", float64(47), "doc")
globalCtx := NewContext(nil, globalSet, nil)
command := Command{Name: "mycommand"}
c := NewContext(nil, set, globalCtx)
c.Command = command
expect(t, c.Int("myflag"), 12)
expect(t, c.Int64("myflagInt64"), int64(12))
expect(t, c.Uint("myflagUint"), uint(93))
expect(t, c.Uint64("myflagUint64"), uint64(93))
expect(t, c.Float64("myflag64"), float64(17))
expect(t, c.GlobalInt("myflag"), 42)
expect(t, c.GlobalInt64("myflagInt64"), int64(42))
expect(t, c.GlobalUint("myflagUint"), uint(33))
expect(t, c.GlobalUint64("myflagUint64"), uint64(33))
expect(t, c.GlobalFloat64("myflag64"), float64(47))
expect(t, c.Command.Name, "mycommand")
}
func TestContext_Int(t *testing.T) {
set := flag.NewFlagSet("test", 0)
set.Int("myflag", 12, "doc")
c := NewContext(nil, set, nil)
expect(t, c.Int("myflag"), 12)
}
func TestContext_Int64(t *testing.T) {
set := flag.NewFlagSet("test", 0)
set.Int64("myflagInt64", 12, "doc")
c := NewContext(nil, set, nil)
expect(t, c.Int64("myflagInt64"), int64(12))
}
func TestContext_Uint(t *testing.T) {
set := flag.NewFlagSet("test", 0)
set.Uint("myflagUint", uint(13), "doc")
c := NewContext(nil, set, nil)
expect(t, c.Uint("myflagUint"), uint(13))
}
func TestContext_Uint64(t *testing.T) {
set := flag.NewFlagSet("test", 0)
set.Uint64("myflagUint64", uint64(9), "doc")
c := NewContext(nil, set, nil)
expect(t, c.Uint64("myflagUint64"), uint64(9))
}
func TestContext_GlobalInt(t *testing.T) {
set := flag.NewFlagSet("test", 0)
set.Int("myflag", 12, "doc")
c := NewContext(nil, set, nil)
expect(t, c.GlobalInt("myflag"), 12)
expect(t, c.GlobalInt("nope"), 0)
}
func TestContext_GlobalInt64(t *testing.T) {
set := flag.NewFlagSet("test", 0)
set.Int64("myflagInt64", 12, "doc")
c := NewContext(nil, set, nil)
expect(t, c.GlobalInt64("myflagInt64"), int64(12))
expect(t, c.GlobalInt64("nope"), int64(0))
}
func TestContext_Float64(t *testing.T) {
set := flag.NewFlagSet("test", 0)
set.Float64("myflag", float64(17), "doc")
c := NewContext(nil, set, nil)
expect(t, c.Float64("myflag"), float64(17))
}
func TestContext_GlobalFloat64(t *testing.T) {
set := flag.NewFlagSet("test", 0)
set.Float64("myflag", float64(17), "doc")
c := NewContext(nil, set, nil)
expect(t, c.GlobalFloat64("myflag"), float64(17))
expect(t, c.GlobalFloat64("nope"), float64(0))
}
func TestContext_Duration(t *testing.T) {
set := flag.NewFlagSet("test", 0)
set.Duration("myflag", time.Duration(12*time.Second), "doc")
c := NewContext(nil, set, nil)
expect(t, c.Duration("myflag"), time.Duration(12*time.Second))
}
func TestContext_String(t *testing.T) {
set := flag.NewFlagSet("test", 0)
set.String("myflag", "hello world", "doc")
c := NewContext(nil, set, nil)
expect(t, c.String("myflag"), "hello world")
}
func TestContext_Bool(t *testing.T) {
set := flag.NewFlagSet("test", 0)
set.Bool("myflag", false, "doc")
c := NewContext(nil, set, nil)
expect(t, c.Bool("myflag"), false)
}
func TestContext_BoolT(t *testing.T) {
set := flag.NewFlagSet("test", 0)
set.Bool("myflag", true, "doc")
c := NewContext(nil, set, nil)
expect(t, c.BoolT("myflag"), true)
}
func TestContext_GlobalBool(t *testing.T) {
set := flag.NewFlagSet("test", 0)
globalSet := flag.NewFlagSet("test-global", 0)
globalSet.Bool("myflag", false, "doc")
globalCtx := NewContext(nil, globalSet, nil)
c := NewContext(nil, set, globalCtx)
expect(t, c.GlobalBool("myflag"), false)
expect(t, c.GlobalBool("nope"), false)
}
func TestContext_GlobalBoolT(t *testing.T) {
set := flag.NewFlagSet("test", 0)
globalSet := flag.NewFlagSet("test-global", 0)
globalSet.Bool("myflag", true, "doc")
globalCtx := NewContext(nil, globalSet, nil)
c := NewContext(nil, set, globalCtx)
expect(t, c.GlobalBoolT("myflag"), true)
expect(t, c.GlobalBoolT("nope"), false)
}
func TestContext_Args(t *testing.T) {
set := flag.NewFlagSet("test", 0)
set.Bool("myflag", false, "doc")
c := NewContext(nil, set, nil)
set.Parse([]string{"--myflag", "bat", "baz"})
expect(t, len(c.Args()), 2)
expect(t, c.Bool("myflag"), true)
}
func TestContext_NArg(t *testing.T) {
set := flag.NewFlagSet("test", 0)
set.Bool("myflag", false, "doc")
c := NewContext(nil, set, nil)
set.Parse([]string{"--myflag", "bat", "baz"})
expect(t, c.NArg(), 2)
}
func TestContext_IsSet(t *testing.T) {
set := flag.NewFlagSet("test", 0)
set.Bool("myflag", false, "doc")
set.String("otherflag", "hello world", "doc")
globalSet := flag.NewFlagSet("test", 0)
globalSet.Bool("myflagGlobal", true, "doc")
globalCtx := NewContext(nil, globalSet, nil)
c := NewContext(nil, set, globalCtx)
set.Parse([]string{"--myflag", "bat", "baz"})
globalSet.Parse([]string{"--myflagGlobal", "bat", "baz"})
expect(t, c.IsSet("myflag"), true)
expect(t, c.IsSet("otherflag"), false)
expect(t, c.IsSet("bogusflag"), false)
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")
set.String("otherflag", "hello world", "doc")
globalSet := flag.NewFlagSet("test", 0)
globalSet.Bool("myflagGlobal", true, "doc")
globalSet.Bool("myflagGlobalUnset", true, "doc")
globalCtx := NewContext(nil, globalSet, nil)
c := NewContext(nil, set, globalCtx)
set.Parse([]string{"--myflag", "bat", "baz"})
globalSet.Parse([]string{"--myflagGlobal", "bat", "baz"})
expect(t, c.GlobalIsSet("myflag"), false)
expect(t, c.GlobalIsSet("otherflag"), false)
expect(t, c.GlobalIsSet("bogusflag"), false)
expect(t, c.GlobalIsSet("myflagGlobal"), true)
expect(t, c.GlobalIsSet("myflagGlobalUnset"), false)
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")
set.String("otherflag", "hello world", "doc")
globalSet := flag.NewFlagSet("test", 0)
globalSet.Bool("myflagGlobal", true, "doc")
globalCtx := NewContext(nil, globalSet, nil)
c := NewContext(nil, set, globalCtx)
set.Parse([]string{"--myflag", "--otherflag=foo"})
globalSet.Parse([]string{"--myflagGlobal"})
expect(t, c.NumFlags(), 2)
}
func TestContext_GlobalFlag(t *testing.T) {
var globalFlag string
var globalFlagSet bool
app := NewApp()
app.Flags = []Flag{
StringFlag{Name: "global, g", Usage: "global"},
}
app.Action = func(c *Context) error {
globalFlag = c.GlobalString("global")
globalFlagSet = c.GlobalIsSet("global")
return nil
}
app.Run([]string{"command", "-g", "foo"})
expect(t, globalFlag, "foo")
expect(t, globalFlagSet, true)
}
func TestContext_GlobalFlagsInSubcommands(t *testing.T) {
subcommandRun := false
parentFlag := false
app := NewApp()
app.Flags = []Flag{
BoolFlag{Name: "debug, d", Usage: "Enable debugging"},
}
app.Commands = []Command{
{
Name: "foo",
Flags: []Flag{
BoolFlag{Name: "parent, p", Usage: "Parent flag"},
},
Subcommands: []Command{
{
Name: "bar",
Action: func(c *Context) error {
if c.GlobalBool("debug") {
subcommandRun = true
}
if c.GlobalBool("parent") {
parentFlag = true
}
return nil
},
},
},
},
}
app.Run([]string{"command", "-d", "foo", "-p", "bar"})
expect(t, subcommandRun, true)
expect(t, parentFlag, true)
}
func TestContext_Set(t *testing.T) {
set := flag.NewFlagSet("test", 0)
set.Int("int", 5, "an int")
c := NewContext(nil, set, nil)
c.Set("int", "1")
expect(t, c.Int("int"), 1)
}
func TestContext_GlobalSet(t *testing.T) {
gSet := flag.NewFlagSet("test", 0)
gSet.Int("int", 5, "an int")
set := flag.NewFlagSet("sub", 0)
set.Int("int", 3, "an int")
pc := NewContext(nil, gSet, nil)
c := NewContext(nil, set, pc)
c.Set("int", "1")
expect(t, c.Int("int"), 1)
expect(t, c.GlobalInt("int"), 5)
c.GlobalSet("int", "1")
expect(t, c.Int("int"), 1)
expect(t, c.GlobalInt("int"), 1)
}

View file

@ -1,157 +0,0 @@
package cli
import (
"bytes"
"errors"
"fmt"
"testing"
)
func TestHandleExitCoder_nil(t *testing.T) {
exitCode := 0
called := false
OsExiter = func(rc int) {
exitCode = rc
called = true
}
defer func() { OsExiter = fakeOsExiter }()
HandleExitCoder(nil)
expect(t, exitCode, 0)
expect(t, called, false)
}
func TestHandleExitCoder_ExitCoder(t *testing.T) {
exitCode := 0
called := false
OsExiter = func(rc int) {
exitCode = rc
called = true
}
defer func() { OsExiter = fakeOsExiter }()
HandleExitCoder(NewExitError("galactic perimeter breach", 9))
expect(t, exitCode, 9)
expect(t, called, true)
}
func TestHandleExitCoder_MultiErrorWithExitCoder(t *testing.T) {
exitCode := 0
called := false
OsExiter = func(rc int) {
exitCode = rc
called = true
}
defer func() { OsExiter = fakeOsExiter }()
exitErr := NewExitError("galactic perimeter breach", 9)
err := NewMultiError(errors.New("wowsa"), errors.New("egad"), exitErr)
HandleExitCoder(err)
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")
}

View file

@ -1,93 +0,0 @@
[
{
"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)"
}
]

File diff suppressed because it is too large Load diff

View file

@ -1,255 +0,0 @@
#!/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())

View file

@ -1,289 +0,0 @@
package cli
import (
"bytes"
"flag"
"strings"
"testing"
)
func Test_ShowAppHelp_NoAuthor(t *testing.T) {
output := new(bytes.Buffer)
app := NewApp()
app.Writer = output
c := NewContext(app, nil, nil)
ShowAppHelp(c)
if bytes.Index(output.Bytes(), []byte("AUTHOR(S):")) != -1 {
t.Errorf("expected\n%snot to include %s", output.String(), "AUTHOR(S):")
}
}
func Test_ShowAppHelp_NoVersion(t *testing.T) {
output := new(bytes.Buffer)
app := NewApp()
app.Writer = output
app.Version = ""
c := NewContext(app, nil, nil)
ShowAppHelp(c)
if bytes.Index(output.Bytes(), []byte("VERSION:")) != -1 {
t.Errorf("expected\n%snot to include %s", output.String(), "VERSION:")
}
}
func Test_ShowAppHelp_HideVersion(t *testing.T) {
output := new(bytes.Buffer)
app := NewApp()
app.Writer = output
app.HideVersion = true
c := NewContext(app, nil, nil)
ShowAppHelp(c)
if bytes.Index(output.Bytes(), []byte("VERSION:")) != -1 {
t.Errorf("expected\n%snot to include %s", output.String(), "VERSION:")
}
}
func Test_Help_Custom_Flags(t *testing.T) {
oldFlag := HelpFlag
defer func() {
HelpFlag = oldFlag
}()
HelpFlag = BoolFlag{
Name: "help, x",
Usage: "show help",
}
app := App{
Flags: []Flag{
BoolFlag{Name: "foo, h"},
},
Action: func(ctx *Context) error {
if ctx.Bool("h") != true {
t.Errorf("custom help flag not set")
}
return nil
},
}
output := new(bytes.Buffer)
app.Writer = output
app.Run([]string{"test", "-h"})
if output.Len() > 0 {
t.Errorf("unexpected output: %s", output.String())
}
}
func Test_Version_Custom_Flags(t *testing.T) {
oldFlag := VersionFlag
defer func() {
VersionFlag = oldFlag
}()
VersionFlag = BoolFlag{
Name: "version, V",
Usage: "show version",
}
app := App{
Flags: []Flag{
BoolFlag{Name: "foo, v"},
},
Action: func(ctx *Context) error {
if ctx.Bool("v") != true {
t.Errorf("custom version flag not set")
}
return nil
},
}
output := new(bytes.Buffer)
app.Writer = output
app.Run([]string{"test", "-v"})
if output.Len() > 0 {
t.Errorf("unexpected output: %s", output.String())
}
}
func Test_helpCommand_Action_ErrorIfNoTopic(t *testing.T) {
app := NewApp()
set := flag.NewFlagSet("test", 0)
set.Parse([]string{"foo"})
c := NewContext(app, set, nil)
err := helpCommand.Action.(func(*Context) error)(c)
if err == nil {
t.Fatalf("expected error from helpCommand.Action(), but got nil")
}
exitErr, ok := err.(*ExitError)
if !ok {
t.Fatalf("expected ExitError from helpCommand.Action(), but instead got: %v", err.Error())
}
if !strings.HasPrefix(exitErr.Error(), "No help topic for") {
t.Fatalf("expected an unknown help topic error, but got: %v", exitErr.Error())
}
if exitErr.exitCode != 3 {
t.Fatalf("expected exit value = 3, got %d instead", exitErr.exitCode)
}
}
func Test_helpCommand_InHelpOutput(t *testing.T) {
app := NewApp()
output := &bytes.Buffer{}
app.Writer = output
app.Run([]string{"test", "--help"})
s := output.String()
if strings.Contains(s, "\nCOMMANDS:\nGLOBAL OPTIONS:\n") {
t.Fatalf("empty COMMANDS section detected: %q", s)
}
if !strings.Contains(s, "help, h") {
t.Fatalf("missing \"help, h\": %q", s)
}
}
func Test_helpSubcommand_Action_ErrorIfNoTopic(t *testing.T) {
app := NewApp()
set := flag.NewFlagSet("test", 0)
set.Parse([]string{"foo"})
c := NewContext(app, set, nil)
err := helpSubcommand.Action.(func(*Context) error)(c)
if err == nil {
t.Fatalf("expected error from helpCommand.Action(), but got nil")
}
exitErr, ok := err.(*ExitError)
if !ok {
t.Fatalf("expected ExitError from helpCommand.Action(), but instead got: %v", err.Error())
}
if !strings.HasPrefix(exitErr.Error(), "No help topic for") {
t.Fatalf("expected an unknown help topic error, but got: %v", exitErr.Error())
}
if exitErr.exitCode != 3 {
t.Fatalf("expected exit value = 3, got %d instead", exitErr.exitCode)
}
}
func TestShowAppHelp_CommandAliases(t *testing.T) {
app := &App{
Commands: []Command{
{
Name: "frobbly",
Aliases: []string{"fr", "frob"},
Action: func(ctx *Context) error {
return nil
},
},
},
}
output := &bytes.Buffer{}
app.Writer = output
app.Run([]string{"foo", "--help"})
if !strings.Contains(output.String(), "frobbly, fr, frob") {
t.Errorf("expected output to include all command aliases; got: %q", output.String())
}
}
func TestShowCommandHelp_CommandAliases(t *testing.T) {
app := &App{
Commands: []Command{
{
Name: "frobbly",
Aliases: []string{"fr", "frob", "bork"},
Action: func(ctx *Context) error {
return nil
},
},
},
}
output := &bytes.Buffer{}
app.Writer = output
app.Run([]string{"foo", "help", "fr"})
if !strings.Contains(output.String(), "frobbly") {
t.Errorf("expected output to include command name; got: %q", output.String())
}
if strings.Contains(output.String(), "bork") {
t.Errorf("expected output to exclude command aliases; got: %q", output.String())
}
}
func TestShowSubcommandHelp_CommandAliases(t *testing.T) {
app := &App{
Commands: []Command{
{
Name: "frobbly",
Aliases: []string{"fr", "frob", "bork"},
Action: func(ctx *Context) error {
return nil
},
},
},
}
output := &bytes.Buffer{}
app.Writer = output
app.Run([]string{"foo", "help"})
if !strings.Contains(output.String(), "frobbly, fr, frob, bork") {
t.Errorf("expected output to include all command aliases; got: %q", output.String())
}
}
func TestShowAppHelp_HiddenCommand(t *testing.T) {
app := &App{
Commands: []Command{
{
Name: "frobbly",
Action: func(ctx *Context) error {
return nil
},
},
{
Name: "secretfrob",
Hidden: true,
Action: func(ctx *Context) error {
return nil
},
},
},
}
output := &bytes.Buffer{}
app.Writer = output
app.Run([]string{"app", "--help"})
if strings.Contains(output.String(), "secretfrob") {
t.Errorf("expected output to exclude \"secretfrob\"; got: %q", output.String())
}
if !strings.Contains(output.String(), "frobbly") {
t.Errorf("expected output to include \"frobbly\"; got: %q", output.String())
}
}

View file

@ -1,28 +0,0 @@
package cli
import (
"os"
"reflect"
"runtime"
"strings"
"testing"
)
var (
wd, _ = os.Getwd()
)
func expect(t *testing.T, a interface{}, b interface{}) {
_, fn, line, _ := runtime.Caller(1)
fn = strings.Replace(fn, wd+"/", "", -1)
if !reflect.DeepEqual(a, b) {
t.Errorf("(%s:%d) Expected %v (type %v) - Got %v (type %v)", fn, line, b, reflect.TypeOf(b), a, reflect.TypeOf(a))
}
}
func refute(t *testing.T, a interface{}, b interface{}) {
if reflect.DeepEqual(a, b) {
t.Errorf("Did not expect %v (type %v) - Got %v (type %v)", b, reflect.TypeOf(b), a, reflect.TypeOf(a))
}
}

View file

@ -1,9 +0,0 @@
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
package cli
import "os"
func clearenv() {
os.Clearenv()
}

View file

@ -1,20 +0,0 @@
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
}
}
}
}

122
vendor/github.com/urfave/cli/runtests generated vendored
View file

@ -1,122 +0,0 @@
#!/usr/bin/env python
from __future__ import print_function
import argparse
import os
import sys
import tempfile
from subprocess import check_call, check_output
PACKAGE_NAME = os.environ.get(
'CLI_PACKAGE_NAME', 'github.com/urfave/cli'
)
def main(sysargs=sys.argv[:]):
targets = {
'vet': _vet,
'test': _test,
'gfmrun': _gfmrun,
'toc': _toc,
'gen': _gen,
}
parser = argparse.ArgumentParser()
parser.add_argument(
'target', nargs='?', choices=tuple(targets.keys()), default='test'
)
args = parser.parse_args(sysargs[1:])
targets[args.target]()
return 0
def _test():
if check_output('go version'.split()).split()[2] < 'go1.2':
_run('go test -v .')
return
coverprofiles = []
for subpackage in ['', 'altsrc']:
coverprofile = 'cli.coverprofile'
if subpackage != '':
coverprofile = '{}.coverprofile'.format(subpackage)
coverprofiles.append(coverprofile)
_run('go test -v'.split() + [
'-coverprofile={}'.format(coverprofile),
('{}/{}'.format(PACKAGE_NAME, subpackage)).rstrip('/')
])
combined_name = _combine_coverprofiles(coverprofiles)
_run('go tool cover -func={}'.format(combined_name))
os.remove(combined_name)
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 ./...')
def _toc():
_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 _gfmrun_count():
with open('README.md') as infile:
lines = infile.read().splitlines()
return len(filter(_is_go_runnable, lines))
def _is_go_runnable(line):
return line.startswith('package main')
def _combine_coverprofiles(coverprofiles):
combined = tempfile.NamedTemporaryFile(
suffix='.coverprofile', delete=False
)
combined.write('mode: set\n')
for coverprofile in coverprofiles:
with open(coverprofile, 'r') as infile:
for line in infile.readlines():
if not line.startswith('mode: '):
combined.write(line)
combined.flush()
name = combined.name
combined.close()
return name
if __name__ == '__main__':
sys.exit(main())