mirror of https://github.com/spf13/viper.git
feat: add finder
Signed-off-by: Mark Sagi-Kazar <mark.sagikazar@gmail.com>
This commit is contained in:
parent
272344e426
commit
f452b09dd9
|
@ -45,7 +45,7 @@ jobs:
|
||||||
matrix:
|
matrix:
|
||||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||||
go: ["1.21", "1.22"]
|
go: ["1.21", "1.22"]
|
||||||
tags: ["", "finder", "viper_bind_struct"]
|
tags: ["", "viper_finder", "viper_bind_struct"]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
|
|
2
file.go
2
file.go
|
@ -1,4 +1,4 @@
|
||||||
//go:build !finder
|
//go:build !viper_finder
|
||||||
|
|
||||||
package viper
|
package viper
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
//go:build finder
|
//go:build viper_finder
|
||||||
|
|
||||||
package viper
|
package viper
|
||||||
|
|
||||||
|
@ -11,6 +11,9 @@ import (
|
||||||
// Search all configPaths for any config file.
|
// Search all configPaths for any config file.
|
||||||
// Returns the first path that exists (and is a config file).
|
// Returns the first path that exists (and is a config file).
|
||||||
func (v *Viper) findConfigFile() (string, error) {
|
func (v *Viper) findConfigFile() (string, error) {
|
||||||
|
finder := v.finder
|
||||||
|
|
||||||
|
if finder == nil {
|
||||||
var names []string
|
var names []string
|
||||||
|
|
||||||
if v.configType != "" {
|
if v.configType != "" {
|
||||||
|
@ -19,11 +22,12 @@ func (v *Viper) findConfigFile() (string, error) {
|
||||||
names = locafero.NameWithExtensions(v.configName, SupportedExts...)
|
names = locafero.NameWithExtensions(v.configName, SupportedExts...)
|
||||||
}
|
}
|
||||||
|
|
||||||
finder := locafero.Finder{
|
finder = locafero.Finder{
|
||||||
Paths: v.configPaths,
|
Paths: v.configPaths,
|
||||||
Names: names,
|
Names: names,
|
||||||
Type: locafero.FileTypeFile,
|
Type: locafero.FileTypeFile,
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
results, err := finder.Find(v.fs)
|
results, err := finder.Find(v.fs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
package viper
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"github.com/spf13/afero"
|
||||||
|
)
|
||||||
|
|
||||||
|
// WithFinder sets a custom [Finder].
|
||||||
|
func WithFinder(f Finder) Option {
|
||||||
|
return optionFunc(func(v *Viper) {
|
||||||
|
v.finder = f
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finder looks for files and directories in an [afero.Fs] filesystem.
|
||||||
|
type Finder interface {
|
||||||
|
Find(fsys afero.Fs) ([]string, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finders combines multiple finders into one.
|
||||||
|
func Finders(finders ...Finder) Finder {
|
||||||
|
return &CombinedFinder{finders: finders}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CombinedFinder is a Finder that combines multiple finders.
|
||||||
|
type CombinedFinder struct {
|
||||||
|
finders []Finder
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find implements the [Finder] interface.
|
||||||
|
func (c *CombinedFinder) Find(fsys afero.Fs) ([]string, error) {
|
||||||
|
var results []string
|
||||||
|
var errs []error
|
||||||
|
|
||||||
|
for _, finder := range c.finders {
|
||||||
|
r, err := finder.Find(fsys)
|
||||||
|
if err != nil {
|
||||||
|
errs = append(errs, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
results = append(results, r...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return results, errors.Join(errs...)
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
package viper
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/spf13/afero"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
type finderStub struct {
|
||||||
|
results []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f finderStub) Find(_ afero.Fs) ([]string, error) {
|
||||||
|
return f.results, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFinders(t *testing.T) {
|
||||||
|
finder := Finders(
|
||||||
|
finderStub{
|
||||||
|
results: []string{
|
||||||
|
"/home/user/.viper.yaml",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
finderStub{
|
||||||
|
results: []string{
|
||||||
|
"/etc/viper/config.yaml",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
results, err := finder.Find(afero.NewMemMapFs())
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
expected := []string{
|
||||||
|
"/home/user/.viper.yaml",
|
||||||
|
"/etc/viper/config.yaml",
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.Equal(t, expected, results)
|
||||||
|
}
|
14
viper.go
14
viper.go
|
@ -158,6 +158,8 @@ type Viper struct {
|
||||||
// The filesystem to read config from.
|
// The filesystem to read config from.
|
||||||
fs afero.Fs
|
fs afero.Fs
|
||||||
|
|
||||||
|
finder Finder
|
||||||
|
|
||||||
// A set of remote providers to search for the configuration
|
// A set of remote providers to search for the configuration
|
||||||
remoteProviders []*defaultRemoteProvider
|
remoteProviders []*defaultRemoteProvider
|
||||||
|
|
||||||
|
@ -506,6 +508,12 @@ func (v *Viper) ConfigFileUsed() string { return v.configFile }
|
||||||
func AddConfigPath(in string) { v.AddConfigPath(in) }
|
func AddConfigPath(in string) { v.AddConfigPath(in) }
|
||||||
|
|
||||||
func (v *Viper) AddConfigPath(in string) {
|
func (v *Viper) AddConfigPath(in string) {
|
||||||
|
if v.finder != nil {
|
||||||
|
v.logger.Warn("call to AddConfigPath is ineffective when a custom finder is configured")
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if in != "" {
|
if in != "" {
|
||||||
absin := absPathify(v.logger, in)
|
absin := absPathify(v.logger, in)
|
||||||
|
|
||||||
|
@ -1955,6 +1963,12 @@ func (v *Viper) SetFs(fs afero.Fs) {
|
||||||
func SetConfigName(in string) { v.SetConfigName(in) }
|
func SetConfigName(in string) { v.SetConfigName(in) }
|
||||||
|
|
||||||
func (v *Viper) SetConfigName(in string) {
|
func (v *Viper) SetConfigName(in string) {
|
||||||
|
if v.finder != nil {
|
||||||
|
v.logger.Warn("call to SetConfigName is ineffective when a custom finder is configured")
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if in != "" {
|
if in != "" {
|
||||||
v.configName = in
|
v.configName = in
|
||||||
v.configFile = ""
|
v.configFile = ""
|
||||||
|
|
Loading…
Reference in New Issue