From 77d7cb9b851deca9030398b4ec809b7f15ef575f Mon Sep 17 00:00:00 2001 From: Jesse van den Kieboom Date: Sun, 21 Mar 2021 11:12:43 +0100 Subject: [PATCH] Do not prevent ini defaults overriding builtin defaults Issue #326. --- ini.go | 18 ++++++++++++++---- ini_test.go | 45 +++++++++++++++++++++++++++++++++++++++++++++ option.go | 19 +++++++++++++++++-- parser.go | 4 ---- 4 files changed, 76 insertions(+), 10 deletions(-) diff --git a/ini.go b/ini.go index 5debe74..2223d7b 100644 --- a/ini.go +++ b/ini.go @@ -541,9 +541,8 @@ func (i *IniParser) parse(ini *ini) error { continue } - // ini value is ignored if override is set and - // value was previously set from non default - if i.ParseAsDefaults && !opt.isSetDefault { + // ini value is ignored if parsed as default but defaults are prevented + if i.ParseAsDefaults && opt.preventDefault { continue } @@ -576,7 +575,15 @@ func (i *IniParser) parse(ini *ini) error { } } - if err := opt.set(pval); err != nil { + var err error + + if i.ParseAsDefaults { + err = opt.setDefault(pval) + } else { + err = opt.set(pval) + } + + if err != nil { return &IniError{ Message: err.Error(), File: ini.File, @@ -584,6 +591,9 @@ func (i *IniParser) parse(ini *ini) error { } } + // Defaults from ini files take precendence over defaults from parser + opt.preventDefault = true + // either all INI values are quoted or only values who need quoting if _, ok := quotesLookup[opt]; !inival.Quoted || !ok { quotesLookup[opt] = inival.Quoted diff --git a/ini_test.go b/ini_test.go index 65fc3e9..72bc386 100644 --- a/ini_test.go +++ b/ini_test.go @@ -903,6 +903,51 @@ func TestIniOverrides(t *testing.T) { assertString(t, opts.ValueWithDefaultOverrideCli, "cli-value") } +func TestIniOverridesFromConfigFlag(t *testing.T) { + file, err := ioutil.TempFile("", "") + + if err != nil { + t.Fatalf("Cannot create temporary file: %s", err) + } + + defer os.Remove(file.Name()) + + _, err = file.WriteString("value-with-default = \"ini-value\"\n") + _, err = file.WriteString("value-with-default-override-cli = \"ini-value\"\n") + + if err != nil { + t.Fatalf("Cannot write to temporary file: %s", err) + } + + file.Close() + + var opts struct { + Config func(filename string) `long:"config"` + ValueWithDefault string `long:"value-with-default" default:"value"` + ValueWithDefaultOverrideCli string `long:"value-with-default-override-cli" default:"value"` + } + + p := NewParser(&opts, Default) + + opt := p.FindOptionByLongName("config") + opt.Default = []string{file.Name()} + + opts.Config = func(filename string) { + parser := NewIniParser(p) + parser.ParseAsDefaults = true + parser.ParseFile(filename) + } + + _, err = p.ParseArgs([]string{"--value-with-default-override-cli", "cli-value"}) + + if err != nil { + t.Fatalf("Failed to parse arguments: %s", err) + } + + assertString(t, opts.ValueWithDefault, "ini-value") + assertString(t, opts.ValueWithDefaultOverrideCli, "cli-value") +} + func TestIniRequired(t *testing.T) { var opts struct { Required string `short:"r" required:"yes" description:"required"` diff --git a/option.go b/option.go index bc41916..cc441f8 100644 --- a/option.go +++ b/option.go @@ -280,6 +280,17 @@ func (option *Option) set(value *string) error { return convert("", option.value, option.tag) } +func (option *Option) setDefault(value *string) error { + if err := option.set(value); err != nil { + return err + } + + option.isSetDefault = true + option.preventDefault = false + + return nil +} + func (option *Option) showInHelp() bool { return !option.Hidden && (option.ShortName != 0 || len(option.LongName) != 0) } @@ -309,6 +320,10 @@ func (option *Option) empty() { } func (option *Option) clearDefault() error { + if option.preventDefault { + return nil + } + usedDefault := option.Default if envKey := option.EnvKeyWithNamespace(); envKey != "" { @@ -327,11 +342,11 @@ func (option *Option) clearDefault() error { option.empty() for _, d := range usedDefault { - err := option.set(&d) + err := option.setDefault(&d) + if err != nil { return err } - option.isSetDefault = true } } else { tp := option.value.Type() diff --git a/parser.go b/parser.go index f2e4237..1ebce81 100644 --- a/parser.go +++ b/parser.go @@ -311,10 +311,6 @@ func (p *Parser) ParseArgs(args []string) ([]string, error) { if s.err == nil { p.eachOption(func(c *Command, g *Group, option *Option) { - if option.preventDefault { - return - } - err := option.clearDefault() if err != nil { if _, ok := err.(*Error); !ok {