Repository navigation
fix: handle payload getters in GenericFlag - #2460
Conversation
|
coilysiren
left a comment
There was a problem hiding this comment.
I'm going to hold for @dearchap to confirm, but this LGTM
Juneezee
left a comment
There was a problem hiding this comment.
I ran both repros from #2459 (the stdlib flag value and the custom textValue) as an external program, one callback at a time. On 26bd9a2, ValidateDefaults, the Validator and the flag Action each panic. On this branch all three run, Command.Generic returns the stored value (also through a persistent parent flag and an env source), and Command.Value still returns the payload. The new payload tests fail on 26bd9a2 and pass here; the self-returning and delegated controls pass on both.
On the question in #2459: cli.Value embeds flag.Getter, which the standard library describes as "an interface that allows the contents of a Value to be retrieved" (https://pkg.go.dev/flag#Getter). So a Get that returns a payload is a valid cli.Value. Fixing the callbacks instead of changing GenericFlag.Get leaves Command.Value as it is, so this approach looks right to me.
Optional nit: the nil check isn't needed. any(generic.val) is a nil interface when val is nil, and a comma-ok assertion on it returns the zero T:
Lines 200 to 206 in 341fa22
if generic, ok := f.value.(*genericValue); ok {
typed, _ := any(generic.val).(T)
return typed
}The full test suite passes with this change.
What type of PR is this?
What this PR does / why we need it:
A GenericFlag can hold a valid cli.Value whose Get method returns its underlying payload, such as a string. Default validation, validation after Set, and flag actions currently assert that payload back to cli.Value and panic before the callback runs. Command.Generic also returns nil for that value after parsing.
Which issue(s) this PR fixes:
Fixes #2459
Special notes for your reviewer:
This proposes the validator-side fix discussed in the issue. The public interface, FlagBase.Get, and Command.Value are unchanged: callers still receive the Getter's payload. If Get already returns a cli.Value, callbacks and Command.Generic keep using that result, including when it is a different value object. Plain nil GenericFlag values are passed to typed callbacks as nil.
The original reproductions and checks below were run locally.
Testing
On Go 1.26.5, macOS arm64:
The pinned gfmrun v1.3.0 macOS arm64 release asset returned 404, so that same version was built locally through the Go-install route documented in CONTRIBUTING before rerunning make all.
Release Notes