Merge branch 'master' into ally_fix_default_val
This commit is contained in:
commit
ab52d6f3a9
1
.github/stale.yml
vendored
1
.github/stale.yml
vendored
@ -14,6 +14,7 @@ onlyLabels: []
|
|||||||
exemptLabels:
|
exemptLabels:
|
||||||
- pinned
|
- pinned
|
||||||
- security
|
- security
|
||||||
|
- "help wanted"
|
||||||
- "kind/maintenance"
|
- "kind/maintenance"
|
||||||
|
|
||||||
# Set to true to ignore issues in a project (defaults to false)
|
# Set to true to ignore issues in a project (defaults to false)
|
||||||
|
10
.github/workflows/cli.yml
vendored
10
.github/workflows/cli.yml
vendored
@ -15,7 +15,7 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||||
go: [1.13, 1.14, 1.15]
|
go: [1.14, 1.15, 1.16]
|
||||||
name: ${{ matrix.os }} @ Go ${{ matrix.go }}
|
name: ${{ matrix.os }} @ Go ${{ matrix.go }}
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
steps:
|
steps:
|
||||||
@ -38,7 +38,7 @@ jobs:
|
|||||||
ref: ${{ github.ref }}
|
ref: ${{ github.ref }}
|
||||||
|
|
||||||
- name: GOFMT Check
|
- name: GOFMT Check
|
||||||
if: matrix.go == 1.15 && matrix.os == 'ubuntu-latest'
|
if: matrix.go == 1.16 && matrix.os == 'ubuntu-latest'
|
||||||
run: test -z $(gofmt -l .)
|
run: test -z $(gofmt -l .)
|
||||||
|
|
||||||
- name: vet
|
- name: vet
|
||||||
@ -51,19 +51,19 @@ jobs:
|
|||||||
run: go run internal/build/build.go check-binary-size
|
run: go run internal/build/build.go check-binary-size
|
||||||
|
|
||||||
- name: Upload coverage to Codecov
|
- name: Upload coverage to Codecov
|
||||||
if: success() && matrix.go == 1.14 && matrix.os == 'ubuntu-latest'
|
if: success() && matrix.go == 1.16 && matrix.os == 'ubuntu-latest'
|
||||||
uses: codecov/codecov-action@v1
|
uses: codecov/codecov-action@v1
|
||||||
with:
|
with:
|
||||||
token: 0a8cc73b-bb7c-480b-8626-38a461643761
|
|
||||||
fail_ci_if_error: true
|
fail_ci_if_error: true
|
||||||
|
|
||||||
test-docs:
|
test-docs:
|
||||||
name: test-docs
|
name: test-docs
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Set up Go 1.15
|
- name: Set up Go
|
||||||
uses: actions/setup-go@v1
|
uses: actions/setup-go@v1
|
||||||
with:
|
with:
|
||||||
|
# Currently fails on 1.16
|
||||||
go-version: 1.15
|
go-version: 1.15
|
||||||
|
|
||||||
- name: Use Node.js 12.x
|
- name: Use Node.js 12.x
|
||||||
|
4
app.go
4
app.go
@ -278,7 +278,7 @@ func (a *App) RunContext(ctx context.Context, arguments []string) (err error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
cerr := checkRequiredFlags(a.Flags, context)
|
cerr := context.checkRequiredFlags(a.Flags)
|
||||||
if cerr != nil {
|
if cerr != nil {
|
||||||
_ = ShowAppHelp(context)
|
_ = ShowAppHelp(context)
|
||||||
return cerr
|
return cerr
|
||||||
@ -397,7 +397,7 @@ func (a *App) RunAsSubcommand(ctx *Context) (err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cerr := checkRequiredFlags(a.Flags, context)
|
cerr := context.checkRequiredFlags(a.Flags)
|
||||||
if cerr != nil {
|
if cerr != nil {
|
||||||
_ = ShowSubcommandHelp(context)
|
_ = ShowSubcommandHelp(context)
|
||||||
return cerr
|
return cerr
|
||||||
|
@ -127,7 +127,7 @@ func (c *Command) Run(ctx *Context) (err error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
cerr := checkRequiredFlags(c.Flags, context)
|
cerr := context.checkRequiredFlags(c.Flags)
|
||||||
if cerr != nil {
|
if cerr != nil {
|
||||||
_ = ShowCommandHelp(context, c.Name)
|
_ = ShowCommandHelp(context, c.Name)
|
||||||
return cerr
|
return cerr
|
||||||
@ -227,6 +227,7 @@ func (c *Command) startApp(ctx *Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
app.Usage = c.Usage
|
app.Usage = c.Usage
|
||||||
|
app.UsageText = c.UsageText
|
||||||
app.Description = c.Description
|
app.Description = c.Description
|
||||||
app.ArgsUsage = c.ArgsUsage
|
app.ArgsUsage = c.ArgsUsage
|
||||||
|
|
||||||
|
116
context.go
116
context.go
@ -2,9 +2,7 @@ package cli
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -53,8 +51,7 @@ func (c *Context) Set(name, value string) error {
|
|||||||
|
|
||||||
// IsSet determines if the flag was actually set
|
// IsSet determines if the flag was actually set
|
||||||
func (c *Context) IsSet(name string) bool {
|
func (c *Context) IsSet(name string) bool {
|
||||||
if fs := lookupFlagSet(name, c); fs != nil {
|
if fs := c.lookupFlagSet(name); fs != nil {
|
||||||
if fs := lookupFlagSet(name, c); fs != nil {
|
|
||||||
isSet := false
|
isSet := false
|
||||||
fs.Visit(func(f *flag.Flag) {
|
fs.Visit(func(f *flag.Flag) {
|
||||||
if f.Name == name {
|
if f.Name == name {
|
||||||
@ -64,9 +61,8 @@ func (c *Context) IsSet(name string) bool {
|
|||||||
if isSet {
|
if isSet {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
f := lookupFlag(name, c)
|
f := c.lookupFlag(name)
|
||||||
if f == nil {
|
if f == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -108,7 +104,7 @@ func (c *Context) Lineage() []*Context {
|
|||||||
|
|
||||||
// Value returns the value of the flag corresponding to `name`
|
// Value returns the value of the flag corresponding to `name`
|
||||||
func (c *Context) Value(name string) interface{} {
|
func (c *Context) Value(name string) interface{} {
|
||||||
if fs := lookupFlagSet(name, c); fs != nil {
|
if fs := c.lookupFlagSet(name); fs != nil {
|
||||||
return fs.Lookup(name).Value.(flag.Getter).Get()
|
return fs.Lookup(name).Value.(flag.Getter).Get()
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -125,7 +121,7 @@ func (c *Context) NArg() int {
|
|||||||
return c.Args().Len()
|
return c.Args().Len()
|
||||||
}
|
}
|
||||||
|
|
||||||
func lookupFlag(name string, ctx *Context) Flag {
|
func (ctx *Context) lookupFlag(name string) Flag {
|
||||||
for _, c := range ctx.Lineage() {
|
for _, c := range ctx.Lineage() {
|
||||||
if c.Command == nil {
|
if c.Command == nil {
|
||||||
continue
|
continue
|
||||||
@ -153,7 +149,7 @@ func lookupFlag(name string, ctx *Context) Flag {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func lookupFlagSet(name string, ctx *Context) *flag.FlagSet {
|
func (ctx *Context) lookupFlagSet(name string) *flag.FlagSet {
|
||||||
for _, c := range ctx.Lineage() {
|
for _, c := range ctx.Lineage() {
|
||||||
if f := c.flagSet.Lookup(name); f != nil {
|
if f := c.flagSet.Lookup(name); f != nil {
|
||||||
return c.flagSet
|
return c.flagSet
|
||||||
@ -163,89 +159,7 @@ func lookupFlagSet(name string, ctx *Context) *flag.FlagSet {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func copyFlag(name string, ff *flag.Flag, set *flag.FlagSet) {
|
func (context *Context) checkRequiredFlags(flags []Flag) requiredFlagsErr {
|
||||||
switch ff.Value.(type) {
|
|
||||||
case Serializer:
|
|
||||||
_ = set.Set(name, ff.Value.(Serializer).Serialize())
|
|
||||||
default:
|
|
||||||
_ = set.Set(name, ff.Value.String())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func normalizeFlags(flags []Flag, set *flag.FlagSet) error {
|
|
||||||
visited := make(map[string]bool)
|
|
||||||
set.Visit(func(f *flag.Flag) {
|
|
||||||
visited[f.Name] = true
|
|
||||||
})
|
|
||||||
for _, f := range flags {
|
|
||||||
parts := f.Names()
|
|
||||||
if len(parts) == 1 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
var ff *flag.Flag
|
|
||||||
for _, name := range parts {
|
|
||||||
name = strings.Trim(name, " ")
|
|
||||||
if visited[name] {
|
|
||||||
if ff != nil {
|
|
||||||
return errors.New("Cannot use two forms of the same flag: " + name + " " + ff.Name)
|
|
||||||
}
|
|
||||||
ff = set.Lookup(name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ff == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for _, name := range parts {
|
|
||||||
name = strings.Trim(name, " ")
|
|
||||||
if !visited[name] {
|
|
||||||
copyFlag(name, ff, set)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func makeFlagNameVisitor(names *[]string) func(*flag.Flag) {
|
|
||||||
return func(f *flag.Flag) {
|
|
||||||
nameParts := strings.Split(f.Name, ",")
|
|
||||||
name := strings.TrimSpace(nameParts[0])
|
|
||||||
|
|
||||||
for _, part := range nameParts {
|
|
||||||
part = strings.TrimSpace(part)
|
|
||||||
if len(part) > len(name) {
|
|
||||||
name = part
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if name != "" {
|
|
||||||
*names = append(*names, name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type requiredFlagsErr interface {
|
|
||||||
error
|
|
||||||
getMissingFlags() []string
|
|
||||||
}
|
|
||||||
|
|
||||||
type errRequiredFlags struct {
|
|
||||||
missingFlags []string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *errRequiredFlags) Error() string {
|
|
||||||
numberOfMissingFlags := len(e.missingFlags)
|
|
||||||
if numberOfMissingFlags == 1 {
|
|
||||||
return fmt.Sprintf("Required flag %q not set", e.missingFlags[0])
|
|
||||||
}
|
|
||||||
joinedMissingFlags := strings.Join(e.missingFlags, ", ")
|
|
||||||
return fmt.Sprintf("Required flags %q not set", joinedMissingFlags)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *errRequiredFlags) getMissingFlags() []string {
|
|
||||||
return e.missingFlags
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkRequiredFlags(flags []Flag, context *Context) requiredFlagsErr {
|
|
||||||
var missingFlags []string
|
var missingFlags []string
|
||||||
for _, f := range flags {
|
for _, f := range flags {
|
||||||
if rf, ok := f.(RequiredFlag); ok && rf.IsRequired() {
|
if rf, ok := f.(RequiredFlag); ok && rf.IsRequired() {
|
||||||
@ -274,3 +188,21 @@ func checkRequiredFlags(flags []Flag, context *Context) requiredFlagsErr {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func makeFlagNameVisitor(names *[]string) func(*flag.Flag) {
|
||||||
|
return func(f *flag.Flag) {
|
||||||
|
nameParts := strings.Split(f.Name, ",")
|
||||||
|
name := strings.TrimSpace(nameParts[0])
|
||||||
|
|
||||||
|
for _, part := range nameParts {
|
||||||
|
part = strings.TrimSpace(part)
|
||||||
|
if len(part) > len(name) {
|
||||||
|
name = part
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if name != "" {
|
||||||
|
*names = append(*names, name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -316,13 +316,13 @@ func TestContext_lookupFlagSet(t *testing.T) {
|
|||||||
_ = set.Parse([]string{"--local-flag"})
|
_ = set.Parse([]string{"--local-flag"})
|
||||||
_ = parentSet.Parse([]string{"--top-flag"})
|
_ = parentSet.Parse([]string{"--top-flag"})
|
||||||
|
|
||||||
fs := lookupFlagSet("top-flag", ctx)
|
fs := ctx.lookupFlagSet("top-flag")
|
||||||
expect(t, fs, parentCtx.flagSet)
|
expect(t, fs, parentCtx.flagSet)
|
||||||
|
|
||||||
fs = lookupFlagSet("local-flag", ctx)
|
fs = ctx.lookupFlagSet("local-flag")
|
||||||
expect(t, fs, ctx.flagSet)
|
expect(t, fs, ctx.flagSet)
|
||||||
|
|
||||||
if fs := lookupFlagSet("frob", ctx); fs != nil {
|
if fs := ctx.lookupFlagSet("frob"); fs != nil {
|
||||||
t.Fail()
|
t.Fail()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -576,7 +576,7 @@ func TestCheckRequiredFlags(t *testing.T) {
|
|||||||
ctx.Command.Flags = test.flags
|
ctx.Command.Flags = test.flags
|
||||||
|
|
||||||
// logic under test
|
// logic under test
|
||||||
err := checkRequiredFlags(test.flags, ctx)
|
err := ctx.checkRequiredFlags(test.flags)
|
||||||
|
|
||||||
// assertions
|
// assertions
|
||||||
if test.expectedAnError && err == nil {
|
if test.expectedAnError && err == nil {
|
||||||
|
22
errors.go
22
errors.go
@ -47,6 +47,28 @@ func (m *multiError) Errors() []error {
|
|||||||
return errs
|
return errs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type requiredFlagsErr interface {
|
||||||
|
error
|
||||||
|
getMissingFlags() []string
|
||||||
|
}
|
||||||
|
|
||||||
|
type errRequiredFlags struct {
|
||||||
|
missingFlags []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *errRequiredFlags) Error() string {
|
||||||
|
numberOfMissingFlags := len(e.missingFlags)
|
||||||
|
if numberOfMissingFlags == 1 {
|
||||||
|
return fmt.Sprintf("Required flag %q not set", e.missingFlags[0])
|
||||||
|
}
|
||||||
|
joinedMissingFlags := strings.Join(e.missingFlags, ", ")
|
||||||
|
return fmt.Sprintf("Required flags %q not set", joinedMissingFlags)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *errRequiredFlags) getMissingFlags() []string {
|
||||||
|
return e.missingFlags
|
||||||
|
}
|
||||||
|
|
||||||
// ErrorFormatter is the interface that will suitably format the error output
|
// ErrorFormatter is the interface that will suitably format the error output
|
||||||
type ErrorFormatter interface {
|
type ErrorFormatter interface {
|
||||||
Format(s fmt.State, verb rune)
|
Format(s fmt.State, verb rune)
|
||||||
|
43
flag.go
43
flag.go
@ -1,6 +1,7 @@
|
|||||||
package cli
|
package cli
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
@ -130,6 +131,48 @@ func flagSet(name string, flags []Flag) (*flag.FlagSet, error) {
|
|||||||
return set, nil
|
return set, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func copyFlag(name string, ff *flag.Flag, set *flag.FlagSet) {
|
||||||
|
switch ff.Value.(type) {
|
||||||
|
case Serializer:
|
||||||
|
_ = set.Set(name, ff.Value.(Serializer).Serialize())
|
||||||
|
default:
|
||||||
|
_ = set.Set(name, ff.Value.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func normalizeFlags(flags []Flag, set *flag.FlagSet) error {
|
||||||
|
visited := make(map[string]bool)
|
||||||
|
set.Visit(func(f *flag.Flag) {
|
||||||
|
visited[f.Name] = true
|
||||||
|
})
|
||||||
|
for _, f := range flags {
|
||||||
|
parts := f.Names()
|
||||||
|
if len(parts) == 1 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
var ff *flag.Flag
|
||||||
|
for _, name := range parts {
|
||||||
|
name = strings.Trim(name, " ")
|
||||||
|
if visited[name] {
|
||||||
|
if ff != nil {
|
||||||
|
return errors.New("Cannot use two forms of the same flag: " + name + " " + ff.Name)
|
||||||
|
}
|
||||||
|
ff = set.Lookup(name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ff == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for _, name := range parts {
|
||||||
|
name = strings.Trim(name, " ")
|
||||||
|
if !visited[name] {
|
||||||
|
copyFlag(name, ff, set)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func visibleFlags(fl []Flag) []Flag {
|
func visibleFlags(fl []Flag) []Flag {
|
||||||
var visible []Flag
|
var visible []Flag
|
||||||
for _, f := range fl {
|
for _, f := range fl {
|
||||||
|
@ -87,7 +87,7 @@ func (f *BoolFlag) Apply(set *flag.FlagSet) error {
|
|||||||
// Bool looks up the value of a local BoolFlag, returns
|
// Bool looks up the value of a local BoolFlag, returns
|
||||||
// false if not found
|
// false if not found
|
||||||
func (c *Context) Bool(name string) bool {
|
func (c *Context) Bool(name string) bool {
|
||||||
if fs := lookupFlagSet(name, c); fs != nil {
|
if fs := c.lookupFlagSet(name); fs != nil {
|
||||||
return lookupBool(name, fs)
|
return lookupBool(name, fs)
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
@ -86,7 +86,7 @@ func (f *DurationFlag) Apply(set *flag.FlagSet) error {
|
|||||||
// Duration looks up the value of a local DurationFlag, returns
|
// Duration looks up the value of a local DurationFlag, returns
|
||||||
// 0 if not found
|
// 0 if not found
|
||||||
func (c *Context) Duration(name string) time.Duration {
|
func (c *Context) Duration(name string) time.Duration {
|
||||||
if fs := lookupFlagSet(name, c); fs != nil {
|
if fs := c.lookupFlagSet(name); fs != nil {
|
||||||
return lookupDuration(name, fs)
|
return lookupDuration(name, fs)
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
|
@ -87,7 +87,7 @@ func (f *Float64Flag) Apply(set *flag.FlagSet) error {
|
|||||||
// Float64 looks up the value of a local Float64Flag, returns
|
// Float64 looks up the value of a local Float64Flag, returns
|
||||||
// 0 if not found
|
// 0 if not found
|
||||||
func (c *Context) Float64(name string) float64 {
|
func (c *Context) Float64(name string) float64 {
|
||||||
if fs := lookupFlagSet(name, c); fs != nil {
|
if fs := c.lookupFlagSet(name); fs != nil {
|
||||||
return lookupFloat64(name, fs)
|
return lookupFloat64(name, fs)
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
|
@ -157,7 +157,7 @@ func (f *Float64SliceFlag) Apply(set *flag.FlagSet) error {
|
|||||||
// Float64Slice looks up the value of a local Float64SliceFlag, returns
|
// Float64Slice looks up the value of a local Float64SliceFlag, returns
|
||||||
// nil if not found
|
// nil if not found
|
||||||
func (c *Context) Float64Slice(name string) []float64 {
|
func (c *Context) Float64Slice(name string) []float64 {
|
||||||
if fs := lookupFlagSet(name, c); fs != nil {
|
if fs := c.lookupFlagSet(name); fs != nil {
|
||||||
return lookupFloat64Slice(name, fs)
|
return lookupFloat64Slice(name, fs)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -89,7 +89,7 @@ func (f GenericFlag) Apply(set *flag.FlagSet) error {
|
|||||||
// Generic looks up the value of a local GenericFlag, returns
|
// Generic looks up the value of a local GenericFlag, returns
|
||||||
// nil if not found
|
// nil if not found
|
||||||
func (c *Context) Generic(name string) interface{} {
|
func (c *Context) Generic(name string) interface{} {
|
||||||
if fs := lookupFlagSet(name, c); fs != nil {
|
if fs := c.lookupFlagSet(name); fs != nil {
|
||||||
return lookupGeneric(name, fs)
|
return lookupGeneric(name, fs)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -87,7 +87,7 @@ func (f *IntFlag) Apply(set *flag.FlagSet) error {
|
|||||||
// Int looks up the value of a local IntFlag, returns
|
// Int looks up the value of a local IntFlag, returns
|
||||||
// 0 if not found
|
// 0 if not found
|
||||||
func (c *Context) Int(name string) int {
|
func (c *Context) Int(name string) int {
|
||||||
if fs := lookupFlagSet(name, c); fs != nil {
|
if fs := c.lookupFlagSet(name); fs != nil {
|
||||||
return lookupInt(name, fs)
|
return lookupInt(name, fs)
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
|
@ -86,7 +86,7 @@ func (f *Int64Flag) Apply(set *flag.FlagSet) error {
|
|||||||
// Int64 looks up the value of a local Int64Flag, returns
|
// Int64 looks up the value of a local Int64Flag, returns
|
||||||
// 0 if not found
|
// 0 if not found
|
||||||
func (c *Context) Int64(name string) int64 {
|
func (c *Context) Int64(name string) int64 {
|
||||||
if fs := lookupFlagSet(name, c); fs != nil {
|
if fs := c.lookupFlagSet(name); fs != nil {
|
||||||
return lookupInt64(name, fs)
|
return lookupInt64(name, fs)
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
|
@ -156,7 +156,7 @@ func (f *Int64SliceFlag) Apply(set *flag.FlagSet) error {
|
|||||||
// Int64Slice looks up the value of a local Int64SliceFlag, returns
|
// Int64Slice looks up the value of a local Int64SliceFlag, returns
|
||||||
// nil if not found
|
// nil if not found
|
||||||
func (c *Context) Int64Slice(name string) []int64 {
|
func (c *Context) Int64Slice(name string) []int64 {
|
||||||
if fs := lookupFlagSet(name, c); fs != nil {
|
if fs := c.lookupFlagSet(name); fs != nil {
|
||||||
return lookupInt64Slice(name, fs)
|
return lookupInt64Slice(name, fs)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -167,7 +167,7 @@ func (f *IntSliceFlag) Apply(set *flag.FlagSet) error {
|
|||||||
// IntSlice looks up the value of a local IntSliceFlag, returns
|
// IntSlice looks up the value of a local IntSliceFlag, returns
|
||||||
// nil if not found
|
// nil if not found
|
||||||
func (c *Context) IntSlice(name string) []int {
|
func (c *Context) IntSlice(name string) []int {
|
||||||
if fs := lookupFlagSet(name, c); fs != nil {
|
if fs := c.lookupFlagSet(name); fs != nil {
|
||||||
return lookupIntSlice(name, fs)
|
return lookupIntSlice(name, fs)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -75,7 +75,7 @@ func (f *PathFlag) Apply(set *flag.FlagSet) error {
|
|||||||
// Path looks up the value of a local PathFlag, returns
|
// Path looks up the value of a local PathFlag, returns
|
||||||
// "" if not found
|
// "" if not found
|
||||||
func (c *Context) Path(name string) string {
|
func (c *Context) Path(name string) string {
|
||||||
if fs := lookupFlagSet(name, c); fs != nil {
|
if fs := c.lookupFlagSet(name); fs != nil {
|
||||||
return lookupPath(name, fs)
|
return lookupPath(name, fs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@ func (f *StringFlag) Apply(set *flag.FlagSet) error {
|
|||||||
// String looks up the value of a local StringFlag, returns
|
// String looks up the value of a local StringFlag, returns
|
||||||
// "" if not found
|
// "" if not found
|
||||||
func (c *Context) String(name string) string {
|
func (c *Context) String(name string) string {
|
||||||
if fs := lookupFlagSet(name, c); fs != nil {
|
if fs := c.lookupFlagSet(name); fs != nil {
|
||||||
return lookupString(name, fs)
|
return lookupString(name, fs)
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
|
@ -171,7 +171,7 @@ func (f *StringSliceFlag) Apply(set *flag.FlagSet) error {
|
|||||||
// StringSlice looks up the value of a local StringSliceFlag, returns
|
// StringSlice looks up the value of a local StringSliceFlag, returns
|
||||||
// nil if not found
|
// nil if not found
|
||||||
func (c *Context) StringSlice(name string) []string {
|
func (c *Context) StringSlice(name string) []string {
|
||||||
if fs := lookupFlagSet(name, c); fs != nil {
|
if fs := c.lookupFlagSet(name); fs != nil {
|
||||||
return lookupStringSlice(name, fs)
|
return lookupStringSlice(name, fs)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
12
flag_test.go
12
flag_test.go
@ -2038,3 +2038,15 @@ func TestFlagDefaultValue(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestTimestampFlagApply_WithDestination(t *testing.T) {
|
||||||
|
var destination Timestamp
|
||||||
|
expectedResult, _ := time.Parse(time.RFC3339, "2006-01-02T15:04:05Z")
|
||||||
|
fl := TimestampFlag{Name: "time", Aliases: []string{"t"}, Layout: time.RFC3339, Destination: &destination}
|
||||||
|
set := flag.NewFlagSet("test", 0)
|
||||||
|
_ = fl.Apply(set)
|
||||||
|
|
||||||
|
err := set.Parse([]string{"--time", "2006-01-02T15:04:05Z"})
|
||||||
|
expect(t, err, nil)
|
||||||
|
expect(t, *fl.Destination.timestamp, expectedResult)
|
||||||
|
}
|
||||||
|
@ -71,6 +71,7 @@ type TimestampFlag struct {
|
|||||||
Value *Timestamp
|
Value *Timestamp
|
||||||
DefaultText string
|
DefaultText string
|
||||||
HasBeenSet bool
|
HasBeenSet bool
|
||||||
|
Destination *Timestamp
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsSet returns whether or not the flag has been set through env or file
|
// IsSet returns whether or not the flag has been set through env or file
|
||||||
@ -123,6 +124,10 @@ func (f *TimestampFlag) Apply(set *flag.FlagSet) error {
|
|||||||
}
|
}
|
||||||
f.Value.SetLayout(f.Layout)
|
f.Value.SetLayout(f.Layout)
|
||||||
|
|
||||||
|
if f.Destination != nil {
|
||||||
|
f.Destination.SetLayout(f.Layout)
|
||||||
|
}
|
||||||
|
|
||||||
if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok {
|
if val, ok := flagFromEnvOrFile(f.EnvVars, f.FilePath); ok {
|
||||||
if err := f.Value.Set(val); err != nil {
|
if err := f.Value.Set(val); err != nil {
|
||||||
return fmt.Errorf("could not parse %q as timestamp value for flag %s: %s", val, f.Name, err)
|
return fmt.Errorf("could not parse %q as timestamp value for flag %s: %s", val, f.Name, err)
|
||||||
@ -131,6 +136,11 @@ func (f *TimestampFlag) Apply(set *flag.FlagSet) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, name := range f.Names() {
|
for _, name := range f.Names() {
|
||||||
|
if f.Destination != nil {
|
||||||
|
set.Var(f.Destination, name, f.Usage)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
set.Var(f.Value, name, f.Usage)
|
set.Var(f.Value, name, f.Usage)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -138,7 +148,7 @@ func (f *TimestampFlag) Apply(set *flag.FlagSet) error {
|
|||||||
|
|
||||||
// Timestamp gets the timestamp from a flag name
|
// Timestamp gets the timestamp from a flag name
|
||||||
func (c *Context) Timestamp(name string) *time.Time {
|
func (c *Context) Timestamp(name string) *time.Time {
|
||||||
if fs := lookupFlagSet(name, c); fs != nil {
|
if fs := c.lookupFlagSet(name); fs != nil {
|
||||||
return lookupTimestamp(name, fs)
|
return lookupTimestamp(name, fs)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -86,7 +86,7 @@ func (f *UintFlag) GetValue() string {
|
|||||||
// Uint looks up the value of a local UintFlag, returns
|
// Uint looks up the value of a local UintFlag, returns
|
||||||
// 0 if not found
|
// 0 if not found
|
||||||
func (c *Context) Uint(name string) uint {
|
func (c *Context) Uint(name string) uint {
|
||||||
if fs := lookupFlagSet(name, c); fs != nil {
|
if fs := c.lookupFlagSet(name); fs != nil {
|
||||||
return lookupUint(name, fs)
|
return lookupUint(name, fs)
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
|
@ -86,7 +86,7 @@ func (f *Uint64Flag) GetValue() string {
|
|||||||
// Uint64 looks up the value of a local Uint64Flag, returns
|
// Uint64 looks up the value of a local Uint64Flag, returns
|
||||||
// 0 if not found
|
// 0 if not found
|
||||||
func (c *Context) Uint64(name string) uint64 {
|
func (c *Context) Uint64(name string) uint64 {
|
||||||
if fs := lookupFlagSet(name, c); fs != nil {
|
if fs := c.lookupFlagSet(name); fs != nil {
|
||||||
return lookupUint64(name, fs)
|
return lookupUint64(name, fs)
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
|
@ -3,24 +3,17 @@ package cli
|
|||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
"runtime"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
|
||||||
wd, _ = os.Getwd()
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
_ = os.Setenv("CLI_TEMPLATE_REPANIC", "1")
|
_ = os.Setenv("CLI_TEMPLATE_REPANIC", "1")
|
||||||
}
|
}
|
||||||
|
|
||||||
func expect(t *testing.T, a interface{}, b interface{}) {
|
func expect(t *testing.T, a interface{}, b interface{}) {
|
||||||
_, fn, line, _ := runtime.Caller(1)
|
t.Helper()
|
||||||
fn = strings.Replace(fn, wd+"/", "", -1)
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(a, b) {
|
if !reflect.DeepEqual(a, b) {
|
||||||
t.Errorf("(%s:%d) Expected %v (type %v) - Got %v (type %v)", fn, line, b, reflect.TypeOf(b), a, reflect.TypeOf(a))
|
t.Errorf("Expected %v (type %v) - Got %v (type %v)", b, reflect.TypeOf(b), a, reflect.TypeOf(a))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user