diff --git a/internal/requestflag/innerflag.go b/internal/requestflag/innerflag.go index 528915f..866ce27 100644 --- a/internal/requestflag/innerflag.go +++ b/internal/requestflag/innerflag.go @@ -32,6 +32,8 @@ type InnerFlag[ // map[string]any before SetInnerField runs. The hint is ignored for typed outer // flags whose zero value already carries a dispatchable reflect.Kind. OuterIsArrayOfObjects bool + + hasBeenSet bool } // GetDataAliases returns the aliases recognized when parsing inner field keys from piped or flag YAML. @@ -89,6 +91,7 @@ func (f *InnerFlag[T]) Set(name string, rawVal string) error { if settableInnerField, ok := f.OuterFlag.(SettableInnerField); ok { settableInnerField.SetInnerField(f.InnerField, parsedValue) + f.hasBeenSet = true } else { return fmt.Errorf("Cannot set inner field on %v", f.OuterFlag) } @@ -106,7 +109,7 @@ func (f *InnerFlag[T]) String() string { } func (f *InnerFlag[T]) IsSet() bool { - return false + return f.hasBeenSet } func (f *InnerFlag[T]) Names() []string { diff --git a/internal/requestflag/innerflag_precedence_test.go b/internal/requestflag/innerflag_precedence_test.go new file mode 100644 index 0000000..ad63103 --- /dev/null +++ b/internal/requestflag/innerflag_precedence_test.go @@ -0,0 +1,36 @@ +package requestflag + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/urfave/cli/v3" +) + +func TestInnerFlagCLIValueBeatsPipedData(t *testing.T) { + t.Parallel() + + outer := &Flag[map[string]any]{ + Name: "address", + BodyPath: "address", + } + assert.NoError(t, outer.PreParse()) + + cityInner := &InnerFlag[string]{ + Name: "address.city", + InnerField: "city", + OuterFlag: outer, + } + assert.NoError(t, cityInner.Set("address.city", "cli-value")) + assert.True(t, cityInner.IsSet()) + + data := map[string]any{ + "address": map[string]any{"city": "piped-value"}, + } + cmd := &cli.Command{Flags: []cli.Flag{outer, cityInner}} + assert.NoError(t, ApplyStdinDataToFlags(cmd, data)) + + outerVal, ok := outer.Get().(map[string]any) + assert.True(t, ok) + assert.Equal(t, "cli-value", outerVal["city"]) +}