diff --git a/fftest/test_case.go b/fftest/test_case.go index 6a7bde9..0760579 100644 --- a/fftest/test_case.go +++ b/fftest/test_case.go @@ -59,6 +59,7 @@ func (tc *ParseTest) Run(t *testing.T) { parseFunc = fftoml.Parse case ".env": parseFunc = ffenv.Parse + opts = append(opts, ff.WithEnvVars()) default: parseFunc = ff.PlainParser } diff --git a/flag_set_test.go b/flag_set_test.go index 928c6d7..e96c5f3 100644 --- a/flag_set_test.go +++ b/flag_set_test.go @@ -295,6 +295,19 @@ func TestFlagSet_invalid(t *testing.T) { _ = fs.Bool('a', "apple", "this should panic") }) + t.Run("same fold short name", func(t *testing.T) { + defer func() { + if x := recover(); x == nil { + t.Logf("have not expected panic (%v)", x) + } else { + t.Errorf("want peace, have panic") + } + }() + fs := ff.NewFlagSet(t.Name()) + _ = fs.Bool('a', "alpha", "this should be OK") + _ = fs.Bool('A', "apple", "this should be OK") + }) + t.Run("duplicate long name", func(t *testing.T) { defer func() { if x := recover(); x == nil { diff --git a/parse.go b/parse.go index bdfb2c7..0b8a03c 100644 --- a/parse.go +++ b/parse.go @@ -38,20 +38,23 @@ func parse(fs Flags, args []string, options ...Option) error { option(&pc) } - // Index valid flags by env var key, to support .env config files (below). - env2flag := map[string]Flag{} - { - if err := fs.WalkFlags(func(f Flag) error { - for _, name := range getNameStrings(f) { - key := getEnvVarKey(name, pc.envVarPrefix) - if existing, ok := env2flag[key]; ok { - return fmt.Errorf("%s: %w (%s)", getNameString(f), ErrDuplicateFlag, getNameString(existing)) + var env2flag map[string]Flag + if pc.envVarEnabled { + // Index valid flags by env var key, to support .env config files (below). + env2flag = map[string]Flag{} + { + if err := fs.WalkFlags(func(f Flag) error { + for _, name := range getNameStrings(f) { + key := getEnvVarKey(name, pc.envVarPrefix) + if existing, ok := env2flag[key]; ok { + return fmt.Errorf("%s: %w (%s)", getNameString(f), ErrDuplicateFlag, getNameString(existing)) + } + env2flag[key] = f } - env2flag[key] = f + return nil + }); err != nil { + return err } - return nil - }); err != nil { - return err } } diff --git a/parse_test.go b/parse_test.go index 62f9b3e..70750ba 100644 --- a/parse_test.go +++ b/parse_test.go @@ -2,6 +2,7 @@ package ff_test import ( "embed" + "errors" "flag" "os" "path/filepath" @@ -428,3 +429,30 @@ func TestParse_stdfs(t *testing.T) { t.Errorf("foo: want %q, have %q", want, have) } } + +func TestParse_shortSameCase(t *testing.T) { + t.Parallel() + + newFS := func() *ff.FlagSet { + fs := ff.NewFlagSet(t.Name()) + _ = fs.String('a', "apple", "", "foo string") + _ = fs.String('A', "apricot", "", "FOO string") + return fs + } + args := []string{"-a", "-A"} + + t.Run("no env", func(t *testing.T) { + t.Parallel() + if err := ff.Parse(newFS(), args); err != nil { + t.Error(err) + } + }) + t.Run("WithEnv", func(t *testing.T) { + t.Parallel() + if err := ff.Parse( + newFS(), args, ff.WithEnvVars(), + ); !errors.Is(err, ff.ErrDuplicateFlag) { + t.Errorf("wanted ErrDuplicateFlag, got %+v", err) + } + }) +}