Remove local altsrc and references

in favor of separate repo at https://github.com/urfave/cli-altsrc
main
Dan Buch 2 years ago
parent 766786fcc2
commit 9361cba851
Signed by: meatballhat
GPG Key ID: A12F782281063434

@ -1,6 +0,0 @@
package altsrc
// defaultInputSource creates a default InputSourceContext.
func defaultInputSource() (InputSourceContext, error) {
return &MapInputSource{file: "", valueMap: map[interface{}]interface{}{}}, nil
}

@ -1,18 +0,0 @@
# NOTE: this file is used by the tool defined in
# ./cmd/urfave-cli-genflags/main.go which uses the
# `Spec` type that maps to this file structure.
flag_types:
Bool:
Duration:
Float64:
Generic:
Int64:
Int:
IntSlice:
Int64Slice:
Float64Slice:
String:
Path:
StringSlice:
Uint64:
Uint:

@ -1,328 +0,0 @@
package altsrc
import (
"fmt"
"path/filepath"
"strconv"
"syscall"
"github.com/urfave/cli/v3"
)
// FlagInputSourceExtension is an extension interface of cli.Flag that
// allows a value to be set on the existing parsed flags.
type FlagInputSourceExtension interface {
cli.Flag
ApplyInputSourceValue(cCtx *cli.Context, isc InputSourceContext) error
}
// ApplyInputSourceValues iterates over all provided flags and
// executes ApplyInputSourceValue on flags implementing the
// FlagInputSourceExtension interface to initialize these flags
// to an alternate input source.
func ApplyInputSourceValues(cCtx *cli.Context, inputSourceContext InputSourceContext, flags []cli.Flag) error {
for _, f := range flags {
inputSourceExtendedFlag, isType := f.(FlagInputSourceExtension)
if isType {
err := inputSourceExtendedFlag.ApplyInputSourceValue(cCtx, inputSourceContext)
if err != nil {
return err
}
}
}
return nil
}
// InitInputSource is used to to setup an InputSourceContext on a cli.Command Before method. It will create a new
// input source based on the func provided. If there is no error it will then apply the new input source to any flags
// that are supported by the input source
func InitInputSource(flags []cli.Flag, createInputSource func() (InputSourceContext, error)) cli.BeforeFunc {
return func(cCtx *cli.Context) error {
inputSource, err := createInputSource()
if err != nil {
return fmt.Errorf("Unable to create input source: inner error: \n'%v'", err.Error())
}
return ApplyInputSourceValues(cCtx, inputSource, flags)
}
}
// InitInputSourceWithContext is used to to setup an InputSourceContext on a cli.Command Before method. It will create a new
// input source based on the func provided with potentially using existing cli.Context values to initialize itself. If there is
// no error it will then apply the new input source to any flags that are supported by the input source
func InitInputSourceWithContext(flags []cli.Flag, createInputSource func(cCtx *cli.Context) (InputSourceContext, error)) cli.BeforeFunc {
return func(cCtx *cli.Context) error {
inputSource, err := createInputSource(cCtx)
if err != nil {
return fmt.Errorf("Unable to create input source with context: inner error: \n'%v'", err.Error())
}
return ApplyInputSourceValues(cCtx, inputSource, flags)
}
}
// ApplyInputSourceValue applies a generic value to the flagSet if required
func (f *GenericFlag) ApplyInputSourceValue(cCtx *cli.Context, isc InputSourceContext) error {
if f.set == nil || cCtx.IsSet(f.Name) || isEnvVarSet(f.EnvVars) {
return nil
}
for _, name := range f.GenericFlag.Names() {
if !isc.isSet(name) {
continue
}
value, err := isc.Generic(name)
if err != nil {
return err
}
if value == nil {
continue
}
for _, n := range f.Names() {
_ = f.set.Set(n, value.String())
}
}
return nil
}
// ApplyInputSourceValue applies a StringSlice value to the flagSet if required
func (f *StringSliceFlag) ApplyInputSourceValue(cCtx *cli.Context, isc InputSourceContext) error {
if f.set == nil || cCtx.IsSet(f.Name) || isEnvVarSet(f.EnvVars) {
return nil
}
for _, name := range f.StringSliceFlag.Names() {
if !isc.isSet(name) {
continue
}
value, err := isc.StringSlice(name)
if err != nil {
return err
}
if value == nil {
continue
}
var sliceValue = *(cli.NewStringSlice(value...))
for _, n := range f.Names() {
underlyingFlag := f.set.Lookup(n)
if underlyingFlag == nil {
continue
}
underlyingFlag.Value = &sliceValue
}
if f.Destination != nil {
f.Destination.Set(sliceValue.Serialize())
}
}
return nil
}
// ApplyInputSourceValue applies a IntSlice value if required
func (f *IntSliceFlag) ApplyInputSourceValue(cCtx *cli.Context, isc InputSourceContext) error {
if f.set == nil || cCtx.IsSet(f.Name) || isEnvVarSet(f.EnvVars) {
return nil
}
for _, name := range f.IntSliceFlag.Names() {
if !isc.isSet(name) {
continue
}
value, err := isc.IntSlice(name)
if err != nil {
return err
}
if value == nil {
continue
}
var sliceValue = *(cli.NewIntSlice(value...))
for _, n := range f.Names() {
underlyingFlag := f.set.Lookup(n)
if underlyingFlag == nil {
continue
}
underlyingFlag.Value = &sliceValue
}
if f.Destination != nil {
f.Destination.Set(sliceValue.Serialize())
}
}
return nil
}
// ApplyInputSourceValue applies a Int64Slice value if required
func (f *Int64SliceFlag) ApplyInputSourceValue(cCtx *cli.Context, isc InputSourceContext) error {
if f.set == nil || cCtx.IsSet(f.Name) || isEnvVarSet(f.EnvVars) {
return nil
}
for _, name := range f.Int64SliceFlag.Names() {
if !isc.isSet(name) {
continue
}
value, err := isc.Int64Slice(name)
if err != nil {
return err
}
if value == nil {
continue
}
var sliceValue = *(cli.NewInt64Slice(value...))
for _, n := range f.Names() {
underlyingFlag := f.set.Lookup(n)
if underlyingFlag == nil {
continue
}
underlyingFlag.Value = &sliceValue
}
if f.Destination != nil {
f.Destination.Set(sliceValue.Serialize())
}
}
return nil
}
// ApplyInputSourceValue applies a Bool value to the flagSet if required
func (f *BoolFlag) ApplyInputSourceValue(cCtx *cli.Context, isc InputSourceContext) error {
if f.set == nil || cCtx.IsSet(f.Name) || isEnvVarSet(f.EnvVars) {
return nil
}
for _, name := range f.BoolFlag.Names() {
if !isc.isSet(name) {
continue
}
value, err := isc.Bool(name)
if err != nil {
return err
}
for _, n := range f.Names() {
_ = f.set.Set(n, strconv.FormatBool(value))
}
}
return nil
}
// ApplyInputSourceValue applies a String value to the flagSet if required
func (f *StringFlag) ApplyInputSourceValue(cCtx *cli.Context, isc InputSourceContext) error {
if f.set == nil || cCtx.IsSet(f.Name) || isEnvVarSet(f.EnvVars) {
return nil
}
for _, name := range f.StringFlag.Names() {
if !isc.isSet(name) {
continue
}
value, err := isc.String(name)
if err != nil {
return err
}
for _, n := range f.Names() {
_ = f.set.Set(n, value)
}
}
return nil
}
// ApplyInputSourceValue applies a Path value to the flagSet if required
func (f *PathFlag) ApplyInputSourceValue(cCtx *cli.Context, isc InputSourceContext) error {
if f.set == nil || cCtx.IsSet(f.Name) || isEnvVarSet(f.EnvVars) {
return nil
}
for _, name := range f.PathFlag.Names() {
if !isc.isSet(name) {
continue
}
value, err := isc.String(name)
if err != nil {
return err
}
if value == "" {
continue
}
for _, n := range f.Names() {
if !filepath.IsAbs(value) && isc.Source() != "" {
basePathAbs, err := filepath.Abs(isc.Source())
if err != nil {
return err
}
value = filepath.Join(filepath.Dir(basePathAbs), value)
}
_ = f.set.Set(n, value)
}
}
return nil
}
// ApplyInputSourceValue applies a int value to the flagSet if required
func (f *IntFlag) ApplyInputSourceValue(cCtx *cli.Context, isc InputSourceContext) error {
if f.set == nil || cCtx.IsSet(f.Name) || isEnvVarSet(f.EnvVars) {
return nil
}
for _, name := range f.IntFlag.Names() {
if !isc.isSet(name) {
continue
}
value, err := isc.Int(name)
if err != nil {
return err
}
for _, n := range f.Names() {
_ = f.set.Set(n, strconv.FormatInt(int64(value), 10))
}
}
return nil
}
// ApplyInputSourceValue applies a Duration value to the flagSet if required
func (f *DurationFlag) ApplyInputSourceValue(cCtx *cli.Context, isc InputSourceContext) error {
if f.set == nil || cCtx.IsSet(f.Name) || isEnvVarSet(f.EnvVars) {
return nil
}
for _, name := range f.DurationFlag.Names() {
if !isc.isSet(name) {
continue
}
value, err := isc.Duration(name)
if err != nil {
return err
}
for _, n := range f.Names() {
_ = f.set.Set(n, value.String())
}
}
return nil
}
// ApplyInputSourceValue applies a Float64 value to the flagSet if required
func (f *Float64Flag) ApplyInputSourceValue(cCtx *cli.Context, isc InputSourceContext) error {
if f.set == nil || cCtx.IsSet(f.Name) || isEnvVarSet(f.EnvVars) {
return nil
}
for _, name := range f.Float64Flag.Names() {
if !isc.isSet(name) {
continue
}
value, err := isc.Float64(name)
if err != nil {
return err
}
floatStr := float64ToString(value)
for _, n := range f.Names() {
_ = f.set.Set(n, floatStr)
}
}
return nil
}
func isEnvVarSet(envVars []string) bool {
for _, envVar := range envVars {
if _, ok := syscall.Getenv(envVar); ok {
// TODO: Can't use this for bools as
// set means that it was true or false based on
// Bool flag type, should work for other types
return true
}
}
return false
}
func float64ToString(f float64) string {
return fmt.Sprintf("%v", f)
}

@ -1,277 +0,0 @@
// WARNING: this file is generated. DO NOT EDIT
package altsrc
import (
"flag"
"github.com/urfave/cli/v3"
)
// BoolFlag is the flag type that wraps cli.BoolFlag to allow
// for other values to be specified
type BoolFlag struct {
*cli.BoolFlag
set *flag.FlagSet
}
// NewBoolFlag creates a new BoolFlag
func NewBoolFlag(fl *cli.BoolFlag) *BoolFlag {
return &BoolFlag{BoolFlag: fl, set: nil}
}
// Apply saves the flagSet for later usage calls, then calls
// the wrapped BoolFlag.Apply
func (f *BoolFlag) Apply(set *flag.FlagSet) error {
f.set = set
return f.BoolFlag.Apply(set)
}
// DurationFlag is the flag type that wraps cli.DurationFlag to allow
// for other values to be specified
type DurationFlag struct {
*cli.DurationFlag
set *flag.FlagSet
}
// NewDurationFlag creates a new DurationFlag
func NewDurationFlag(fl *cli.DurationFlag) *DurationFlag {
return &DurationFlag{DurationFlag: fl, set: nil}
}
// Apply saves the flagSet for later usage calls, then calls
// the wrapped DurationFlag.Apply
func (f *DurationFlag) Apply(set *flag.FlagSet) error {
f.set = set
return f.DurationFlag.Apply(set)
}
// Float64Flag is the flag type that wraps cli.Float64Flag to allow
// for other values to be specified
type Float64Flag struct {
*cli.Float64Flag
set *flag.FlagSet
}
// NewFloat64Flag creates a new Float64Flag
func NewFloat64Flag(fl *cli.Float64Flag) *Float64Flag {
return &Float64Flag{Float64Flag: fl, set: nil}
}
// Apply saves the flagSet for later usage calls, then calls
// the wrapped Float64Flag.Apply
func (f *Float64Flag) Apply(set *flag.FlagSet) error {
f.set = set
return f.Float64Flag.Apply(set)
}
// Float64SliceFlag is the flag type that wraps cli.Float64SliceFlag to allow
// for other values to be specified
type Float64SliceFlag struct {
*cli.Float64SliceFlag
set *flag.FlagSet
}
// NewFloat64SliceFlag creates a new Float64SliceFlag
func NewFloat64SliceFlag(fl *cli.Float64SliceFlag) *Float64SliceFlag {
return &Float64SliceFlag{Float64SliceFlag: fl, set: nil}
}
// Apply saves the flagSet for later usage calls, then calls
// the wrapped Float64SliceFlag.Apply
func (f *Float64SliceFlag) Apply(set *flag.FlagSet) error {
f.set = set
return f.Float64SliceFlag.Apply(set)
}
// GenericFlag is the flag type that wraps cli.GenericFlag to allow
// for other values to be specified
type GenericFlag struct {
*cli.GenericFlag
set *flag.FlagSet
}
// NewGenericFlag creates a new GenericFlag
func NewGenericFlag(fl *cli.GenericFlag) *GenericFlag {
return &GenericFlag{GenericFlag: fl, set: nil}
}
// Apply saves the flagSet for later usage calls, then calls
// the wrapped GenericFlag.Apply
func (f *GenericFlag) Apply(set *flag.FlagSet) error {
f.set = set
return f.GenericFlag.Apply(set)
}
// IntFlag is the flag type that wraps cli.IntFlag to allow
// for other values to be specified
type IntFlag struct {
*cli.IntFlag
set *flag.FlagSet
}
// NewIntFlag creates a new IntFlag
func NewIntFlag(fl *cli.IntFlag) *IntFlag {
return &IntFlag{IntFlag: fl, set: nil}
}
// Apply saves the flagSet for later usage calls, then calls
// the wrapped IntFlag.Apply
func (f *IntFlag) Apply(set *flag.FlagSet) error {
f.set = set
return f.IntFlag.Apply(set)
}
// Int64Flag is the flag type that wraps cli.Int64Flag to allow
// for other values to be specified
type Int64Flag struct {
*cli.Int64Flag
set *flag.FlagSet
}
// NewInt64Flag creates a new Int64Flag
func NewInt64Flag(fl *cli.Int64Flag) *Int64Flag {
return &Int64Flag{Int64Flag: fl, set: nil}
}
// Apply saves the flagSet for later usage calls, then calls
// the wrapped Int64Flag.Apply
func (f *Int64Flag) Apply(set *flag.FlagSet) error {
f.set = set
return f.Int64Flag.Apply(set)
}
// Int64SliceFlag is the flag type that wraps cli.Int64SliceFlag to allow
// for other values to be specified
type Int64SliceFlag struct {
*cli.Int64SliceFlag
set *flag.FlagSet
}
// NewInt64SliceFlag creates a new Int64SliceFlag
func NewInt64SliceFlag(fl *cli.Int64SliceFlag) *Int64SliceFlag {
return &Int64SliceFlag{Int64SliceFlag: fl, set: nil}
}
// Apply saves the flagSet for later usage calls, then calls
// the wrapped Int64SliceFlag.Apply
func (f *Int64SliceFlag) Apply(set *flag.FlagSet) error {
f.set = set
return f.Int64SliceFlag.Apply(set)
}
// IntSliceFlag is the flag type that wraps cli.IntSliceFlag to allow
// for other values to be specified
type IntSliceFlag struct {
*cli.IntSliceFlag
set *flag.FlagSet
}
// NewIntSliceFlag creates a new IntSliceFlag
func NewIntSliceFlag(fl *cli.IntSliceFlag) *IntSliceFlag {
return &IntSliceFlag{IntSliceFlag: fl, set: nil}
}
// Apply saves the flagSet for later usage calls, then calls
// the wrapped IntSliceFlag.Apply
func (f *IntSliceFlag) Apply(set *flag.FlagSet) error {
f.set = set
return f.IntSliceFlag.Apply(set)
}
// PathFlag is the flag type that wraps cli.PathFlag to allow
// for other values to be specified
type PathFlag struct {
*cli.PathFlag
set *flag.FlagSet
}
// NewPathFlag creates a new PathFlag
func NewPathFlag(fl *cli.PathFlag) *PathFlag {
return &PathFlag{PathFlag: fl, set: nil}
}
// Apply saves the flagSet for later usage calls, then calls
// the wrapped PathFlag.Apply
func (f *PathFlag) Apply(set *flag.FlagSet) error {
f.set = set
return f.PathFlag.Apply(set)
}
// StringFlag is the flag type that wraps cli.StringFlag to allow
// for other values to be specified
type StringFlag struct {
*cli.StringFlag
set *flag.FlagSet
}
// NewStringFlag creates a new StringFlag
func NewStringFlag(fl *cli.StringFlag) *StringFlag {
return &StringFlag{StringFlag: fl, set: nil}
}
// Apply saves the flagSet for later usage calls, then calls
// the wrapped StringFlag.Apply
func (f *StringFlag) Apply(set *flag.FlagSet) error {
f.set = set
return f.StringFlag.Apply(set)
}
// StringSliceFlag is the flag type that wraps cli.StringSliceFlag to allow
// for other values to be specified
type StringSliceFlag struct {
*cli.StringSliceFlag
set *flag.FlagSet
}
// NewStringSliceFlag creates a new StringSliceFlag
func NewStringSliceFlag(fl *cli.StringSliceFlag) *StringSliceFlag {
return &StringSliceFlag{StringSliceFlag: fl, set: nil}
}
// Apply saves the flagSet for later usage calls, then calls
// the wrapped StringSliceFlag.Apply
func (f *StringSliceFlag) Apply(set *flag.FlagSet) error {
f.set = set
return f.StringSliceFlag.Apply(set)
}
// UintFlag is the flag type that wraps cli.UintFlag to allow
// for other values to be specified
type UintFlag struct {
*cli.UintFlag
set *flag.FlagSet
}
// NewUintFlag creates a new UintFlag
func NewUintFlag(fl *cli.UintFlag) *UintFlag {
return &UintFlag{UintFlag: fl, set: nil}
}
// Apply saves the flagSet for later usage calls, then calls
// the wrapped UintFlag.Apply
func (f *UintFlag) Apply(set *flag.FlagSet) error {
f.set = set
return f.UintFlag.Apply(set)
}
// Uint64Flag is the flag type that wraps cli.Uint64Flag to allow
// for other values to be specified
type Uint64Flag struct {
*cli.Uint64Flag
set *flag.FlagSet
}
// NewUint64Flag creates a new Uint64Flag
func NewUint64Flag(fl *cli.Uint64Flag) *Uint64Flag {
return &Uint64Flag{Uint64Flag: fl, set: nil}
}
// Apply saves the flagSet for later usage calls, then calls
// the wrapped Uint64Flag.Apply
func (f *Uint64Flag) Apply(set *flag.FlagSet) error {
f.set = set
return f.Uint64Flag.Apply(set)
}
// vim:ro

@ -1,743 +0,0 @@
package altsrc
import (
"flag"
"fmt"
"os"
"path/filepath"
"runtime"
"strings"
"testing"
"time"
"github.com/urfave/cli/v3"
)
type testApplyInputSource struct {
Flag FlagInputSourceExtension
FlagName string
FlagSetName string
Expected string
ContextValueString string
ContextValue flag.Value
EnvVarValue string
EnvVarName string
SourcePath string
MapValue interface{}
}
type racyInputSource struct {
*MapInputSource
}
func (ris *racyInputSource) isSet(name string) bool {
if _, ok := ris.MapInputSource.valueMap[name]; ok {
ris.MapInputSource.valueMap[name] = bogus{0}
}
return true
}
func TestGenericApplyInputSourceValue_Alias(t *testing.T) {
v := &Parser{"abc", "def"}
tis := testApplyInputSource{
Flag: NewGenericFlag(&cli.GenericFlag{Name: "test", Aliases: []string{"test_alias"}, Value: &Parser{}}),
FlagName: "test_alias",
MapValue: v,
}
c := runTest(t, tis)
expect(t, v, c.Generic("test_alias"))
c = runRacyTest(t, tis)
refute(t, v, c.Generic("test_alias"))
}
func TestGenericApplyInputSourceValue(t *testing.T) {
v := &Parser{"abc", "def"}
tis := testApplyInputSource{
Flag: NewGenericFlag(&cli.GenericFlag{Name: "test", Value: &Parser{}}),
FlagName: "test",
MapValue: v,
}
c := runTest(t, tis)
expect(t, v, c.Generic("test"))
c = runRacyTest(t, tis)
refute(t, v, c.Generic("test"))
}
func TestGenericApplyInputSourceMethodContextSet(t *testing.T) {
p := &Parser{"abc", "def"}
tis := testApplyInputSource{
Flag: NewGenericFlag(&cli.GenericFlag{Name: "test", Value: &Parser{}}),
FlagName: "test",
MapValue: &Parser{"efg", "hig"},
ContextValueString: p.String(),
}
c := runTest(t, tis)
expect(t, p, c.Generic("test"))
c = runRacyTest(t, tis)
refute(t, p, c.Generic("test"))
}
func TestGenericApplyInputSourceMethodEnvVarSet(t *testing.T) {
tis := testApplyInputSource{
Flag: NewGenericFlag(&cli.GenericFlag{
Name: "test",
Value: &Parser{},
EnvVars: []string{"TEST"},
}),
FlagName: "test",
MapValue: &Parser{"efg", "hij"},
EnvVarName: "TEST",
EnvVarValue: "abc,def",
}
c := runTest(t, tis)
expect(t, &Parser{"abc", "def"}, c.Generic("test"))
c = runRacyTest(t, tis)
refute(t, &Parser{"abc", "def"}, c.Generic("test"))
}
func TestStringSliceApplyInputSourceValue_Alias(t *testing.T) {
dest := cli.NewStringSlice()
tis := testApplyInputSource{
Flag: NewStringSliceFlag(&cli.StringSliceFlag{Name: "test", Aliases: []string{"test_alias"}, Destination: dest}),
FlagName: "test_alias",
MapValue: []interface{}{"hello", "world"},
}
c := runTest(t, tis)
expect(t, c.StringSlice("test_alias"), []string{"hello", "world"})
expect(t, dest.Value(), []string{"hello", "world"})
// reset dest
dest = cli.NewStringSlice()
tis = testApplyInputSource{
Flag: NewStringSliceFlag(&cli.StringSliceFlag{Name: "test", Aliases: []string{"test_alias"}, Destination: dest}),
FlagName: "test_alias",
MapValue: []interface{}{"hello", "world"},
}
c = runRacyTest(t, tis)
refute(t, c.StringSlice("test_alias"), []string{"hello", "world"})
refute(t, dest.Value(), []string{"hello", "world"})
}
func TestStringSliceApplyInputSourceValue(t *testing.T) {
dest := cli.NewStringSlice()
tis := testApplyInputSource{
Flag: NewStringSliceFlag(&cli.StringSliceFlag{Name: "test", Destination: dest}),
FlagName: "test",
MapValue: []interface{}{"hello", "world"},
}
c := runTest(t, tis)
expect(t, c.StringSlice("test"), []string{"hello", "world"})
expect(t, dest.Value(), []string{"hello", "world"})
// reset dest
dest = cli.NewStringSlice()
tis = testApplyInputSource{
Flag: NewStringSliceFlag(&cli.StringSliceFlag{Name: "test", Destination: dest}),
FlagName: "test",
MapValue: []interface{}{"hello", "world"},
}
c = runRacyTest(t, tis)
refute(t, c.StringSlice("test"), []string{"hello", "world"})
refute(t, dest.Value(), []string{"hello", "world"})
}
func TestStringSliceApplyInputSourceMethodContextSet(t *testing.T) {
dest := cli.NewStringSlice()
c := runTest(t, testApplyInputSource{
Flag: NewStringSliceFlag(&cli.StringSliceFlag{Name: "test", Destination: dest}),
FlagName: "test",
MapValue: []interface{}{"hello", "world"},
ContextValueString: "ohno",
})
expect(t, c.StringSlice("test"), []string{"ohno"})
expect(t, dest.Value(), []string{"ohno"})
}
func TestStringSliceApplyInputSourceMethodEnvVarSet(t *testing.T) {
tis := testApplyInputSource{
Flag: NewStringSliceFlag(&cli.StringSliceFlag{Name: "test", EnvVars: []string{"TEST"}}),
FlagName: "test",
MapValue: []interface{}{"hello", "world"},
EnvVarName: "TEST",
EnvVarValue: "oh,no",
}
c := runTest(t, tis)
expect(t, c.StringSlice("test"), []string{"oh", "no"})
c = runRacyTest(t, tis)
refute(t, c.StringSlice("test"), []string{"oh", "no"})
}
func TestIntSliceApplyInputSourceValue_Alias(t *testing.T) {
dest := cli.NewIntSlice()
tis := testApplyInputSource{
Flag: NewIntSliceFlag(&cli.IntSliceFlag{Name: "test", Aliases: []string{"test_alias"}, Destination: dest}),
FlagName: "test_alias",
MapValue: []interface{}{1, 2},
}
c := runTest(t, tis)
expect(t, c.IntSlice("test_alias"), []int{1, 2})
expect(t, dest.Value(), []int{1, 2})
dest = cli.NewIntSlice()
tis = testApplyInputSource{
Flag: NewIntSliceFlag(&cli.IntSliceFlag{Name: "test", Aliases: []string{"test_alias"}, Destination: dest}),
FlagName: "test_alias",
MapValue: []interface{}{1, 2},
}
c = runRacyTest(t, tis)
refute(t, c.IntSlice("test_alias"), []int{1, 2})
refute(t, dest.Value(), []int{1, 2})
}
func TestIntSliceApplyInputSourceValue(t *testing.T) {
dest := cli.NewIntSlice()
tis := testApplyInputSource{
Flag: NewIntSliceFlag(&cli.IntSliceFlag{Name: "test", Destination: dest}),
FlagName: "test",
MapValue: []interface{}{1, 2},
}
c := runTest(t, tis)
expect(t, c.IntSlice("test"), []int{1, 2})
expect(t, dest.Value(), []int{1, 2})
// reset dest
dest = cli.NewIntSlice()
tis = testApplyInputSource{
Flag: NewIntSliceFlag(&cli.IntSliceFlag{Name: "test", Destination: dest}),
FlagName: "test",
MapValue: []interface{}{1, 2},
}
c = runRacyTest(t, tis)
refute(t, c.IntSlice("test"), []int{1, 2})
refute(t, dest.Value(), []int{1, 2})
}
func TestIntSliceApplyInputSourceMethodContextSet(t *testing.T) {
dest := cli.NewIntSlice()
tis := testApplyInputSource{
Flag: NewIntSliceFlag(&cli.IntSliceFlag{Name: "test", Destination: dest}),
FlagName: "test",
MapValue: []interface{}{1, 2},
ContextValueString: "3",
}
c := runTest(t, tis)
expect(t, c.IntSlice("test"), []int{3})
expect(t, dest.Value(), []int{3})
// reset dest
dest = cli.NewIntSlice()
tis = testApplyInputSource{
Flag: NewIntSliceFlag(&cli.IntSliceFlag{Name: "test", Destination: dest}),
FlagName: "test",
MapValue: []interface{}{1, 2},
ContextValueString: "3",
}
c = runRacyTest(t, tis)
refute(t, c.IntSlice("test"), []int{3})
refute(t, dest.Value(), []int{3})
}
func TestIntSliceApplyInputSourceMethodEnvVarSet(t *testing.T) {
tis := testApplyInputSource{
Flag: NewIntSliceFlag(&cli.IntSliceFlag{Name: "test", EnvVars: []string{"TEST"}}),
FlagName: "test",
MapValue: []interface{}{1, 2},
EnvVarName: "TEST",
EnvVarValue: "3,4",
}
c := runTest(t, tis)
expect(t, c.IntSlice("test"), []int{3, 4})
c = runRacyTest(t, tis)
refute(t, c.IntSlice("test"), []int{3, 4})
}
func TestInt64SliceFlagApplyInputSourceValue(t *testing.T) {
dest := cli.NewInt64Slice()
tis := testApplyInputSource{
Flag: NewInt64SliceFlag(&cli.Int64SliceFlag{Name: "test", Destination: dest}),
FlagName: "test",
MapValue: []interface{}{int64(1), int64(2)},
}
c := runTest(t, tis)
expect(t, c.Int64Slice("test"), []int64{1, 2})
expect(t, dest.Value(), []int64{1, 2})
// reset dest
dest = cli.NewInt64Slice()
tis = testApplyInputSource{
Flag: NewInt64SliceFlag(&cli.Int64SliceFlag{Name: "test", Destination: dest}),
FlagName: "test",
MapValue: []interface{}{int64(1), int64(2)},
}
c = runRacyTest(t, tis)
refute(t, c.IntSlice("test"), []int64{1, 2})
refute(t, dest.Value(), []int64{1, 2})
}
func TestBoolApplyInputSourceMethodSet(t *testing.T) {
tis := testApplyInputSource{
Flag: NewBoolFlag(&cli.BoolFlag{Name: "test"}),
FlagName: "test",
MapValue: true,
}
c := runTest(t, tis)
expect(t, true, c.Bool("test"))
c = runRacyTest(t, tis)
refute(t, true, c.Bool("test"))
}
func TestBoolApplyInputSourceMethodSet_Alias(t *testing.T) {
tis := testApplyInputSource{
Flag: NewBoolFlag(&cli.BoolFlag{Name: "test", Aliases: []string{"test_alias"}}),
FlagName: "test_alias",
MapValue: true,
}
c := runTest(t, tis)
expect(t, true, c.Bool("test_alias"))
c = runRacyTest(t, tis)
refute(t, true, c.Bool("test_alias"))
}
func TestBoolApplyInputSourceMethodContextSet(t *testing.T) {
tis := testApplyInputSource{
Flag: NewBoolFlag(&cli.BoolFlag{Name: "test"}),
FlagName: "test",
MapValue: false,
ContextValueString: "true",
}
c := runTest(t, tis)
expect(t, true, c.Bool("test"))
c = runRacyTest(t, tis)
refute(t, true, c.Bool("test"))
}
func TestBoolApplyInputSourceMethodEnvVarSet(t *testing.T) {
tis := testApplyInputSource{
Flag: NewBoolFlag(&cli.BoolFlag{Name: "test", EnvVars: []string{"TEST"}}),
FlagName: "test",
MapValue: false,
EnvVarName: "TEST",
EnvVarValue: "true",
}
c := runTest(t, tis)
expect(t, true, c.Bool("test"))
c = runRacyTest(t, tis)
refute(t, true, c.Bool("test"))
}
func TestStringApplyInputSourceMethodSet_Alias(t *testing.T) {
tis := testApplyInputSource{
Flag: NewStringFlag(&cli.StringFlag{Name: "test", Aliases: []string{"test_alias"}}),
FlagName: "test_alias",
MapValue: "hello",
}
c := runTest(t, tis)
expect(t, "hello", c.String("test_alias"))
c = runRacyTest(t, tis)
refute(t, "hello", c.String("test_alias"))
}
func TestStringApplyInputSourceMethodSet(t *testing.T) {
tis := testApplyInputSource{
Flag: NewStringFlag(&cli.StringFlag{Name: "test"}),
FlagName: "test",
MapValue: "hello",
}
c := runTest(t, tis)
expect(t, "hello", c.String("test"))
c = runRacyTest(t, tis)
refute(t, "hello", c.String("test"))
}
func TestStringApplyInputSourceMethodContextSet(t *testing.T) {
tis := testApplyInputSource{
Flag: NewStringFlag(&cli.StringFlag{Name: "test"}),
FlagName: "test",
MapValue: "hello",
ContextValueString: "goodbye",
}
c := runTest(t, tis)
expect(t, "goodbye", c.String("test"))
c = runRacyTest(t, tis)
refute(t, "goodbye", c.String("test"))
}
func TestStringApplyInputSourceMethodEnvVarSet(t *testing.T) {
tis := testApplyInputSource{
Flag: NewStringFlag(&cli.StringFlag{Name: "test", EnvVars: []string{"TEST"}}),
FlagName: "test",
MapValue: "hello",
EnvVarName: "TEST",
EnvVarValue: "goodbye",
}
c := runTest(t, tis)
expect(t, "goodbye", c.String("test"))
c = runRacyTest(t, tis)
refute(t, "goodbye", c.String("test"))
}
func TestPathApplyInputSourceMethodSet_Alias(t *testing.T) {
tis := testApplyInputSource{
Flag: NewPathFlag(&cli.PathFlag{Name: "test", Aliases: []string{"test_alias"}}),
FlagName: "test_alias",
MapValue: "hello",
SourcePath: "/path/to/source/file",
}
c := runTest(t, tis)
expected := "/path/to/source/hello"
if runtime.GOOS == "windows" {
var err error
// Prepend the corresponding drive letter (or UNC path?), and change
// to windows-style path:
expected, err = filepath.Abs(expected)
if err != nil {
t.Fatal(err)
}
}
expect(t, expected, c.String("test_alias"))
c = runRacyTest(t, tis)
refute(t, expected, c.String("test_alias"))
}
func TestPathApplyInputSourceMethodSet(t *testing.T) {
tis := testApplyInputSource{
Flag: NewPathFlag(&cli.PathFlag{Name: "test"}),
FlagName: "test",
MapValue: "hello",
SourcePath: "/path/to/source/file",
}
c := runTest(t, tis)
expected := "/path/to/source/hello"
if runtime.GOOS == "windows" {
var err error
// Prepend the corresponding drive letter (or UNC path?), and change
// to windows-style path:
expected, err = filepath.Abs(expected)
if err != nil {
t.Fatal(err)
}
}
expect(t, expected, c.String("test"))
c = runRacyTest(t, tis)
refute(t, expected, c.String("test"))
}
func TestPathApplyInputSourceMethodContextSet(t *testing.T) {
tis := testApplyInputSource{
Flag: NewPathFlag(&cli.PathFlag{Name: "test"}),
FlagName: "test",
MapValue: "hello",
ContextValueString: "goodbye",
SourcePath: "/path/to/source/file",
}
c := runTest(t, tis)
expect(t, "goodbye", c.String("test"))
c = runRacyTest(t, tis)
refute(t, "goodbye", c.String("test"))
}
func TestPathApplyInputSourceMethodEnvVarSet(t *testing.T) {
tis := testApplyInputSource{
Flag: NewPathFlag(&cli.PathFlag{Name: "test", EnvVars: []string{"TEST"}}),
FlagName: "test",
MapValue: "hello",
EnvVarName: "TEST",
EnvVarValue: "goodbye",
SourcePath: "/path/to/source/file",
}
c := runTest(t, tis)
expect(t, "goodbye", c.String("test"))
c = runRacyTest(t, tis)
refute(t, "goodbye", c.String("test"))
}
func TestIntApplyInputSourceMethodSet_Alias(t *testing.T) {
tis := testApplyInputSource{
Flag: NewIntFlag(&cli.IntFlag{Name: "test", Aliases: []string{"test_alias"}}),
FlagName: "test_alias",
MapValue: 15,
}
c := runTest(t, tis)
expect(t, 15, c.Int("test_alias"))
c = runRacyTest(t, tis)
refute(t, 15, c.Int("test_alias"))
}
func TestIntApplyInputSourceMethodSet(t *testing.T) {
tis := testApplyInputSource{
Flag: NewIntFlag(&cli.IntFlag{Name: "test"}),
FlagName: "test",
MapValue: 15,
}
c := runTest(t, tis)
expect(t, 15, c.Int("test"))
c = runRacyTest(t, tis)
refute(t, 15, c.Int("test"))
}
func TestIntApplyInputSourceMethodSetNegativeValue(t *testing.T) {
tis := testApplyInputSource{
Flag: NewIntFlag(&cli.IntFlag{Name: "test"}),
FlagName: "test",
MapValue: -1,
}
c := runTest(t, tis)
expect(t, -1, c.Int("test"))
c = runRacyTest(t, tis)
refute(t, -1, c.Int("test"))
}
func TestIntApplyInputSourceMethodContextSet(t *testing.T) {
tis := testApplyInputSource{
Flag: NewIntFlag(&cli.IntFlag{Name: "test"}),
FlagName: "test",
MapValue: 15,
ContextValueString: "7",
}
c := runTest(t, tis)
expect(t, 7, c.Int("test"))
c = runRacyTest(t, tis)
refute(t, 7, c.Int("test"))
}
func TestIntApplyInputSourceMethodEnvVarSet(t *testing.T) {
tis := testApplyInputSource{
Flag: NewIntFlag(&cli.IntFlag{Name: "test", EnvVars: []string{"TEST"}}),
FlagName: "test",
MapValue: 15,
EnvVarName: "TEST",
EnvVarValue: "12",
}
c := runTest(t, tis)
expect(t, 12, c.Int("test"))
c = runRacyTest(t, tis)
refute(t, 12, c.Int("test"))
}
func TestDurationApplyInputSourceMethodSet_Alias(t *testing.T) {
tis := testApplyInputSource{
Flag: NewDurationFlag(&cli.DurationFlag{Name: "test", Aliases: []string{"test_alias"}}),
FlagName: "test_alias",
MapValue: 30 * time.Second,
}
c := runTest(t, tis)
expect(t, 30*time.Second, c.Duration("test_alias"))
c = runRacyTest(t, tis)
refute(t, 30*time.Second, c.Duration("test_alias"))
}
func TestDurationApplyInputSourceMethodSet(t *testing.T) {
tis := testApplyInputSource{
Flag: NewDurationFlag(&cli.DurationFlag{Name: "test"}),
FlagName: "test",
MapValue: 30 * time.Second,
}
c := runTest(t, tis)
expect(t, 30*time.Second, c.Duration("test"))
c = runRacyTest(t, tis)
refute(t, 30*time.Second, c.Duration("test"))
}
func TestDurationApplyInputSourceMethodSetNegativeValue(t *testing.T) {
tis := testApplyInputSource{
Flag: NewDurationFlag(&cli.DurationFlag{Name: "test"}),
FlagName: "test",
MapValue: -30 * time.Second,
}
c := runTest(t, tis)
expect(t, -30*time.Second, c.Duration("test"))
c = runRacyTest(t, tis)
refute(t, -30*time.Second, c.Duration("test"))
}
func TestDurationApplyInputSourceMethodContextSet(t *testing.T) {
tis := testApplyInputSource{
Flag: NewDurationFlag(&cli.DurationFlag{Name: "test"}),
FlagName: "test",
MapValue: 30 * time.Second,
ContextValueString: (15 * time.Second).String(),
}
c := runTest(t, tis)
expect(t, 15*time.Second, c.Duration("test"))
c = runRacyTest(t, tis)
refute(t, 15*time.Second, c.Duration("test"))
}
func TestDurationApplyInputSourceMethodEnvVarSet(t *testing.T) {
tis := testApplyInputSource{
Flag: NewDurationFlag(&cli.DurationFlag{Name: "test", EnvVars: []string{"TEST"}}),
FlagName: "test",
MapValue: 30 * time.Second,
EnvVarName: "TEST",
EnvVarValue: (15 * time.Second).String(),
}
c := runTest(t, tis)
expect(t, 15*time.Second, c.Duration("test"))
c = runRacyTest(t, tis)
refute(t, 15*time.Second, c.Duration("test"))
}
func TestFloat64ApplyInputSourceMethodSet(t *testing.T) {
tis := testApplyInputSource{
Flag: NewFloat64Flag(&cli.Float64Flag{Name: "test"}),
FlagName: "test",
MapValue: 1.3,
}
c := runTest(t, tis)
expect(t, 1.3, c.Float64("test"))
c = runRacyTest(t, tis)
refute(t, 1.3, c.Float64("test"))
}
func TestFloat64ApplyInputSourceMethodSetNegativeValue_Alias(t *testing.T) {
tis := testApplyInputSource{
Flag: NewFloat64Flag(&cli.Float64Flag{Name: "test", Aliases: []string{"test_alias"}}),
FlagName: "test_alias",
MapValue: -1.3,
}
c := runTest(t, tis)
expect(t, -1.3, c.Float64("test_alias"))
c = runRacyTest(t, tis)
refute(t, -1.3, c.Float64("test_alias"))
}
func TestFloat64ApplyInputSourceMethodSetNegativeValue(t *testing.T) {
tis := testApplyInputSource{
Flag: NewFloat64Flag(&cli.Float64Flag{Name: "test"}),
FlagName: "test",
MapValue: -1.3,
}
c := runTest(t, tis)
expect(t, -1.3, c.Float64("test"))
c = runRacyTest(t, tis)
refute(t, -1.3, c.Float64("test"))
}
func TestFloat64ApplyInputSourceMethodSetNegativeValueNotSet(t *testing.T) {
c := runTest(t, testApplyInputSource{
Flag: NewFloat64Flag(&cli.Float64Flag{Name: "test1"}),
FlagName: "test1",
// dont set map value
})
expect(t, 0.0, c.Float64("test1"))
}
func TestFloat64ApplyInputSourceMethodContextSet(t *testing.T) {
tis := testApplyInputSource{
Flag: NewFloat64Flag(&cli.Float64Flag{Name: "test"}),
FlagName: "test",
MapValue: 1.3,
ContextValueString: fmt.Sprintf("%v", 1.4),
}
c := runTest(t, tis)
expect(t, 1.4, c.Float64("test"))
c = runRacyTest(t, tis)
refute(t, 1.4, c.Float64("test"))
}
func TestFloat64ApplyInputSourceMethodEnvVarSet(t *testing.T) {
tis := testApplyInputSource{
Flag: NewFloat64Flag(&cli.Float64Flag{Name: "test", EnvVars: []string{"TEST"}}),
FlagName: "test",
MapValue: 1.3,
EnvVarName: "TEST",
EnvVarValue: fmt.Sprintf("%v", 1.4),
}
c := runTest(t, tis)
expect(t, 1.4, c.Float64("test"))
c = runRacyTest(t, tis)
refute(t, 1.4, c.Float64("test"))
}
func runTest(t *testing.T, test testApplyInputSource) *cli.Context {
inputSource := &MapInputSource{
file: test.SourcePath,
valueMap: map[interface{}]interface{}{test.FlagName: test.MapValue},
}
set := flag.NewFlagSet(test.FlagSetName, flag.ContinueOnError)
c := cli.NewContext(nil, set, nil)
if test.EnvVarName != "" && test.EnvVarValue != "" {
_ = os.Setenv(test.EnvVarName, test.EnvVarValue)
defer os.Setenv(test.EnvVarName, "")
}
_ = test.Flag.Apply(set)
if test.ContextValue != nil {
f := set.Lookup(test.FlagName)
f.Value = test.ContextValue
}
if test.ContextValueString != "" {
_ = set.Set(test.FlagName, test.ContextValueString)
}
_ = test.Flag.ApplyInputSourceValue(c, inputSource)
return c
}
func runRacyTest(t *testing.T, test testApplyInputSource) *cli.Context {
set := flag.NewFlagSet(test.FlagSetName, flag.ContinueOnError)
c := cli.NewContext(nil, set, nil)
_ = test.Flag.ApplyInputSourceValue(c, &racyInputSource{
MapInputSource: &MapInputSource{
file: test.SourcePath,
valueMap: map[interface{}]interface{}{test.FlagName: test.MapValue},
},
})
return c
}
type Parser [2]string
func (p *Parser) Set(value string) error {
parts := strings.Split(value, ",")
if len(parts) != 2 {
return fmt.Errorf("invalid format")
}
(*p)[0] = parts[0]
(*p)[1] = parts[1]
return nil
}
func (p *Parser) String() string {
return fmt.Sprintf("%s,%s", p[0], p[1])
}
type bogus [1]uint

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

@ -1,28 +0,0 @@
package altsrc
import (
"time"
"github.com/urfave/cli/v3"
)
// InputSourceContext is an interface used to allow
// other input sources to be implemented as needed.
//
// Source returns an identifier for the input source. In case of file source
// it should return path to the file.
type InputSourceContext interface {
Source() string
Int(name string) (int, error)
Duration(name string) (time.Duration, error)
Float64(name string) (float64, error)
String(name string) (string, error)
StringSlice(name string) ([]string, error)
IntSlice(name string) ([]int, error)
Int64Slice(name string) ([]int64, error)
Generic(name string) (cli.Generic, error)
Bool(name string) (bool, error)
isSet(name string) bool
}

@ -1,329 +0,0 @@
package altsrc
import (
"flag"
"io/ioutil"
"os"
"testing"
"github.com/urfave/cli/v3"