From ab3a50c0ce2020028f8cb515c62fc4d2d97a8996 Mon Sep 17 00:00:00 2001 From: Mark Sagi-Kazar Date: Fri, 15 Dec 2023 13:31:38 +0100 Subject: [PATCH] fix!: hide struct binding behind a feature flag Signed-off-by: Mark Sagi-Kazar --- .github/workflows/ci.yaml | 8 +++--- internal/features/bind_struct.go | 5 ++++ internal/features/bind_struct_default.go | 5 ++++ viper.go | 33 +++++++++++++++++------- viper_test.go | 5 ++++ 5 files changed, 42 insertions(+), 14 deletions(-) create mode 100644 internal/features/bind_struct.go create mode 100644 internal/features/bind_struct_default.go diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index e641b0465..74ef9514b 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -26,7 +26,7 @@ jobs: - name: Set up Go uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 with: - go-version: '1.21' + go-version: "1.21" - name: Build run: go build . @@ -44,8 +44,8 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, macos-latest, windows-latest] - go: ['1.19', '1.20', '1.21'] - tags: ['', 'finder'] + go: ["1.19", "1.20", "1.21"] + tags: ["", "finder", "viper_bind_struct"] steps: - name: Checkout repository @@ -75,7 +75,7 @@ jobs: - name: Set up Go uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 with: - go-version: '1.21' + go-version: "1.21" - name: Lint uses: golangci/golangci-lint-action@3a919529898de77ec3da873e3063ca4b10e7f5cc # v3.7.0 diff --git a/internal/features/bind_struct.go b/internal/features/bind_struct.go new file mode 100644 index 000000000..89302c216 --- /dev/null +++ b/internal/features/bind_struct.go @@ -0,0 +1,5 @@ +//go:build viper_bind_struct + +package features + +const BindStruct = true diff --git a/internal/features/bind_struct_default.go b/internal/features/bind_struct_default.go new file mode 100644 index 000000000..edfaf73b6 --- /dev/null +++ b/internal/features/bind_struct_default.go @@ -0,0 +1,5 @@ +//go:build !viper_bind_struct + +package features + +const BindStruct = false diff --git a/viper.go b/viper.go index 122280b11..20eb4da17 100644 --- a/viper.go +++ b/viper.go @@ -48,6 +48,7 @@ import ( "github.com/spf13/viper/internal/encoding/json" "github.com/spf13/viper/internal/encoding/toml" "github.com/spf13/viper/internal/encoding/yaml" + "github.com/spf13/viper/internal/features" ) // ConfigMarshalError happens when failing to marshal the configuration. @@ -1114,14 +1115,20 @@ func Unmarshal(rawVal any, opts ...DecoderConfigOption) error { } func (v *Viper) Unmarshal(rawVal any, opts ...DecoderConfigOption) error { - // TODO: make this optional? - structKeys, err := v.decodeStructKeys(rawVal, opts...) - if err != nil { - return err + keys := v.AllKeys() + + if features.BindStruct { + // TODO: make this optional? + structKeys, err := v.decodeStructKeys(rawVal, opts...) + if err != nil { + return err + } + + keys = append(keys, structKeys...) } // TODO: struct keys should be enough? - return decode(v.getSettings(append(v.AllKeys(), structKeys...)), defaultDecoderConfig(rawVal, opts...)) + return decode(v.getSettings(keys), defaultDecoderConfig(rawVal, opts...)) } func (v *Viper) decodeStructKeys(input any, opts ...DecoderConfigOption) ([]string, error) { @@ -1179,14 +1186,20 @@ func (v *Viper) UnmarshalExact(rawVal any, opts ...DecoderConfigOption) error { config := defaultDecoderConfig(rawVal, opts...) config.ErrorUnused = true - // TODO: make this optional? - structKeys, err := v.decodeStructKeys(rawVal, opts...) - if err != nil { - return err + keys := v.AllKeys() + + if features.BindStruct { + // TODO: make this optional? + structKeys, err := v.decodeStructKeys(rawVal, opts...) + if err != nil { + return err + } + + keys = append(keys, structKeys...) } // TODO: struct keys should be enough? - return decode(v.getSettings(append(v.AllKeys(), structKeys...)), config) + return decode(v.getSettings(keys), config) } // BindPFlags binds a full flag set to the configuration, using each flag's long diff --git a/viper_test.go b/viper_test.go index 4dc52ac27..0b1f40741 100644 --- a/viper_test.go +++ b/viper_test.go @@ -28,6 +28,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/spf13/viper/internal/features" "github.com/spf13/viper/internal/testutil" ) @@ -956,6 +957,10 @@ func TestUnmarshalWithDecoderOptions(t *testing.T) { } func TestUnmarshalWithAutomaticEnv(t *testing.T) { + if !features.BindStruct { + t.Skip("binding struct is not enabled") + } + t.Setenv("PORT", "1313") t.Setenv("NAME", "Steve") t.Setenv("DURATION", "1s1ms")