Skip to content

Commit

Permalink
Propagate noinit from parent fields (#67)
Browse files Browse the repository at this point in the history
Prior to this commit, only the first-level parent fields were propagated for `noinit`. This fixes the bug to always carry noinit through to all nested fields in a struct.
  • Loading branch information
sethvargo committed Jul 27, 2022
1 parent f264df5 commit 20ad4b3
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 6 deletions.
10 changes: 5 additions & 5 deletions envconfig.go
Expand Up @@ -286,17 +286,18 @@ func processWith(ctx context.Context, i interface{}, l Lookuper, parentNoInit bo
if opts.NoInit && ef.Kind() != reflect.Ptr {
return fmt.Errorf("%s: %w", tf.Name, ErrNoInitNotPtr)
}
shouldNotInit := opts.NoInit || parentNoInit

isNilStructPtr := false
setNilStruct := func(v reflect.Value) {
origin := e.Field(i)
if isNilStructPtr {
empty := reflect.New(origin.Type().Elem()).Interface()

// If a struct (after traversal) equals to the empty value, it means
// nothing was changed in any sub-fields. With the noinit opt, we skip
// setting the empty value to the original struct pointer (aka. keep it
// nil).
if !reflect.DeepEqual(v.Interface(), empty) || (!opts.NoInit && !parentNoInit) {
// setting the empty value to the original struct pointer (keep it nil).
if !reflect.DeepEqual(v.Interface(), empty) || !shouldNotInit {
origin.Set(v)
}
}
Expand All @@ -314,7 +315,6 @@ func processWith(ctx context.Context, i interface{}, l Lookuper, parentNoInit bo
isNilStructPtr = true
// Use an empty struct of the type so we can traverse.
ef = reflect.New(ef.Type().Elem()).Elem()

} else {
ef = ef.Elem()
}
Expand Down Expand Up @@ -351,7 +351,7 @@ func processWith(ctx context.Context, i interface{}, l Lookuper, parentNoInit bo
plu = PrefixLookuper(opts.Prefix, l)
}

if err := processWith(ctx, ef.Interface(), plu, opts.NoInit, fns...); err != nil {
if err := processWith(ctx, ef.Interface(), plu, shouldNotInit, fns...); err != nil {
return fmt.Errorf("%s: %w", tf.Name, err)
}

Expand Down
31 changes: 30 additions & 1 deletion envconfig_test.go
Expand Up @@ -1942,7 +1942,7 @@ func TestProcessWith(t *testing.T) {
lookuper: MapLookuper(nil),
},
{
name: "noinit/init_when_sub_sub_fields_unset",
name: "noinit/no_init_when_sub_sub_fields_unset",
input: &struct {
Lepton *Lepton `env:",noinit"`
}{},
Expand All @@ -1954,6 +1954,35 @@ func TestProcessWith(t *testing.T) {
},
lookuper: MapLookuper(nil),
},
{
name: "noinit/no_init_from_parent",
input: &struct {
Electron *Electron `env:"FIELD,noinit"`
}{},
exp: &struct {
Electron *Electron `env:"FIELD,noinit"`
}{
Electron: nil,
},
lookuper: MapLookuper(nil),
},
{
name: "noinit/no_init_when_decoder",
input: &struct {
Parent *struct {
Field url.URL
} `env:",noinit"`
}{},
exp: &struct {
Parent *struct {
Field url.URL
} `env:",noinit"`
}{
// Parent should be nil.
Parent: nil,
},
lookuper: MapLookuper(nil),
},
{
name: "noinit/init_when_sub_fields_set",
input: &struct {
Expand Down

0 comments on commit 20ad4b3

Please sign in to comment.