Merge branch 'v2' into v2-completion
This commit is contained in:
commit
6aa0ab6903
25
.travis.yml
25
.travis.yml
@ -7,11 +7,11 @@ cache:
|
|||||||
- node_modules
|
- node_modules
|
||||||
|
|
||||||
go:
|
go:
|
||||||
- 1.2.2
|
- 1.2.x
|
||||||
- 1.3.3
|
- 1.3.x
|
||||||
- 1.4
|
- 1.4.2
|
||||||
- 1.5.4
|
- 1.5.x
|
||||||
- 1.6.2
|
- 1.6.x
|
||||||
- master
|
- master
|
||||||
|
|
||||||
env: pip_install="pip install --user"
|
env: pip_install="pip install --user"
|
||||||
@ -20,17 +20,12 @@ matrix:
|
|||||||
allow_failures:
|
allow_failures:
|
||||||
- go: master
|
- go: master
|
||||||
include:
|
include:
|
||||||
- go: 1.6.2
|
- go: 1.6.x
|
||||||
os: osx
|
os: osx
|
||||||
env: pip_install="sudo pip install"
|
env: pip_install="sudo pip install"
|
||||||
|
|
||||||
before_script:
|
before_script:
|
||||||
- $pip_install flake8
|
- $pip_install flake8
|
||||||
- go get github.com/urfave/gfmrun/...
|
|
||||||
- go get golang.org/x/tools/cmd/goimports || true
|
|
||||||
- if [ ! -f node_modules/.bin/markdown-toc ] ; then
|
|
||||||
npm install markdown-toc ;
|
|
||||||
fi
|
|
||||||
- mkdir -p ${GOPATH%%:*}/src/gopkg.in/urfave
|
- mkdir -p ${GOPATH%%:*}/src/gopkg.in/urfave
|
||||||
- rm -rvf ${GOPATH%%:*}/src/gopkg.in/urfave/cli.v2
|
- rm -rvf ${GOPATH%%:*}/src/gopkg.in/urfave/cli.v2
|
||||||
- rm -rvf ${GOPATH%%:*}/pkg/*/gopkg.in/urfave/cli.v2.a
|
- rm -rvf ${GOPATH%%:*}/pkg/*/gopkg.in/urfave/cli.v2.a
|
||||||
@ -38,10 +33,4 @@ before_script:
|
|||||||
|
|
||||||
script:
|
script:
|
||||||
- flake8 runtests cli-v1-to-v2 generate-flag-types
|
- flake8 runtests cli-v1-to-v2 generate-flag-types
|
||||||
- ./runtests gen
|
- make all
|
||||||
- ./runtests vet
|
|
||||||
- ./runtests test
|
|
||||||
- ./runtests gfmrun
|
|
||||||
- ./cli-v1-to-v2 --selftest
|
|
||||||
- ./runtests migrations
|
|
||||||
- ./runtests toc
|
|
||||||
|
@ -35,6 +35,8 @@
|
|||||||
## [Unreleased] - (1.x series)
|
## [Unreleased] - (1.x series)
|
||||||
### Added
|
### Added
|
||||||
- Flag type code generation via `go generate`
|
- 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
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- Raise minimum tested/supported Go version to 1.2+
|
- Raise minimum tested/supported Go version to 1.2+
|
||||||
|
37
GNUmakefile
Normal file
37
GNUmakefile
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
default: test
|
||||||
|
|
||||||
|
deps:
|
||||||
|
go get golang.org/x/tools/cmd/goimports || true
|
||||||
|
go get github.com/urfave/gfmrun/... || true
|
||||||
|
go list ./... \
|
||||||
|
| xargs go list -f '{{ join .Deps "\n" }}{{ printf "\n" }}{{ join .TestImports "\n" }}' \
|
||||||
|
| grep -v github.com/urfave/cli \
|
||||||
|
| xargs go get
|
||||||
|
@if [ ! -f node_modules/.bin/markdown-toc ]; then \
|
||||||
|
npm install markdown-toc ; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
gen: deps
|
||||||
|
./runtests gen
|
||||||
|
|
||||||
|
vet:
|
||||||
|
./runtests vet
|
||||||
|
|
||||||
|
gfmrun:
|
||||||
|
./runtests gfmrun
|
||||||
|
|
||||||
|
v1-to-v2:
|
||||||
|
./cli-v1-to-v2 --selftest
|
||||||
|
|
||||||
|
migrations:
|
||||||
|
./runtests migrations
|
||||||
|
|
||||||
|
toc:
|
||||||
|
./runtests toc
|
||||||
|
|
||||||
|
test: deps
|
||||||
|
./runtests test
|
||||||
|
|
||||||
|
all: gen vet test gfmrun v1-to-v2 migrations toc
|
||||||
|
|
||||||
|
.PHONY: default gen vet test gfmrun migrations toc v1-to-v2 deps all
|
59
README.md
59
README.md
@ -31,7 +31,8 @@ applications in an expressive way.
|
|||||||
+ [Placeholder Values](#placeholder-values)
|
+ [Placeholder Values](#placeholder-values)
|
||||||
+ [Alternate Names](#alternate-names)
|
+ [Alternate Names](#alternate-names)
|
||||||
+ [Values from the Environment](#values-from-the-environment)
|
+ [Values from the Environment](#values-from-the-environment)
|
||||||
+ [Values from alternate input sources (YAML and others)](#values-from-alternate-input-sources-yaml-and-others)
|
+ [Values from alternate input sources (YAML, TOML, and others)](#values-from-alternate-input-sources-yaml-toml-and-others)
|
||||||
|
+ [Default Values for help output](#default-values-for-help-output)
|
||||||
* [Subcommands](#subcommands)
|
* [Subcommands](#subcommands)
|
||||||
* [Subcommands categories](#subcommands-categories)
|
* [Subcommands categories](#subcommands-categories)
|
||||||
* [Exit code](#exit-code)
|
* [Exit code](#exit-code)
|
||||||
@ -520,10 +521,14 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Values from alternate input sources (YAML and others)
|
#### Values from alternate input sources (YAML, TOML, and others)
|
||||||
|
|
||||||
There is a separate package altsrc that adds support for getting flag values
|
There is a separate package altsrc that adds support for getting flag values
|
||||||
from other input sources like YAML.
|
from other file input sources.
|
||||||
|
|
||||||
|
Currently supported input source formats:
|
||||||
|
* YAML
|
||||||
|
* TOML
|
||||||
|
|
||||||
In order to get values for a flag from an alternate input source the following
|
In order to get values for a flag from an alternate input source the following
|
||||||
code would be added to wrap an existing cli.Flag like below:
|
code would be added to wrap an existing cli.Flag like below:
|
||||||
@ -545,9 +550,9 @@ the yaml input source for any flags that are defined on that command. As a note
|
|||||||
the "load" flag used would also have to be defined on the command flags in order
|
the "load" flag used would also have to be defined on the command flags in order
|
||||||
for this code snipped to work.
|
for this code snipped to work.
|
||||||
|
|
||||||
Currently only YAML and JSON files are supported but developers can add support
|
Currently only the aboved specified formats are supported but developers can
|
||||||
for other input sources by implementing the altsrc.InputSourceContext for their
|
add support for other input sources by implementing the
|
||||||
given sources.
|
altsrc.InputSourceContext for their given sources.
|
||||||
|
|
||||||
Here is a more complete sample of a command using YAML support:
|
Here is a more complete sample of a command using YAML support:
|
||||||
|
|
||||||
@ -585,6 +590,48 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Default Values for help output
|
||||||
|
|
||||||
|
Sometimes it's useful to specify a flag's default help-text value within the flag declaration. This can be useful if the default value for a flag is a computed value. The default value can be set via the `DefaultText` struct field.
|
||||||
|
|
||||||
|
For example this:
|
||||||
|
|
||||||
|
<!-- {
|
||||||
|
"args": ["--help"],
|
||||||
|
"output": "--port value"
|
||||||
|
} -->
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"gopkg.in/urfave/cli.v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
app := &cli.App{
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
&cli.IntFlag{
|
||||||
|
Name: "port",
|
||||||
|
Usage: "Use a randomized port",
|
||||||
|
Value: 0,
|
||||||
|
DefaultText: "random",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
app.Run(os.Args)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Will result in help output like:
|
||||||
|
|
||||||
|
```
|
||||||
|
--port value Use a randomized port (default: random)
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
### Subcommands
|
### Subcommands
|
||||||
|
|
||||||
Subcommands can be defined for a more git-like command line app.
|
Subcommands can be defined for a more git-like command line app.
|
||||||
|
@ -5,7 +5,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
"gopkg.in/urfave/cli.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// FlagInputSourceExtension is an extension interface of cli.Flag that
|
// FlagInputSourceExtension is an extension interface of cli.Flag that
|
||||||
|
@ -3,7 +3,7 @@ package altsrc
|
|||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
"gopkg.in/urfave/cli.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// WARNING: This file is generated!
|
// WARNING: This file is generated!
|
||||||
|
@ -8,7 +8,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
"gopkg.in/urfave/cli.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
type testApplyInputSource struct {
|
type testApplyInputSource struct {
|
||||||
|
@ -3,7 +3,7 @@ package altsrc
|
|||||||
import (
|
import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
"gopkg.in/urfave/cli.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// InputSourceContext is an interface used to allow
|
// InputSourceContext is an interface used to allow
|
||||||
|
@ -6,7 +6,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
"gopkg.in/urfave/cli.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -8,7 +8,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
"gopkg.in/urfave/cli.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewJSONSourceFromFlagFunc returns a func that takes a cli.Context
|
// NewJSONSourceFromFlagFunc returns a func that takes a cli.Context
|
||||||
|
@ -6,7 +6,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
"gopkg.in/urfave/cli.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MapInputSource implements InputSourceContext to return
|
// MapInputSource implements InputSourceContext to return
|
||||||
|
310
altsrc/toml_command_test.go
Normal file
310
altsrc/toml_command_test.go
Normal file
@ -0,0 +1,310 @@
|
|||||||
|
// Disabling building of toml support in cases where golang is 1.0 or 1.1
|
||||||
|
// as the encoding library is not implemented or supported.
|
||||||
|
|
||||||
|
// +build go1.2
|
||||||
|
|
||||||
|
package altsrc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"gopkg.in/urfave/cli.v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestCommandTomFileTest(t *testing.T) {
|
||||||
|
app := (&cli.App{})
|
||||||
|
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.App{})
|
||||||
|
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", EnvVars: []string{"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.App{})
|
||||||
|
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", EnvVars: []string{"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.App{})
|
||||||
|
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.App{})
|
||||||
|
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.App{})
|
||||||
|
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.App{})
|
||||||
|
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.App{})
|
||||||
|
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, EnvVars: []string{"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.App{})
|
||||||
|
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, EnvVars: []string{"THE_TEST"}}),
|
||||||
|
&cli.StringFlag{Name: "load"}},
|
||||||
|
}
|
||||||
|
command.Before = InitInputSourceWithContext(command.Flags, NewTomlSourceFromFlagFunc("load"))
|
||||||
|
err := command.Run(c)
|
||||||
|
|
||||||
|
expect(t, err, nil)
|
||||||
|
}
|
113
altsrc/toml_file_loader.go
Normal file
113
altsrc/toml_file_loader.go
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
// Disabling building of toml support in cases where golang is 1.0 or 1.1
|
||||||
|
// as the encoding library is not implemented or supported.
|
||||||
|
|
||||||
|
// +build go1.2
|
||||||
|
|
||||||
|
package altsrc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
|
||||||
|
"github.com/BurntSushi/toml"
|
||||||
|
"gopkg.in/urfave/cli.v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
@ -11,7 +11,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
"gopkg.in/urfave/cli.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestCommandYamlFileTest(t *testing.T) {
|
func TestCommandYamlFileTest(t *testing.T) {
|
||||||
|
@ -12,7 +12,7 @@ import (
|
|||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
"gopkg.in/urfave/cli.v2"
|
||||||
|
|
||||||
"gopkg.in/yaml.v2"
|
"gopkg.in/yaml.v2"
|
||||||
)
|
)
|
||||||
|
13
app_test.go
13
app_test.go
@ -13,6 +13,19 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
lastExitCode = 0
|
||||||
|
fakeOsExiter = func(rc int) {
|
||||||
|
lastExitCode = rc
|
||||||
|
}
|
||||||
|
fakeErrWriter = &bytes.Buffer{}
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
OsExiter = fakeOsExiter
|
||||||
|
ErrWriter = fakeErrWriter
|
||||||
|
}
|
||||||
|
|
||||||
type opCounts struct {
|
type opCounts struct {
|
||||||
Total, ShellComplete, OnUsageError, Before, CommandNotFound, Action, After, SubCommand int
|
Total, ShellComplete, OnUsageError, Before, CommandNotFound, Action, After, SubCommand int
|
||||||
}
|
}
|
||||||
|
@ -98,5 +98,11 @@ func HandleExitCoder(err error) {
|
|||||||
for _, merr := range multiErr.Errors() {
|
for _, merr := range multiErr.Errors() {
|
||||||
HandleExitCoder(merr)
|
HandleExitCoder(merr)
|
||||||
}
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err.Error() != "" {
|
||||||
|
fmt.Fprintln(ErrWriter, err)
|
||||||
|
}
|
||||||
|
OsExiter(1)
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package cli
|
package cli
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"os"
|
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -15,7 +15,7 @@ func TestHandleExitCoder_nil(t *testing.T) {
|
|||||||
called = true
|
called = true
|
||||||
}
|
}
|
||||||
|
|
||||||
defer func() { OsExiter = os.Exit }()
|
defer func() { OsExiter = fakeOsExiter }()
|
||||||
|
|
||||||
HandleExitCoder(nil)
|
HandleExitCoder(nil)
|
||||||
|
|
||||||
@ -32,7 +32,7 @@ func TestHandleExitCoder_ExitCoder(t *testing.T) {
|
|||||||
called = true
|
called = true
|
||||||
}
|
}
|
||||||
|
|
||||||
defer func() { OsExiter = os.Exit }()
|
defer func() { OsExiter = fakeOsExiter }()
|
||||||
|
|
||||||
HandleExitCoder(Exit("galactic perimeter breach", 9))
|
HandleExitCoder(Exit("galactic perimeter breach", 9))
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ func TestHandleExitCoder_MultiErrorWithExitCoder(t *testing.T) {
|
|||||||
called = true
|
called = true
|
||||||
}
|
}
|
||||||
|
|
||||||
defer func() { OsExiter = os.Exit }()
|
defer func() { OsExiter = fakeOsExiter }()
|
||||||
|
|
||||||
exitErr := Exit("galactic perimeter breach", 9)
|
exitErr := Exit("galactic perimeter breach", 9)
|
||||||
err := newMultiError(errors.New("wowsa"), errors.New("egad"), exitErr)
|
err := newMultiError(errors.New("wowsa"), errors.New("egad"), exitErr)
|
||||||
@ -58,3 +58,49 @@ func TestHandleExitCoder_MultiErrorWithExitCoder(t *testing.T) {
|
|||||||
expect(t, exitCode, 9)
|
expect(t, exitCode, 9)
|
||||||
expect(t, called, true)
|
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(), "")
|
||||||
|
}
|
||||||
|
7
flag.go
7
flag.go
@ -736,7 +736,6 @@ func stringifyFlag(f Flag) string {
|
|||||||
needsPlaceholder := false
|
needsPlaceholder := false
|
||||||
defaultValueString := ""
|
defaultValueString := ""
|
||||||
val := fv.FieldByName("Value")
|
val := fv.FieldByName("Value")
|
||||||
|
|
||||||
if val.IsValid() {
|
if val.IsValid() {
|
||||||
needsPlaceholder = val.Kind() != reflect.Bool
|
needsPlaceholder = val.Kind() != reflect.Bool
|
||||||
defaultValueString = fmt.Sprintf(" (default: %v)", val.Interface())
|
defaultValueString = fmt.Sprintf(" (default: %v)", val.Interface())
|
||||||
@ -746,6 +745,12 @@ func stringifyFlag(f Flag) string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
helpText := fv.FieldByName("DefaultText")
|
||||||
|
if helpText.IsValid() && helpText.String() != "" {
|
||||||
|
needsPlaceholder = val.Kind() != reflect.Bool
|
||||||
|
defaultValueString = fmt.Sprintf(" (default: %s)", helpText.String())
|
||||||
|
}
|
||||||
|
|
||||||
if defaultValueString == " (default: )" {
|
if defaultValueString == " (default: )" {
|
||||||
defaultValueString = ""
|
defaultValueString = ""
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@ type BoolFlag struct {
|
|||||||
EnvVars []string
|
EnvVars []string
|
||||||
Hidden bool
|
Hidden bool
|
||||||
Value bool
|
Value bool
|
||||||
|
DefaultText string
|
||||||
Destination *bool
|
Destination *bool
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,6 +60,7 @@ type DurationFlag struct {
|
|||||||
EnvVars []string
|
EnvVars []string
|
||||||
Hidden bool
|
Hidden bool
|
||||||
Value time.Duration
|
Value time.Duration
|
||||||
|
DefaultText string
|
||||||
Destination *time.Duration
|
Destination *time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,6 +104,7 @@ type Float64Flag struct {
|
|||||||
EnvVars []string
|
EnvVars []string
|
||||||
Hidden bool
|
Hidden bool
|
||||||
Value float64
|
Value float64
|
||||||
|
DefaultText string
|
||||||
Destination *float64
|
Destination *float64
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,6 +148,7 @@ type GenericFlag struct {
|
|||||||
EnvVars []string
|
EnvVars []string
|
||||||
Hidden bool
|
Hidden bool
|
||||||
Value Generic
|
Value Generic
|
||||||
|
DefaultText string
|
||||||
}
|
}
|
||||||
|
|
||||||
// String returns a readable representation of this value
|
// String returns a readable representation of this value
|
||||||
@ -187,6 +191,7 @@ type Int64Flag struct {
|
|||||||
EnvVars []string
|
EnvVars []string
|
||||||
Hidden bool
|
Hidden bool
|
||||||
Value int64
|
Value int64
|
||||||
|
DefaultText string
|
||||||
Destination *int64
|
Destination *int64
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -230,6 +235,7 @@ type IntFlag struct {
|
|||||||
EnvVars []string
|
EnvVars []string
|
||||||
Hidden bool
|
Hidden bool
|
||||||
Value int
|
Value int
|
||||||
|
DefaultText string
|
||||||
Destination *int
|
Destination *int
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -273,6 +279,7 @@ type IntSliceFlag struct {
|
|||||||
EnvVars []string
|
EnvVars []string
|
||||||
Hidden bool
|
Hidden bool
|
||||||
Value *IntSlice
|
Value *IntSlice
|
||||||
|
DefaultText string
|
||||||
}
|
}
|
||||||
|
|
||||||
// String returns a readable representation of this value
|
// String returns a readable representation of this value
|
||||||
@ -315,6 +322,7 @@ type Int64SliceFlag struct {
|
|||||||
EnvVars []string
|
EnvVars []string
|
||||||
Hidden bool
|
Hidden bool
|
||||||
Value *Int64Slice
|
Value *Int64Slice
|
||||||
|
DefaultText string
|
||||||
}
|
}
|
||||||
|
|
||||||
// String returns a readable representation of this value
|
// String returns a readable representation of this value
|
||||||
@ -357,6 +365,7 @@ type Float64SliceFlag struct {
|
|||||||
EnvVars []string
|
EnvVars []string
|
||||||
Hidden bool
|
Hidden bool
|
||||||
Value *Float64Slice
|
Value *Float64Slice
|
||||||
|
DefaultText string
|
||||||
}
|
}
|
||||||
|
|
||||||
// String returns a readable representation of this value
|
// String returns a readable representation of this value
|
||||||
@ -399,6 +408,7 @@ type StringFlag struct {
|
|||||||
EnvVars []string
|
EnvVars []string
|
||||||
Hidden bool
|
Hidden bool
|
||||||
Value string
|
Value string
|
||||||
|
DefaultText string
|
||||||
Destination *string
|
Destination *string
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -442,6 +452,7 @@ type StringSliceFlag struct {
|
|||||||
EnvVars []string
|
EnvVars []string
|
||||||
Hidden bool
|
Hidden bool
|
||||||
Value *StringSlice
|
Value *StringSlice
|
||||||
|
DefaultText string
|
||||||
}
|
}
|
||||||
|
|
||||||
// String returns a readable representation of this value
|
// String returns a readable representation of this value
|
||||||
@ -484,6 +495,7 @@ type Uint64Flag struct {
|
|||||||
EnvVars []string
|
EnvVars []string
|
||||||
Hidden bool
|
Hidden bool
|
||||||
Value uint64
|
Value uint64
|
||||||
|
DefaultText string
|
||||||
Destination *uint64
|
Destination *uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -527,6 +539,7 @@ type UintFlag struct {
|
|||||||
EnvVars []string
|
EnvVars []string
|
||||||
Hidden bool
|
Hidden bool
|
||||||
Value uint
|
Value uint
|
||||||
|
DefaultText string
|
||||||
Destination *uint
|
Destination *uint
|
||||||
}
|
}
|
||||||
|
|
||||||
|
15
flag_test.go
15
flag_test.go
@ -67,6 +67,16 @@ func TestStringFlagHelpOutput(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestStringFlagDefaultText(t *testing.T) {
|
||||||
|
flag := &StringFlag{Name: "foo", Aliases: nil, Usage: "amount of `foo` requested", Value: "none", DefaultText: "all of it"}
|
||||||
|
expected := "--foo foo\tamount of foo requested (default: all of it)"
|
||||||
|
output := flag.String()
|
||||||
|
|
||||||
|
if output != expected {
|
||||||
|
t.Errorf("%q does not match %q", output, expected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestStringFlagWithEnvVarHelpOutput(t *testing.T) {
|
func TestStringFlagWithEnvVarHelpOutput(t *testing.T) {
|
||||||
os.Clearenv()
|
os.Clearenv()
|
||||||
os.Setenv("APP_FOO", "derp")
|
os.Setenv("APP_FOO", "derp")
|
||||||
@ -482,7 +492,6 @@ func TestFloat64FlagApply_SetsAllNames(t *testing.T) {
|
|||||||
expect(t, v, float64(43.33333))
|
expect(t, v, float64(43.33333))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var float64SliceFlagTests = []struct {
|
var float64SliceFlagTests = []struct {
|
||||||
name string
|
name string
|
||||||
aliases []string
|
aliases []string
|
||||||
@ -523,8 +532,6 @@ func TestFloat64SliceFlagWithEnvVarHelpOutput(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var genericFlagTests = []struct {
|
var genericFlagTests = []struct {
|
||||||
name string
|
name string
|
||||||
value Generic
|
value Generic
|
||||||
@ -1100,7 +1107,6 @@ func TestParseMultiFloat64FromEnvCascade(t *testing.T) {
|
|||||||
a.Run([]string{"run"})
|
a.Run([]string{"run"})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func TestParseMultiFloat64SliceFromEnv(t *testing.T) {
|
func TestParseMultiFloat64SliceFromEnv(t *testing.T) {
|
||||||
os.Clearenv()
|
os.Clearenv()
|
||||||
os.Setenv("APP_INTERVALS", "0.1,-10.5")
|
os.Setenv("APP_INTERVALS", "0.1,-10.5")
|
||||||
@ -1141,7 +1147,6 @@ func TestParseMultiFloat64SliceFromEnvCascade(t *testing.T) {
|
|||||||
}).Run([]string{"run"})
|
}).Run([]string{"run"})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func TestParseMultiBool(t *testing.T) {
|
func TestParseMultiBool(t *testing.T) {
|
||||||
a := App{
|
a := App{
|
||||||
Flags: []Flag{
|
Flags: []Flag{
|
||||||
|
@ -145,6 +145,7 @@ def _write_cli_flag_types(outfile, types):
|
|||||||
EnvVars []string
|
EnvVars []string
|
||||||
Hidden bool
|
Hidden bool
|
||||||
Value {type}
|
Value {type}
|
||||||
|
DefaultText string
|
||||||
""".format(**typedef))
|
""".format(**typedef))
|
||||||
|
|
||||||
if typedef['dest']:
|
if typedef['dest']:
|
||||||
@ -193,6 +194,8 @@ def _write_altsrc_flag_types(outfile, types):
|
|||||||
_fwrite(outfile, """\
|
_fwrite(outfile, """\
|
||||||
package altsrc
|
package altsrc
|
||||||
|
|
||||||
|
import "gopkg.in/urfave/cli.v2"
|
||||||
|
|
||||||
// WARNING: This file is generated!
|
// WARNING: This file is generated!
|
||||||
|
|
||||||
""")
|
""")
|
||||||
|
9
runtests
9
runtests
@ -61,6 +61,10 @@ def _test():
|
|||||||
|
|
||||||
@_target
|
@_target
|
||||||
def _gfmrun():
|
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'])
|
_run(['gfmrun', '-c', str(_gfmrun_count()), '-s', 'README.md'])
|
||||||
|
|
||||||
|
|
||||||
@ -71,6 +75,11 @@ def _vet():
|
|||||||
|
|
||||||
@_target
|
@_target
|
||||||
def _migrations():
|
def _migrations():
|
||||||
|
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
|
||||||
|
|
||||||
migration_script = os.path.abspath(
|
migration_script = os.path.abspath(
|
||||||
os.environ.get('V1TOV2', './cli-v1-to-v2')
|
os.environ.get('V1TOV2', './cli-v1-to-v2')
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user