From 5386ade0f7a88a6fcbaa384d99e61563deac76ae Mon Sep 17 00:00:00 2001 From: Sergey Kamardin Date: Fri, 16 Oct 2020 23:39:12 +0300 Subject: [PATCH] SetActual() impl --- flagutil.go | 26 ++++++++++++++++++++++++++ flagutil_test.go | 44 ++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 66 insertions(+), 4 deletions(-) diff --git a/flagutil.go b/flagutil.go index 26e1b24..01e4150 100644 --- a/flagutil.go +++ b/flagutil.go @@ -517,6 +517,32 @@ func CombineFlags(f0, f1 *flag.Flag) *flag.Flag { return &r } +// SetActual makes flag look like it has been set within flag set. +// If flag set doesn't has flag with given SetActual() does nothing. +// Original value of found flag remains untouched, so it is safe to use with +// flags that accumulate values of multiple Set() calls. +func SetActual(fs *flag.FlagSet, name string) { + f := fs.Lookup(name) + if f == nil { + return + } + orig := f.Value + defer func() { + f.Value = orig + }() + var didSet bool + f.Value = value{ + doSet: func(s string) error { + didSet = s == "dummy" + return nil + }, + } + fs.Set(name, "dummy") + if !didSet { + panic("flagutil: make specified didn't work well") + } +} + func mergeUsage(name, s0, s1 string) string { switch { case s0 == "": diff --git a/flagutil_test.go b/flagutil_test.go index 4fa6b3b..18082d4 100644 --- a/flagutil_test.go +++ b/flagutil_test.go @@ -15,6 +15,21 @@ import ( "github.com/gobwas/flagutil/parse" ) +func TestSetActual(t *testing.T) { + fs := flag.NewFlagSet(t.Name(), flag.PanicOnError) + fs.String("flag", "default", "usage") + + f := fs.Lookup("flag") + f.Value = OverrideSet(f.Value, func(string) error { + t.Fatalf("unexpected value change") + return nil + }) + + mustNotBeActual(t, fs, "flag") + SetActual(fs, "flag") + mustBeActual(t, fs, "flag") +} + type fullParser struct { Parser Printer @@ -160,7 +175,7 @@ func ExampleMerge() { ) // Now we need to setup same flag (probably from some different place). // Setting it up again in a superset will cause error. - Merge(fs, func(sub *flag.FlagSet) { + MergeInto(fs, func(sub *flag.FlagSet) { // Notice that default value of this flag is different. // However, it will be discarded in favour of default value from superset. sub.StringVar(&s1, @@ -197,7 +212,7 @@ func ExampleMerge_different_types() { "foo", "42", "some flag usage here", ) - Merge(fs, func(sub *flag.FlagSet) { + MergeInto(fs, func(sub *flag.FlagSet) { sub.IntVar(&i, "foo", 84, "another flag usage here", @@ -222,10 +237,10 @@ func TestMerge(t *testing.T) { "foo", "bar", "superset usage", ) - Merge(fs, func(fs *flag.FlagSet) { + MergeInto(fs, func(fs *flag.FlagSet) { fs.StringVar(&s1, "foo", "baz", "subset1 usage") }) - Merge(fs, func(fs *flag.FlagSet) { + MergeInto(fs, func(fs *flag.FlagSet) { fs.StringVar(&s2, "foo", "baq", "subset2 usage") }) if s0 == s1 || s1 == s2 { @@ -323,6 +338,27 @@ func mustBeDefined(t *testing.T, fs *flag.FlagSet, name string) { } } +func mustBeActual(t *testing.T, fs *flag.FlagSet, name string) { + if !isActual(fs, name) { + t.Fatalf("want flag %q to be actual in set", name) + } +} + +func mustNotBeActual(t *testing.T, fs *flag.FlagSet, name string) { + if isActual(fs, name) { + t.Fatalf("want flag %q to not be actual in set", name) + } +} + +func isActual(fs *flag.FlagSet, name string) (actual bool) { + fs.Visit(func(f *flag.Flag) { + if f.Name == name { + actual = true + } + }) + return +} + func TestCombineFlags(t *testing.T) { for _, test := range []struct { name string