mirror of
https://github.com/spf13/viper
synced 2024-12-22 19:47:01 +00:00
feat: implement new finder using io/fs
Signed-off-by: Mark Sagi-Kazar <mark.sagikazar@gmail.com>
This commit is contained in:
parent
ce82267a11
commit
8e71595a4a
2 changed files with 165 additions and 0 deletions
65
fs.go
Normal file
65
fs.go
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
//go:build go1.16
|
||||||
|
// +build go1.16
|
||||||
|
|
||||||
|
package viper
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"io/fs"
|
||||||
|
"path/filepath"
|
||||||
|
)
|
||||||
|
|
||||||
|
type finder struct {
|
||||||
|
paths []string
|
||||||
|
fileNames []string
|
||||||
|
extensions []string
|
||||||
|
|
||||||
|
withoutExtension bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f finder) Find(fsys fs.FS) (string, error) {
|
||||||
|
for _, path := range f.paths {
|
||||||
|
for _, fileName := range f.fileNames {
|
||||||
|
for _, extension := range f.extensions {
|
||||||
|
filePath := filepath.Join(path, fileName+"."+extension)
|
||||||
|
|
||||||
|
ok, err := fileExists(fsys, filePath)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
if ok {
|
||||||
|
return filePath, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if f.withoutExtension {
|
||||||
|
filePath := filepath.Join(path, fileName)
|
||||||
|
|
||||||
|
ok, err := fileExists(fsys, filePath)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
if ok {
|
||||||
|
return filePath, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func fileExists(fsys fs.FS, filePath string) (bool, error) {
|
||||||
|
fileInfo, err := fs.Stat(fsys, filePath)
|
||||||
|
if err == nil {
|
||||||
|
return !fileInfo.IsDir(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if errors.Is(err, fs.ErrNotExist) {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return false, err
|
||||||
|
}
|
100
fs_test.go
Normal file
100
fs_test.go
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
//go:build go1.16
|
||||||
|
// +build go1.16
|
||||||
|
|
||||||
|
package viper
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/fs"
|
||||||
|
"testing"
|
||||||
|
"testing/fstest"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestFinder(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
fsys := fstest.MapFS{
|
||||||
|
"home/user/.config": &fstest.MapFile{},
|
||||||
|
"home/user/config.json": &fstest.MapFile{},
|
||||||
|
"home/user/config.yaml": &fstest.MapFile{},
|
||||||
|
"home/user/data.json": &fstest.MapFile{},
|
||||||
|
"etc/config/.config": &fstest.MapFile{},
|
||||||
|
"etc/config/a_random_file.txt": &fstest.MapFile{},
|
||||||
|
"etc/config/config.json": &fstest.MapFile{},
|
||||||
|
"etc/config/config.yaml": &fstest.MapFile{},
|
||||||
|
"etc/config/config.xml": &fstest.MapFile{},
|
||||||
|
}
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
fsys func() fs.FS
|
||||||
|
finder finder
|
||||||
|
result string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "find file",
|
||||||
|
fsys: func() fs.FS { return fsys },
|
||||||
|
finder: finder{
|
||||||
|
paths: []string{"etc/config"},
|
||||||
|
fileNames: []string{"config"},
|
||||||
|
extensions: []string{"json"},
|
||||||
|
},
|
||||||
|
result: "etc/config/config.json",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "file not found",
|
||||||
|
fsys: func() fs.FS { return fsys },
|
||||||
|
finder: finder{
|
||||||
|
paths: []string{"var/config"},
|
||||||
|
fileNames: []string{"config"},
|
||||||
|
extensions: []string{"json"},
|
||||||
|
},
|
||||||
|
result: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "empty search params",
|
||||||
|
fsys: func() fs.FS { return fsys },
|
||||||
|
finder: finder{},
|
||||||
|
result: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "precedence",
|
||||||
|
fsys: func() fs.FS { return fsys },
|
||||||
|
finder: finder{
|
||||||
|
paths: []string{"var/config", "home/user", "etc/config"},
|
||||||
|
fileNames: []string{"aconfig", "config"},
|
||||||
|
extensions: []string{"zml", "xml", "json"},
|
||||||
|
},
|
||||||
|
result: "home/user/config.json",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "without extension",
|
||||||
|
fsys: func() fs.FS { return fsys },
|
||||||
|
finder: finder{
|
||||||
|
paths: []string{"var/config", "home/user", "etc/config"},
|
||||||
|
fileNames: []string{".config"},
|
||||||
|
extensions: []string{"zml", "xml", "json"},
|
||||||
|
|
||||||
|
withoutExtension: true,
|
||||||
|
},
|
||||||
|
result: "home/user/.config",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, testCase := range testCases {
|
||||||
|
testCase := testCase
|
||||||
|
|
||||||
|
t.Run(testCase.name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
fsys := testCase.fsys()
|
||||||
|
|
||||||
|
result, err := testCase.finder.Find(fsys)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
assert.Equal(t, testCase.result, result)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue