Resolved compile-time errors since merging from v1
This commit is contained in:
parent
a61867e5e6
commit
47a412375f
380
app_test.go
380
app_test.go
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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")
|
||||
},
|
||||
}
|
||||
app.Action = func(ctx *Context) error {
|
||||
return fmt.Errorf("should not get here")
|
||||
}
|
||||
err := app.Run([]string{"", "--test-completion", "--" + BashCompletionFlag.GetName()})
|
||||
err := app.Run([]string{"", "--test-completion", "--" + genCompName()})
|
||||
if err != nil {
|
||||
t.Errorf("app should not return an error: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHandleActionActuallyWorksWithActions(t *testing.T) {
|
||||
var f ActionFunc
|
||||
called := false
|
||||
f = func(c *Context) error {
|
||||
called = true
|
||||
return nil
|
||||
}
|
||||
|
||||
err := HandleAction(f, nil)
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Should not have errored: %v", err)
|
||||
}
|
||||
|
||||
if !called {
|
||||
t.Errorf("Function was not called")
|
||||
}
|
||||
}
|
||||
|
@ -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")
|
||||
}
|
||||
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
|
||||
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())
|
||||
}
|
||||
|
113
flag.go
113
flag.go
@ -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 {
|
||||
|
66
flag_test.go
66
flag_test.go
@ -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
|
||||
},
|
||||
|
24
help.go
24
help.go
@ -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
|
||||
}
|
||||
|
||||
|
10
help_test.go
10
help_test.go
@ -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 {
|
||||
|
25
runtests
25
runtests
@ -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…
Reference in New Issue
Block a user