From 6f81c7e746a3c7917f9d0efc1a6b34d905135866 Mon Sep 17 00:00:00 2001 From: GrĂ©goire DuchĂȘne Date: Sat, 3 Dec 2022 12:19:17 +0000 Subject: Prevent flags from being set again by default Flag values that are safe to be set again should implement the new MutableFlagValue interface. --- flag.go | 13 +++++++++++++ flag_test.go | 9 +++++++++ 2 files changed, 22 insertions(+) diff --git a/flag.go b/flag.go index 6fe41f3..4ef45d1 100644 --- a/flag.go +++ b/flag.go @@ -82,6 +82,12 @@ func InitFlagSet(fs *flag.FlagSet, env []string, cfg map[string]string, args []s return } + if f.DefValue != f.Value.String() { + if _, ok := f.Value.(MutableFlagValue); !ok { + return + } + } + var next string if val, found := environ[strings.ToUpper(strings.ReplaceAll(f.Name, "-", "_"))]; found { next = val @@ -102,6 +108,13 @@ func InitFlagSet(fs *flag.FlagSet, env []string, cfg map[string]string, args []s return err } +// MutableFlagValue is used to signal whether it is safe to set a flag +// to another value if it has already been set before, i.e. if its +// current value (as a string) is the same as its default value. +type MutableFlagValue interface { + MutableFlagValue() +} + // ParseString returns the string passed with no error set. func ParseString(s string) (string, error) { return s, nil diff --git a/flag_test.go b/flag_test.go index 26568d6..1f36b63 100644 --- a/flag_test.go +++ b/flag_test.go @@ -110,4 +110,13 @@ func TestInitFlagSet(s *testing.T) { t.AssertEqual(tc.expStr, *fm) }) } + + t.Run("NoMutableFlagValue", func(t *core.T) { + fs := flag.NewFlagSet("", flag.PanicOnError) + fi := fs.Int("int", 0, "") + t.AssertErrorIs(nil, core.InitFlagSet(fs, nil, nil, []string{"-int=42"})) + t.AssertEqual(42, *fi) + t.AssertErrorIs(nil, core.InitFlagSet(fs, nil, nil, []string{"-int=21"})) + t.AssertEqual(42, *fi) + }) } -- cgit v1.2.3-70-g09d2