Resolved compile-time errors since merging from v1

main
Dan Buch 7 years ago
parent a61867e5e6
commit 47a412375f
Signed by: meatballhat
GPG Key ID: 9685130D8B763EA7

@ -11,6 +11,8 @@ import (
"reflect"
"strings"
"testing"
"github.com/stretchr/testify/assert"
)
var (
@ -201,14 +203,15 @@ func ExampleApp_Run_noAction() {
}
func ExampleApp_Run_subcommandNoAction() {
app := App{}
app.Name = "greet"
app.Commands = []Command{
{
Name: "describeit",
Aliases: []string{"d"},
Usage: "use it to see a description",
Description: "This is how we describe describeit the function",
app := &App{
Name: "greet",
Commands: []*Command{
{
Name: "describeit",
Aliases: []string{"d"},
Usage: "use it to see a description",
Description: "This is how we describe describeit the function",
},
},
}
app.Run([]string{"greet", "describeit"})
@ -273,10 +276,10 @@ func TestApp_Run(t *testing.T) {
}
err := app.Run([]string{"command", "foo"})
expect(t, err, nil)
assert.Nil(t, err)
err = app.Run([]string{"command", "bar"})
expect(t, err, nil)
expect(t, s, "foobar")
assert.Nil(t, err)
assert.Equal(t, "foobar", s)
}
var commandAppTests = []struct {
@ -292,12 +295,11 @@ var commandAppTests = []struct {
}
func TestApp_Command(t *testing.T) {
app := &App{}
fooCommand := &Command{Name: "foobar", Aliases: []string{"f"}}
batCommand := &Command{Name: "batbaz", Aliases: []string{"b"}}
app.Commands = []*Command{
fooCommand,
batCommand,
app := &App{
Commands: []*Command{
{Name: "foobar", Aliases: []string{"f"}},
{Name: "batbaz", Aliases: []string{"b"}},
},
}
for _, test := range commandAppTests {
@ -314,24 +316,25 @@ func TestApp_Setup_defaultsWriter(t *testing.T) {
func TestApp_CommandWithArgBeforeFlags(t *testing.T) {
var parsedOption, firstArg string
app := NewApp()
command := Command{
Name: "cmd",
Flags: []Flag{
StringFlag{Name: "option", Value: "", Usage: "some option"},
},
Action: func(c *Context) error {
parsedOption = c.String("option")
firstArg = c.Args().First()
return nil
app := &App{
Commands: []*Command{
{
Name: "cmd",
Flags: []Flag{
&StringFlag{Name: "option", Value: "", Usage: "some option"},
},
Action: func(c *Context) error {
parsedOption = c.String("option")
firstArg = c.Args().First()
return nil
},
},
},
}
app.Commands = []Command{command}
app.Run([]string{"", "cmd", "my-arg", "--option", "my-option"})
expect(t, parsedOption, "my-option")
expect(t, firstArg, "my-arg")
assert.Equal(t, parsedOption, "my-option")
assert.Equal(t, firstArg, "my-arg")
}
func TestApp_RunAsSubcommandParseFlags(t *testing.T) {
@ -384,19 +387,21 @@ func TestApp_CommandWithFlagBeforeTerminator(t *testing.T) {
var parsedOption string
var args Args
app := &App{}
command := &Command{
Name: "cmd",
Flags: []Flag{
&StringFlag{Name: "option", Value: "", Usage: "some option"},
},
Action: func(c *Context) error {
parsedOption = c.String("option")
args = c.Args()
return nil
app := &App{
Commands: []*Command{
{
Name: "cmd",
Flags: []Flag{
&StringFlag{Name: "option", Value: "", Usage: "some option"},
},
Action: func(c *Context) error {
parsedOption = c.String("option")
args = c.Args()
return nil
},
},
},
}
app.Commands = []*Command{command}
app.Run([]string{"", "cmd", "--option", "my-option", "my-arg", "--", "--notARealFlag"})
@ -409,15 +414,17 @@ func TestApp_CommandWithFlagBeforeTerminator(t *testing.T) {
func TestApp_CommandWithDash(t *testing.T) {
var args Args
app := &App{}
command := &Command{
Name: "cmd",
Action: func(c *Context) error {
args = c.Args()
return nil
app := &App{
Commands: []*Command{
{
Name: "cmd",
Action: func(c *Context) error {
args = c.Args()
return nil
},
},
},
}
app.Commands = []*Command{command}
app.Run([]string{"", "cmd", "my-arg", "-"})
@ -428,15 +435,17 @@ func TestApp_CommandWithDash(t *testing.T) {
func TestApp_CommandWithNoFlagBeforeTerminator(t *testing.T) {
var args Args
app := &App{}
command := &Command{
Name: "cmd",
Action: func(c *Context) error {
args = c.Args()
return nil
app := &App{
Commands: []*Command{
{
Name: "cmd",
Action: func(c *Context) error {
args = c.Args()
return nil
},
},
},
}
app.Commands = []*Command{command}
app.Run([]string{"", "cmd", "my-arg", "--", "notAFlagAtAll"})
@ -518,22 +527,24 @@ func TestApp_ParseSliceFlags(t *testing.T) {
var parsedIntSlice []int
var parsedStringSlice []string
app := &App{}
command := &Command{
Name: "cmd",
Flags: []Flag{
&IntSliceFlag{Name: "p", Value: NewIntSlice(), Usage: "set one or more ip addr"},
&StringSliceFlag{Name: "ip", Value: NewStringSlice(), Usage: "set one or more ports to open"},
},
Action: func(c *Context) error {
parsedIntSlice = c.IntSlice("p")
parsedStringSlice = c.StringSlice("ip")
parsedOption = c.String("option")
firstArg = c.Args().First()
return nil
app := &App{
Commands: []*Command{
{
Name: "cmd",
Flags: []Flag{
&IntSliceFlag{Name: "p", Value: NewIntSlice(), Usage: "set one or more ip addr"},
&StringSliceFlag{Name: "ip", Value: NewStringSlice(), Usage: "set one or more ports to open"},
},
Action: func(c *Context) error {
parsedIntSlice = c.IntSlice("p")
parsedStringSlice = c.StringSlice("ip")
parsedOption = c.String("option")
firstArg = c.Args().First()
return nil
},
},
},
}
app.Commands = []*Command{command}
app.Run([]string{"", "cmd", "-p", "22", "-p", "80", "-ip", "8.8.8.8", "-ip", "8.8.4.4", "my-arg"})
@ -576,20 +587,22 @@ func TestApp_ParseSliceFlagsWithMissingValue(t *testing.T) {
var parsedIntSlice []int
var parsedStringSlice []string
app := &App{}
command := &Command{
Name: "cmd",
Flags: []Flag{
&IntSliceFlag{Name: "a", Usage: "set numbers"},
&StringSliceFlag{Name: "str", Usage: "set strings"},
},
Action: func(c *Context) error {
parsedIntSlice = c.IntSlice("a")
parsedStringSlice = c.StringSlice("str")
return nil
app := &App{
Commands: []*Command{
{
Name: "cmd",
Flags: []Flag{
&IntSliceFlag{Name: "a", Usage: "set numbers"},
&StringSliceFlag{Name: "str", Usage: "set strings"},
},
Action: func(c *Context) error {
parsedIntSlice = c.IntSlice("a")
parsedStringSlice = c.StringSlice("str")
return nil
},
},
},
}
app.Commands = []*Command{command}
app.Run([]string{"", "cmd", "-a", "2", "-str", "A", "my-arg"})
@ -1569,8 +1582,8 @@ func (c *customBoolFlag) String() string {
return "***" + c.Nombre + "***"
}
func (c *customBoolFlag) GetName() string {
return c.Nombre
func (c *customBoolFlag) Names() []string {
return []string{c.Nombre}
}
func (c *customBoolFlag) Apply(set *flag.FlagSet) {
@ -1578,8 +1591,9 @@ func (c *customBoolFlag) Apply(set *flag.FlagSet) {
}
func TestCustomFlagsUnused(t *testing.T) {
app := NewApp()
app.Flags = []Flag{&customBoolFlag{"custom"}}
app := &App{
Flags: []Flag{&customBoolFlag{"custom"}},
}
err := app.Run([]string{"foo"})
if err != nil {
@ -1588,8 +1602,9 @@ func TestCustomFlagsUnused(t *testing.T) {
}
func TestCustomFlagsUsed(t *testing.T) {
app := NewApp()
app.Flags = []Flag{&customBoolFlag{"custom"}}
app := &App{
Flags: []Flag{&customBoolFlag{"custom"}},
}
err := app.Run([]string{"foo", "--custom=bar"})
if err != nil {
@ -1598,12 +1613,12 @@ func TestCustomFlagsUsed(t *testing.T) {
}
func TestCustomHelpVersionFlags(t *testing.T) {
app := NewApp()
app := &App{}
// Be sure to reset the global flags
defer func(helpFlag Flag, versionFlag Flag) {
HelpFlag = helpFlag
VersionFlag = versionFlag
HelpFlag = helpFlag.(*BoolFlag)
VersionFlag = versionFlag.(*BoolFlag)
}(HelpFlag, VersionFlag)
HelpFlag = &customBoolFlag{"help-custom"}
@ -1615,166 +1630,47 @@ func TestCustomHelpVersionFlags(t *testing.T) {
}
}
func TestHandleAction_WithNonFuncAction(t *testing.T) {
app := NewApp()
app.Action = 42
fs, err := flagSet(app.Name, app.Flags)
if err != nil {
t.Errorf("error creating FlagSet: %s", err)
}
err = HandleAction(app.Action, NewContext(app, fs, nil))
if err == nil {
t.Fatalf("expected to receive error from Run, got none")
}
exitErr, ok := err.(*ExitError)
if !ok {
t.Fatalf("expected to receive a *ExitError")
}
if !strings.HasPrefix(exitErr.Error(), "ERROR invalid Action type.") {
t.Fatalf("expected an unknown Action error, but got: %v", exitErr.Error())
}
if exitErr.ExitCode() != 2 {
t.Fatalf("expected error exit code to be 2, but got: %v", exitErr.ExitCode())
}
}
func TestHandleAction_WithInvalidFuncSignature(t *testing.T) {
app := NewApp()
app.Action = func() string { return "" }
fs, err := flagSet(app.Name, app.Flags)
if err != nil {
t.Errorf("error creating FlagSet: %s", err)
}
err = HandleAction(app.Action, NewContext(app, fs, nil))
if err == nil {
t.Fatalf("expected to receive error from Run, got none")
}
exitErr, ok := err.(*ExitError)
if !ok {
t.Fatalf("expected to receive a *ExitError")
}
if !strings.HasPrefix(exitErr.Error(), "ERROR invalid Action type") {
t.Fatalf("expected an unknown Action error, but got: %v", exitErr.Error())
}
if exitErr.ExitCode() != 2 {
t.Fatalf("expected error exit code to be 2, but got: %v", exitErr.ExitCode())
}
}
func TestHandleAction_WithInvalidFuncReturnSignature(t *testing.T) {
app := NewApp()
app.Action = func(_ *Context) (int, error) { return 0, nil }
fs, err := flagSet(app.Name, app.Flags)
if err != nil {
t.Errorf("error creating FlagSet: %s", err)
}
err = HandleAction(app.Action, NewContext(app, fs, nil))
if err == nil {
t.Fatalf("expected to receive error from Run, got none")
}
exitErr, ok := err.(*ExitError)
if !ok {
t.Fatalf("expected to receive a *ExitError")
}
if !strings.HasPrefix(exitErr.Error(), "ERROR invalid Action type") {
t.Fatalf("expected an invalid Action signature error, but got: %v", exitErr.Error())
}
if exitErr.ExitCode() != 2 {
t.Fatalf("expected error exit code to be 2, but got: %v", exitErr.ExitCode())
}
}
func TestHandleAction_WithUnknownPanic(t *testing.T) {
defer func() { refute(t, recover(), nil) }()
var fn ActionFunc
app := NewApp()
app.Action = func(ctx *Context) error {
fn(ctx)
return nil
}
fs, err := flagSet(app.Name, app.Flags)
if err != nil {
t.Errorf("error creating FlagSet: %s", err)
}
HandleAction(app.Action, NewContext(app, fs, nil))
}
func TestShellCompletionForIncompleteFlags(t *testing.T) {
app := NewApp()
app.Flags = []Flag{
IntFlag{
Name: "test-completion",
app := &App{
Flags: []Flag{
&IntFlag{
Name: "test-completion",
},
},
}
app.EnableBashCompletion = true
app.BashComplete = func(ctx *Context) {
for _, command := range ctx.App.Commands {
if command.Hidden {
continue
}
for _, name := range command.Names() {
fmt.Fprintln(ctx.App.Writer, name)
}
}
for _, flag := range ctx.App.Flags {
for _, name := range strings.Split(flag.GetName(), ",") {
if name == BashCompletionFlag.GetName() {
EnableShellCompletion: true,
ShellComplete: func(ctx *Context) {
for _, command := range ctx.App.Commands {
if command.Hidden {
continue
}
switch name = strings.TrimSpace(name); len(name) {
case 0:
case 1:
fmt.Fprintln(ctx.App.Writer, "-"+name)
default:
fmt.Fprintln(ctx.App.Writer, "--"+name)
for _, name := range command.Names() {
fmt.Fprintln(ctx.App.Writer, name)
}
}
}
}
app.Action = func(ctx *Context) error {
return fmt.Errorf("should not get here")
}
err := app.Run([]string{"", "--test-completion", "--" + BashCompletionFlag.GetName()})
if err != nil {
t.Errorf("app should not return an error: %s", err)
}
}
func TestHandleActionActuallyWorksWithActions(t *testing.T) {
var f ActionFunc
called := false
f = func(c *Context) error {
called = true
return nil
for _, flag := range ctx.App.Flags {
for _, name := range flag.Names() {
if name == genCompName() {
continue
}
switch name = strings.TrimSpace(name); len(name) {
case 0:
case 1:
fmt.Fprintln(ctx.App.Writer, "-"+name)
default:
fmt.Fprintln(ctx.App.Writer, "--"+name)
}
}
}
},
Action: func(ctx *Context) error {
return fmt.Errorf("should not get here")
},
}
err := HandleAction(f, nil)
err := app.Run([]string{"", "--test-completion", "--" + genCompName()})
if err != nil {
t.Errorf("Should not have errored: %v", err)
}
if !called {
t.Errorf("Function was not called")
t.Errorf("app should not return an error: %s", err)
}
}

@ -124,15 +124,16 @@ func TestCommand_Run_BeforeSavesMetadata(t *testing.T) {
}
func TestCommand_OnUsageError_hasCommandContext(t *testing.T) {
app := NewApp()
app.Commands = []Command{
{
Name: "bar",
Flags: []Flag{
IntFlag{Name: "flag"},
},
OnUsageError: func(c *Context, err error, _ bool) error {
return fmt.Errorf("intercepted in %s: %s", c.Command.Name, err.Error())
app := &App{
Commands: []*Command{
{
Name: "bar",
Flags: []Flag{
&IntFlag{Name: "flag"},
},
OnUsageError: func(c *Context, err error, _ bool) error {
return fmt.Errorf("intercepted in %s: %s", c.Command.Name, err.Error())
},
},
},
}
@ -176,23 +177,24 @@ func TestCommand_OnUsageError_WithWrongFlagValue(t *testing.T) {
}
func TestCommand_OnUsageError_WithSubcommand(t *testing.T) {
app := NewApp()
app.Commands = []Command{
{
Name: "bar",
Subcommands: []Command{
{
Name: "baz",
app := &App{
Commands: []*Command{
{
Name: "bar",
Subcommands: []*Command{
{
Name: "baz",
},
},
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())
},
},
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())
},
},
}
@ -208,22 +210,23 @@ func TestCommand_OnUsageError_WithSubcommand(t *testing.T) {
}
func TestCommand_Run_SubcommandsCanUseErrWriter(t *testing.T) {
app := NewApp()
app.ErrWriter = ioutil.Discard
app.Commands = []Command{
{
Name: "bar",
Usage: "this is for testing",
Subcommands: []Command{
{
Name: "baz",
Usage: "this is for testing",
Action: func(c *Context) error {
if c.App.ErrWriter != ioutil.Discard {
return fmt.Errorf("ErrWriter not passed")
}
return nil
app := &App{
ErrWriter: ioutil.Discard,
Commands: []*Command{
{
Name: "bar",
Usage: "this is for testing",
Subcommands: []*Command{
{
Name: "baz",
Usage: "this is for testing",
Action: func(c *Context) error {
if c.App.ErrWriter != ioutil.Discard {
return fmt.Errorf("ErrWriter not passed")
}
return nil
},
},
},
},

@ -121,6 +121,11 @@ func (c *Context) Lineage() []*Context {
return lineage
}
// value returns the value of the flag coressponding to `name`
func (c *Context) value(name string) interface{} {
return c.flagSet.Lookup(name).Value.(flag.Getter).Get()
}
// Args returns the command line arguments associated with the context.
func (c *Context) Args() Args {
ret := args(c.flagSet.Args())

@ -2,7 +2,6 @@ package cli
import (
"flag"
"os"
"sort"
"testing"
"time"
@ -158,78 +157,6 @@ func TestContext_IsSet(t *testing.T) {
expect(t, ctx.IsSet("bogus"), 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, noEnvVarIsSet, nIsSet bool
globalTimeoutIsSet, TIsSet, globalNoEnvVarIsSet, NIsSet bool
)
clearenv()
os.Setenv("GLOBAL_APP_TIMEOUT_SECONDS", "15.5")
os.Setenv("APP_TIMEOUT_SECONDS", "15.5")
os.Setenv("APP_PASSWORD", "")
a := App{
Flags: []Flag{
&Float64Flag{
Name: "global-timeout",
Aliases: []string{"T"},
EnvVars: []string{"GLOBAL_APP_TIMEOUT_SECONDS"},
},
&Float64Flag{
Name: "global-no-env-var",
Aliases: []string{"N"},
},
},
Commands: []*Command{
{
Name: "hello",
Flags: []Flag{
&Float64Flag{
Name: "timeout",
Aliases: []string{"t"},
EnvVars: []string{"APP_TIMEOUT_SECONDS"},
},
&Float64Flag{
Name: "no-env-var",
Aliases: []string{"n"},
},
},
Action: func(ctx *Context) error {
globalTimeoutIsSet = ctx.IsSet("global-timeout")
TIsSet = ctx.IsSet("T")
globalNoEnvVarIsSet = ctx.IsSet("global-no-env-var")
NIsSet = ctx.IsSet("N")
timeoutIsSet = ctx.IsSet("timeout")
tIsSet = ctx.IsSet("t")
noEnvVarIsSet = ctx.IsSet("no-env-var")
nIsSet = ctx.IsSet("n")
return nil
},
},
},
}
a.Run([]string{"run", "hello"})
expect(t, globalTimeoutIsSet, true)
expect(t, TIsSet, true)
expect(t, globalNoEnvVarIsSet, false)
expect(t, NIsSet, false)
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")

@ -66,7 +66,7 @@ type exitError struct {
// Exit wraps a message and exit code into an ExitCoder suitable for handling by
// HandleExitCoder
func Exit(message string, exitCode int) ExitCoder {
func Exit(message interface{}, exitCode int) ExitCoder {
return &exitError{
exitCode: exitCode,
message: message,
@ -74,7 +74,7 @@ func Exit(message string, exitCode int) ExitCoder {
}
func (ee *exitError) Error() string {
return ee.message
return fmt.Sprintf("%v", ee.message)
}
func (ee *exitError) ExitCode() int {
@ -112,7 +112,7 @@ func HandleExitCoder(err error) {
func handleMultiError(multiErr MultiError) int {
code := 1
for _, merr := range multiErr.Errors {
for _, merr := range multiErr.Errors() {
if multiErr2, ok := merr.(MultiError); ok {
code = handleMultiError(multiErr2)
} else {

@ -5,6 +5,8 @@ import (
"errors"
"fmt"
"testing"
"github.com/stretchr/testify/assert"
)
func TestHandleExitCoder_nil(t *testing.T) {
@ -95,7 +97,7 @@ func TestHandleExitCoder_ErrorWithFormat(t *testing.T) {
ErrWriter = fakeErrWriter
}()
err := NewExitError(NewErrorWithFormat("I am formatted"), 1)
err := Exit(NewErrorWithFormat("I am formatted"), 1)
HandleExitCoder(err)
expect(t, called, true)
@ -114,9 +116,9 @@ func TestHandleExitCoder_MultiErrorWithFormat(t *testing.T) {
defer func() { OsExiter = fakeOsExiter }()
err := NewMultiError(NewErrorWithFormat("err1"), NewErrorWithFormat("err2"))
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")
assert.True(t, called)
assert.Equal(t, "This the format: err1\nThis the format: err2\n", ErrWriter.(*bytes.Buffer).String())
}

@ -22,11 +22,19 @@ var (
)
// GenerateCompletionFlag enables completion for all commands and subcommands
var GenerateCompletionFlag = &BoolFlag{
var GenerateCompletionFlag Flag = &BoolFlag{
Name: "generate-completion",
Hidden: true,
}
func genCompName() string {
names := GenerateCompletionFlag.Names()
if len(names) == 0 {
return "generate-completion"
}
return names[0]
}
// InitCompletionFlag generates completion code
var InitCompletionFlag = &StringFlag{
Name: "init-completion",
@ -34,7 +42,7 @@ var InitCompletionFlag = &StringFlag{
}
// VersionFlag prints the version for the application
var VersionFlag = &BoolFlag{
var VersionFlag Flag = &BoolFlag{
Name: "version",
Aliases: []string{"v"},
Usage: "print the version",
@ -43,7 +51,7 @@ var VersionFlag = &BoolFlag{
// HelpFlag prints the help for all commands and subcommands.
// Set to nil to disable the flag. The subcommand
// will still be added unless HideHelp is set to true.
var HelpFlag = &BoolFlag{
var HelpFlag Flag = &BoolFlag{
Name: "help",
Aliases: []string{"h"},
Usage: "show help",
@ -121,7 +129,14 @@ type Generic interface {
// Apply takes the flagset and calls Set on the generic flag with the value
// provided by the user for parsing by the flag
// Ignores parsing errors
func (f *GenericFlag) Apply(set *flag.FlagSet) {
f.ApplyWithError(set)
}
// ApplyWithError takes the flagset and calls Set on the generic flag with the
// value provided by the user for parsing by the flag
func (f *GenericFlag) ApplyWithError(set *flag.FlagSet) error {
val := f.Value
if f.EnvVars != nil {
for _, envVar := range f.EnvVars {
@ -135,6 +150,7 @@ func (f *GenericFlag) Apply(set *flag.FlagSet) {
for _, name := range f.Names() {
set.Var(val, name, f.Usage)
}
return nil
}
// StringSlice wraps a []string to satisfy flag.Value
@ -188,7 +204,13 @@ func (f *StringSlice) Get() interface{} {
}
// Apply populates the flag given the flag set and environment
// Ignores errors
func (f *StringSliceFlag) Apply(set *flag.FlagSet) {
f.ApplyWithError(set)
}
// ApplyWithError populates the flag given the flag set and environment
func (f *StringSliceFlag) ApplyWithError(set *flag.FlagSet) error {
if f.EnvVars != nil {
for _, envVar := range f.EnvVars {
if envVal, ok := syscall.Getenv(envVar); ok {
@ -212,6 +234,7 @@ func (f *StringSliceFlag) Apply(set *flag.FlagSet) {
for _, name := range f.Names() {
set.Var(f.Value, name, f.Usage)
}
return nil
}
// IntSlice wraps an []int to satisfy flag.Value
@ -285,7 +308,13 @@ func (f *IntSlice) Get() interface{} {
}
// Apply populates the flag given the flag set and environment
// Ignores errors
func (f *IntSliceFlag) Apply(set *flag.FlagSet) {
f.ApplyWithError(set)
}
// ApplyWithError populates the flag given the flag set and environment
func (f *IntSliceFlag) ApplyWithError(set *flag.FlagSet) error {
if f.EnvVars != nil {
for _, envVar := range f.EnvVars {
if envVal, ok := syscall.Getenv(envVar); ok {
@ -309,6 +338,7 @@ func (f *IntSliceFlag) Apply(set *flag.FlagSet) {
for _, name := range f.Names() {
set.Var(f.Value, name, f.Usage)
}
return nil
}
// Int64Slice is an opaque type for []int to satisfy flag.Value
@ -362,7 +392,13 @@ func (f *Int64Slice) Get() interface{} {
}
// Apply populates the flag given the flag set and environment
// Ignores errors
func (f *Int64SliceFlag) Apply(set *flag.FlagSet) {
f.ApplyWithError(set)
}
// ApplyWithError populates the flag given the flag set and environment
func (f *Int64SliceFlag) ApplyWithError(set *flag.FlagSet) error {
if f.EnvVars != nil {
for _, envVar := range f.EnvVars {
if envVal, ok := syscall.Getenv(envVar); ok {
@ -386,10 +422,17 @@ func (f *Int64SliceFlag) Apply(set *flag.FlagSet) {
for _, name := range f.Names() {
set.Var(f.Value, name, f.Usage)
}
return nil
}
// Apply populates the flag given the flag set and environment
// Ignores errors
func (f *BoolFlag) Apply(set *flag.FlagSet) {
f.ApplyWithError(set)
}
// ApplyWithError populates the flag given the flag set and environment
func (f *BoolFlag) ApplyWithError(set *flag.FlagSet) error {
if f.EnvVars != nil {
for _, envVar := range f.EnvVars {
if envVal, ok := syscall.Getenv(envVar); ok {
@ -398,7 +441,6 @@ func (f *BoolFlag) Apply(set *flag.FlagSet) {
f.Value = envValBool
}
val = envValBool
break
}
}
@ -411,10 +453,17 @@ func (f *BoolFlag) Apply(set *flag.FlagSet) {
}
set.Bool(name, f.Value, f.Usage)
}
return nil
}
// Apply populates the flag given the flag set and environment
// Ignores errors
func (f *StringFlag) Apply(set *flag.FlagSet) {
f.ApplyWithError(set)
}
// ApplyWithError populates the flag given the flag set and environment
func (f *StringFlag) ApplyWithError(set *flag.FlagSet) error {
if f.EnvVars != nil {
for _, envVar := range f.EnvVars {
if envVal, ok := syscall.Getenv(envVar); ok {
@ -431,10 +480,17 @@ func (f *StringFlag) Apply(set *flag.FlagSet) {
}
set.String(name, f.Value, f.Usage)
}
return nil
}
// Apply populates the flag given the flag set and environment
// Ignores errors
func (f *IntFlag) Apply(set *flag.FlagSet) {
f.ApplyWithError(set)
}
// ApplyWithError populates the flag given the flag set and environment
func (f *IntFlag) ApplyWithError(set *flag.FlagSet) error {
if f.EnvVars != nil {
for _, envVar := range f.EnvVars {
if envVal, ok := syscall.Getenv(envVar); ok {
@ -455,10 +511,17 @@ func (f *IntFlag) Apply(set *flag.FlagSet) {
}
set.Int(name, f.Value, f.Usage)
}
return nil
}
// Apply populates the flag given the flag set and environment
// Ignores errors
func (f *Int64Flag) Apply(set *flag.FlagSet) {
f.ApplyWithError(set)
}
// ApplyWithError populates the flag given the flag set and environment
func (f *Int64Flag) ApplyWithError(set *flag.FlagSet) error {
if f.EnvVars != nil {
for _, envVar := range f.EnvVars {
if envVal, ok := syscall.Getenv(envVar); ok {
@ -476,14 +539,21 @@ func (f *Int64Flag) Apply(set *flag.FlagSet) {
for _, name := range f.Names() {
if f.Destination != nil {
set.Int64Var(f.Destination, name, f.Value, f.Usage)
return
return nil
}
set.Int64(name, f.Value, f.Usage)
}
return nil
}
// Apply populates the flag given the flag set and environment
// Ignores errors
func (f *UintFlag) Apply(set *flag.FlagSet) {
f.ApplyWithError(set)
}
// ApplyWithError populates the flag given the flag set and environment
func (f *UintFlag) ApplyWithError(set *flag.FlagSet) error {
if f.EnvVars != nil {
for _, envVar := range f.EnvVars {
if envVal, ok := syscall.Getenv(envVar); ok {
@ -501,14 +571,21 @@ func (f *UintFlag) Apply(set *flag.FlagSet) {
for _, name := range f.Names() {
if f.Destination != nil {
set.UintVar(f.Destination, name, f.Value, f.Usage)
return
return nil
}
set.Uint(name, f.Value, f.Usage)
}
return nil
}
// Apply populates the flag given the flag set and environment
// Ignores errors
func (f *Uint64Flag) Apply(set *flag.FlagSet) {
f.ApplyWithError(set)
}
// ApplyWithError populates the flag given the flag set and environment
func (f *Uint64Flag) ApplyWithError(set *flag.FlagSet) error {
if f.EnvVars != nil {
for _, envVar := range f.EnvVars {
if envVal, ok := syscall.Getenv(envVar); ok {
@ -526,14 +603,21 @@ func (f *Uint64Flag) Apply(set *flag.FlagSet) {
for _, name := range f.Names() {
if f.Destination != nil {
set.Uint64Var(f.Destination, name, f.Value, f.Usage)
return
return nil
}
set.Uint64(name, f.Value, f.Usage)
}
return nil
}
// Apply populates the flag given the flag set and environment
// Ignores errors
func (f *DurationFlag) Apply(set *flag.FlagSet) {
f.ApplyWithError(set)
}
// ApplyWithError populates the flag given the flag set and environment
func (f *DurationFlag) ApplyWithError(set *flag.FlagSet) error {
if f.EnvVars != nil {
for _, envVar := range f.EnvVars {
if envVal, ok := syscall.Getenv(envVar); ok {
@ -555,10 +639,17 @@ func (f *DurationFlag) Apply(set *flag.FlagSet) {
}
set.Duration(name, f.Value, f.Usage)
}
return nil
}
// Apply populates the flag given the flag set and environment
// Ignores errors
func (f *Float64Flag) Apply(set *flag.FlagSet) {
f.ApplyWithError(set)
}
// ApplyWithError populates the flag given the flag set and environment
func (f *Float64Flag) ApplyWithError(set *flag.FlagSet) error {
if f.EnvVars != nil {
for _, envVar := range f.EnvVars {
if envVal, ok := syscall.Getenv(envVar); ok {
@ -580,6 +671,7 @@ func (f *Float64Flag) Apply(set *flag.FlagSet) {
}
set.Float64(name, f.Value, f.Usage)
}
return nil
}
// NewFloat64Slice makes a *Float64Slice with default values
@ -633,7 +725,13 @@ func (f *Float64Slice) Value() []float64 {
}
// Apply populates the flag given the flag set and environment
// Ignores errors
func (f *Float64SliceFlag) Apply(set *flag.FlagSet) {
f.ApplyWithError(set)
}
// ApplyWithError populates the flag given the flag set and environment
func (f *Float64SliceFlag) ApplyWithError(set *flag.FlagSet) error {
if f.EnvVars != nil {
for _, envVar := range f.EnvVars {
if envVal, ok := syscall.Getenv(envVar); ok {
@ -658,6 +756,7 @@ func (f *Float64SliceFlag) Apply(set *flag.FlagSet) {
for _, name := range f.Names() {
set.Var(f.Value, name, f.Usage)
}
return nil
}
func visibleFlags(fl []Flag) []Flag {

@ -49,57 +49,57 @@ func TestFlagsFromEnv(t *testing.T) {
flag Flag
errRegexp string
}{
{"", false, &BoolFlag{Name: "debug", EnvVar: "DEBUG"}, ""},
{"1", true, &BoolFlag{Name: "debug", EnvVar: "DEBUG"}, ""},
{"false", false, &BoolFlag{Name: "debug", EnvVar: "DEBUG"}, ""},
{"foobar", true, &BoolFlag{Name: "debug", EnvVar: "DEBUG"}, fmt.Sprintf(`could not parse foobar as bool value for flag debug: .*`)},
{"", false, &BoolFlag{Name: "debug", EnvVars: []string{"DEBUG"}}, ""},
{"1", true, &BoolFlag{Name: "debug", EnvVars: []string{"DEBUG"}}, ""},
{"false", false, &BoolFlag{Name: "debug", EnvVars: []string{"DEBUG"}}, ""},
{"foobar", true, &BoolFlag{Name: "debug", EnvVars: []string{"DEBUG"}}, fmt.Sprintf(`could not parse foobar as bool value for flag debug: .*`)},
{"1s", 1 * time.Second, &DurationFlag{Name: "time", EnvVar: "TIME"}, ""},
{"foobar", false, &DurationFlag{Name: "time", EnvVar: "TIME"}, fmt.Sprintf(`could not parse foobar as duration for flag time: .*`)},
{"1s", 1 * time.Second, &DurationFlag{Name: "time", EnvVars: []string{"TIME"}}, ""},
{"foobar", false, &DurationFlag{Name: "time", EnvVars: []string{"TIME"}}, fmt.Sprintf(`could not parse foobar as duration for flag time: .*`)},
{"1.2", 1.2, &Float64Flag{Name: "seconds", EnvVar: "SECONDS"}, ""},
{"1", 1.0, &Float64Flag{Name: "seconds", EnvVar: "SECONDS"}, ""},
{"foobar", 0, &Float64Flag{Name: "seconds", EnvVar: "SECONDS"}, fmt.Sprintf(`could not parse foobar as float64 value for flag seconds: .*`)},
{"1.2", 1.2, &Float64Flag{Name: "seconds", EnvVars: []string{"SECONDS"}}, ""},
{"1", 1.0, &Float64Flag{Name: "seconds", EnvVars: []string{"SECONDS"}}, ""},
{"foobar", 0, &Float64Flag{Name: "seconds", EnvVars: []string{"SECONDS"}}, fmt.Sprintf(`could not parse foobar as float64 value for flag seconds: .*`)},
{"1", int64(1), &Int64Flag{Name: "seconds", EnvVar: "SECONDS"}, ""},
{"1.2", 0, &Int64Flag{Name: "seconds", EnvVar: "SECONDS"}, fmt.Sprintf(`could not parse 1.2 as int value for flag seconds: .*`)},
{"foobar", 0, &Int64Flag{Name: "seconds", EnvVar: "SECONDS"}, fmt.Sprintf(`could not parse foobar as int value for flag seconds: .*`)},
{"1", int64(1), &Int64Flag{Name: "seconds", EnvVars: []string{"SECONDS"}}, ""},
{"1.2", 0, &Int64Flag{Name: "seconds", EnvVars: []string{"SECONDS"}}, fmt.Sprintf(`could not parse 1.2 as int value for flag seconds: .*`)},
{"foobar", 0, &Int64Flag{Name: "seconds", EnvVars: []string{"SECONDS"}}, fmt.Sprintf(`could not parse foobar as int value for flag seconds: .*`)},
{"1", 1, &IntFlag{Name: "seconds", EnvVar: "SECONDS"}, ""},
{"1.2", 0, &IntFlag{Name: "seconds", EnvVar: "SECONDS"}, fmt.Sprintf(`could not parse 1.2 as int value for flag seconds: .*`)},
{"foobar", 0, &IntFlag{Name: "seconds", EnvVar: "SECONDS"}, fmt.Sprintf(`could not parse foobar as int value for flag seconds: .*`)},
{"1", 1, &IntFlag{Name: "seconds", EnvVars: []string{"SECONDS"}}, ""},
{"1.2", 0, &IntFlag{Name: "seconds", EnvVars: []string{"SECONDS"}}, fmt.Sprintf(`could not parse 1.2 as int value for flag seconds: .*`)},
{"foobar", 0, &IntFlag{Name: "seconds", EnvVars: []string{"SECONDS"}}, fmt.Sprintf(`could not parse foobar as int value for flag seconds: .*`)},
{"1,2", NewIntSlice(1, 2), &IntSliceFlag{Name: "seconds", EnvVar: "SECONDS"}, ""},
{"1.2,2", NewIntSlice(), &IntSliceFlag{Name: "seconds", EnvVar: "SECONDS"}, fmt.Sprintf(`could not parse 1.2,2 as int slice value for flag seconds: .*`)},
{"foobar", NewIntSlice(), &IntSliceFlag{Name: "seconds", EnvVar: "SECONDS"}, fmt.Sprintf(`could not parse foobar as int slice value for flag seconds: .*`)},
{"1,2", NewIntSlice(1, 2), &IntSliceFlag{Name: "seconds", EnvVars: []string{"SECONDS"}}, ""},
{"1.2,2", NewIntSlice(), &IntSliceFlag{Name: "seconds", EnvVars: []string{"SECONDS"}}, fmt.Sprintf(`could not parse 1.2,2 as int slice value for flag seconds: .*`)},
{"foobar", NewIntSlice(), &IntSliceFlag{Name: "seconds", EnvVars: []string{"SECONDS"}}, fmt.Sprintf(`could not parse foobar as int slice value for flag seconds: .*`)},
{"1,2", NewInt64Slice(1, 2), &Int64SliceFlag{Name: "seconds", EnvVar: "SECONDS"}, ""},
{"1.2,2", NewInt64Slice(), &Int64SliceFlag{Name: "seconds", EnvVar: "SECONDS"}, fmt.Sprintf(`could not parse 1.2,2 as int64 slice value for flag seconds: .*`)},
{"foobar", NewInt64Slice(), &Int64SliceFlag{Name: "seconds", EnvVar: "SECONDS"}, fmt.Sprintf(`could not parse foobar as int64 slice value for flag seconds: .*`)},
{"1,2", NewInt64Slice(1, 2), &Int64SliceFlag{Name: "seconds", EnvVars: []string{"SECONDS"}}, ""},
{"1.2,2", NewInt64Slice(), &Int64SliceFlag{Name: "seconds", EnvVars: []string{"SECONDS"}}, fmt.Sprintf(`could not parse 1.2,2 as int64 slice value for flag seconds: .*`)},
{"foobar", NewInt64Slice(), &Int64SliceFlag{Name: "seconds", EnvVars: []string{"SECONDS"}}, fmt.Sprintf(`could not parse foobar as int64 slice value for flag seconds: .*`)},
{"foo", "foo", &StringFlag{Name: "name", EnvVar: "NAME"}, ""},
{"foo", "foo", &StringFlag{Name: "name", EnvVars: []string{"NAME"}}, ""},
{"foo,bar", NewStringSlice("foo", "bar"), &StringSliceFlag{Name: "names", EnvVar: "NAMES"}, ""},
{"foo,bar", NewStringSlice("foo", "bar"), &StringSliceFlag{Name: "names", EnvVars: []string{"NAMES"}}, ""},
{"1", uint(1), &UintFlag{Name: "seconds", EnvVar: "SECONDS"}, ""},
{"1.2", 0, &UintFlag{Name: "seconds", EnvVar: "SECONDS"}, fmt.Sprintf(`could not parse 1.2 as uint value for flag seconds: .*`)},
{"foobar", 0, &UintFlag{Name: "seconds", EnvVar: "SECONDS"}, fmt.Sprintf(`could not parse foobar as uint value for flag seconds: .*`)},
{"1", uint(1), &UintFlag{Name: "seconds", EnvVars: []string{"SECONDS"}}, ""},
{"1.2", 0, &UintFlag{Name: "seconds", EnvVars: []string{"SECONDS"}}, fmt.Sprintf(`could not parse 1.2 as uint value for flag seconds: .*`)},
{"foobar", 0, &UintFlag{Name: "seconds", EnvVars: []string{"SECONDS"}}, fmt.Sprintf(`could not parse foobar as uint value for flag seconds: .*`)},
{"1", uint64(1), &Uint64Flag{Name: "seconds", EnvVar: "SECONDS"}, ""},
{"1.2", 0, &Uint64Flag{Name: "seconds", EnvVar: "SECONDS"}, fmt.Sprintf(`could not parse 1.2 as uint64 value for flag seconds: .*`)},
{"foobar", 0, &Uint64Flag{Name: "seconds", EnvVar: "SECONDS"}, fmt.Sprintf(`could not parse foobar as uint64 value for flag seconds: .*`)},
{"1", uint64(1), &Uint64Flag{Name: "seconds", EnvVars: []string{"SECONDS"}}, ""},
{"1.2", 0, &Uint64Flag{Name: "seconds", EnvVars: []string{"SECONDS"}}, fmt.Sprintf(`could not parse 1.2 as uint64 value for flag seconds: .*`)},
{"foobar", 0, &Uint64Flag{Name: "seconds", EnvVars: []string{"SECONDS"}}, fmt.Sprintf(`could not parse foobar as uint64 value for flag seconds: .*`)},
{"foo,bar", &Parser{"foo", "bar"}, &GenericFlag{Name: "names", Value: &Parser{}, EnvVar: "NAMES"}, ""},
{"foo,bar", &Parser{"foo", "bar"}, &GenericFlag{Name: "names", Value: &Parser{}, EnvVars: []string{"NAMES"}}, ""},
}
for _, test := range flagTests {
clearenv()
os.Setenv(reflect.ValueOf(test.flag).FieldByName("EnvVar").String(), test.input)
os.Setenv(reflect.ValueOf(test.flag).FieldByName("EnvVars").Slice(0, 1).String(), test.input)
a := App{
Flags: []Flag{test.flag},
Action: func(ctx *Context) error {
if !reflect.DeepEqual(ctx.value(test.flag.GetName()), test.output) {
t.Errorf("expected %+v to be parsed as %+v, instead was %+v", test.input, test.output, ctx.value(test.flag.GetName()))
if !reflect.DeepEqual(ctx.value(test.flag.Names()[0]), test.output) {
t.Errorf("expected %+v to be parsed as %+v, instead was %+v", test.input, test.output, ctx.value(test.flag.Names()[0]))
}
return nil
},

@ -266,11 +266,9 @@ func printHelp(out io.Writer, templ string, data interface{}) {
func checkVersion(c *Context) bool {
found := false
if VersionFlag.Name != "" {
for _, name := range VersionFlag.Names() {
if c.Bool(name) {
found = true
}
for _, name := range VersionFlag.Names() {
if c.Bool(name) {
found = true
}
}
return found
@ -278,11 +276,9 @@ func checkVersion(c *Context) bool {
func checkHelp(c *Context) bool {
found := false
if HelpFlag.Name != "" {
for _, name := range HelpFlag.Names() {
if c.Bool(name) {
found = true
}
for _, name := range HelpFlag.Names() {
if c.Bool(name) {
found = true
}
}
return found
@ -307,14 +303,14 @@ func checkSubcommandHelp(c *Context) bool {
}
func checkShellCompleteFlag(a *App, arguments []string) (bool, []string) {
if !a.EnableBashCompletion {
if !a.EnableShellCompletion {
return false, arguments
}
pos := len(arguments) - 1
lastArg := arguments[pos]
if lastArg != "--"+BashCompletionFlag.GetName() {
if lastArg != "--"+genCompName() {
return false, arguments
}
@ -322,7 +318,7 @@ func checkShellCompleteFlag(a *App, arguments []string) (bool, []string) {
}
func checkCompletions(c *Context) bool {
if !c.Bool(GenerateCompletionFlag.Name) && !c.App.EnableShellCompletion {
if !c.Bool(genCompName()) && !c.App.EnableShellCompletion {
return false
}
@ -339,7 +335,7 @@ func checkCompletions(c *Context) bool {
}
func checkCommandCompletions(c *Context, name string) bool {
if !c.Bool(GenerateCompletionFlag.Name) && !c.App.EnableShellCompletion {
if !c.Bool(genCompName()) && !c.App.EnableShellCompletion {
return false
}

@ -259,7 +259,7 @@ func TestShowSubcommandHelp_CommandAliases(t *testing.T) {
func TestShowCommandHelp_Customtemplate(t *testing.T) {
app := &App{
Commands: []Command{
Commands: []*Command{
{
Name: "frobbly",
Action: func(ctx *Context) error {
@ -301,7 +301,7 @@ EXAMPLES:
func TestShowSubcommandHelp_CommandUsageText(t *testing.T) {
app := &App{
Commands: []Command{
Commands: []*Command{
{
Name: "frobbly",
UsageText: "this is usage text",
@ -321,10 +321,10 @@ func TestShowSubcommandHelp_CommandUsageText(t *testing.T) {
func TestShowSubcommandHelp_SubcommandUsageText(t *testing.T) {
app := &App{
Commands: []Command{
Commands: []*Command{
{
Name: "frobbly",
Subcommands: []Command{
Subcommands: []*Command{
{
Name: "bobbly",
UsageText: "this is usage text",
@ -377,7 +377,7 @@ func TestShowAppHelp_HiddenCommand(t *testing.T) {
func TestShowAppHelp_CustomAppTemplate(t *testing.T) {
app := &App{
Commands: []Command{
Commands: []*Command{
{
Name: "frobbly",
Action: func(ctx *Context) error {

@ -1,7 +1,8 @@
#!/usr/bin/env python
from __future__ import print_function
from __future__ import print_function, unicode_literals
import argparse
import codecs
import glob
import os
import platform
@ -37,7 +38,7 @@ def _target(func):
@_target
def _test():
if check_output('go version'.split()).split()[2] < 'go1.2':
if _go_version() < 'go1.2':
_run('go test -v .')
return
@ -61,7 +62,7 @@ def _test():
@_target
def _gfmrun():
go_version = check_output('go version'.split()).split()[2]
go_version = _go_version()
if go_version < 'go1.3':
print('runtests: skip on {}'.format(go_version), file=sys.stderr)
return
@ -75,7 +76,7 @@ def _vet():
@_target
def _migrations():
go_version = check_output('go version'.split()).split()[2]
go_version = _go_version()
if go_version < 'go1.3':
print('runtests: skip on {}'.format(go_version), file=sys.stderr)
return
@ -115,7 +116,7 @@ def _toc():
@_target
def _gen():
go_version = check_output('go version'.split()).split()[2]
go_version = _go_version()
if go_version < 'go1.5':
print('runtests: skip on {}'.format(go_version), file=sys.stderr)
return
@ -133,26 +134,30 @@ def _run(command):
def _gfmrun_count():
with open('README.md') as infile:
with codecs.open('README.md', 'r', 'utf-8') as infile:
lines = infile.read().splitlines()
return len(filter(_is_go_runnable, lines))
return len(list(filter(_is_go_runnable, lines)))
def _is_go_runnable(line):
return line.startswith('package main')
def _go_version():
return check_output('go version'.split()).decode('utf-8').split()[2]
def _combine_coverprofiles(coverprofiles):
combined = tempfile.NamedTemporaryFile(
suffix='.coverprofile', delete=False
)
combined.write('mode: set\n')
combined.write(b'mode: set\n')
for coverprofile in coverprofiles:
with open(coverprofile, 'r') as infile:
with codecs.open(coverprofile, 'r', 'utf-8') as infile:
for line in infile.readlines():
if not line.startswith('mode: '):
combined.write(line)
combined.write(line.encode('utf-8'))
combined.flush()
name = combined.name

Loading…
Cancel
Save