summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/spf13
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/spf13')
-rw-r--r--vendor/github.com/spf13/afero/afero.go2
-rw-r--r--vendor/github.com/spf13/afero/basepath.go1
-rw-r--r--vendor/github.com/spf13/afero/copyOnWriteFs.go9
-rw-r--r--vendor/github.com/spf13/afero/ioutil.go11
-rw-r--r--vendor/github.com/spf13/afero/mem/file.go7
-rw-r--r--vendor/github.com/spf13/afero/memmap.go21
-rw-r--r--vendor/github.com/spf13/afero/regexpfs.go1
-rw-r--r--vendor/github.com/spf13/afero/symlink.go6
-rw-r--r--vendor/github.com/spf13/afero/unionFile.go7
-rw-r--r--vendor/github.com/spf13/afero/util.go7
-rw-r--r--vendor/github.com/spf13/cast/README.md12
-rw-r--r--vendor/github.com/spf13/cast/caste.go32
-rw-r--r--vendor/github.com/spf13/viper/.golangci.yaml8
-rw-r--r--vendor/github.com/spf13/viper/Makefile4
-rw-r--r--vendor/github.com/spf13/viper/README.md3
-rw-r--r--vendor/github.com/spf13/viper/util.go5
-rw-r--r--vendor/github.com/spf13/viper/viper.go61
17 files changed, 146 insertions, 51 deletions
diff --git a/vendor/github.com/spf13/afero/afero.go b/vendor/github.com/spf13/afero/afero.go
index 199480cd..39f65852 100644
--- a/vendor/github.com/spf13/afero/afero.go
+++ b/vendor/github.com/spf13/afero/afero.go
@@ -97,7 +97,7 @@ type Fs interface {
// Chown changes the uid and gid of the named file.
Chown(name string, uid, gid int) error
- //Chtimes changes the access and modification times of the named file
+ // Chtimes changes the access and modification times of the named file
Chtimes(name string, atime time.Time, mtime time.Time) error
}
diff --git a/vendor/github.com/spf13/afero/basepath.go b/vendor/github.com/spf13/afero/basepath.go
index 70a1d916..2e72793a 100644
--- a/vendor/github.com/spf13/afero/basepath.go
+++ b/vendor/github.com/spf13/afero/basepath.go
@@ -40,7 +40,6 @@ func (f *BasePathFile) Name() string {
func (f *BasePathFile) ReadDir(n int) ([]fs.DirEntry, error) {
if rdf, ok := f.File.(fs.ReadDirFile); ok {
return rdf.ReadDir(n)
-
}
return readDirFile{f.File}.ReadDir(n)
}
diff --git a/vendor/github.com/spf13/afero/copyOnWriteFs.go b/vendor/github.com/spf13/afero/copyOnWriteFs.go
index 6ff8f309..184d6dd7 100644
--- a/vendor/github.com/spf13/afero/copyOnWriteFs.go
+++ b/vendor/github.com/spf13/afero/copyOnWriteFs.go
@@ -223,7 +223,7 @@ func (u *CopyOnWriteFs) OpenFile(name string, flag int, perm os.FileMode) (File,
return nil, err
}
if isaDir {
- if err = u.layer.MkdirAll(dir, 0777); err != nil {
+ if err = u.layer.MkdirAll(dir, 0o777); err != nil {
return nil, err
}
return u.layer.OpenFile(name, flag, perm)
@@ -247,8 +247,9 @@ func (u *CopyOnWriteFs) OpenFile(name string, flag int, perm os.FileMode) (File,
// This function handles the 9 different possibilities caused
// by the union which are the intersection of the following...
-// layer: doesn't exist, exists as a file, and exists as a directory
-// base: doesn't exist, exists as a file, and exists as a directory
+//
+// layer: doesn't exist, exists as a file, and exists as a directory
+// base: doesn't exist, exists as a file, and exists as a directory
func (u *CopyOnWriteFs) Open(name string) (File, error) {
// Since the overlay overrides the base we check that first
b, err := u.isBaseFile(name)
@@ -322,5 +323,5 @@ func (u *CopyOnWriteFs) MkdirAll(name string, perm os.FileMode) error {
}
func (u *CopyOnWriteFs) Create(name string) (File, error) {
- return u.OpenFile(name, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0666)
+ return u.OpenFile(name, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0o666)
}
diff --git a/vendor/github.com/spf13/afero/ioutil.go b/vendor/github.com/spf13/afero/ioutil.go
index 386c9cdc..fa6abe1e 100644
--- a/vendor/github.com/spf13/afero/ioutil.go
+++ b/vendor/github.com/spf13/afero/ioutil.go
@@ -141,8 +141,10 @@ func WriteFile(fs Fs, filename string, data []byte, perm os.FileMode) error {
// We generate random temporary file names so that there's a good
// chance the file doesn't exist yet - keeps the number of tries in
// TempFile to a minimum.
-var randNum uint32
-var randmu sync.Mutex
+var (
+ randNum uint32
+ randmu sync.Mutex
+)
func reseed() uint32 {
return uint32(time.Now().UnixNano() + int64(os.Getpid()))
@@ -190,7 +192,7 @@ func TempFile(fs Fs, dir, pattern string) (f File, err error) {
nconflict := 0
for i := 0; i < 10000; i++ {
name := filepath.Join(dir, prefix+nextRandom()+suffix)
- f, err = fs.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600)
+ f, err = fs.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0o600)
if os.IsExist(err) {
if nconflict++; nconflict > 10 {
randmu.Lock()
@@ -214,6 +216,7 @@ func TempFile(fs Fs, dir, pattern string) (f File, err error) {
func (a Afero) TempDir(dir, prefix string) (name string, err error) {
return TempDir(a.Fs, dir, prefix)
}
+
func TempDir(fs Fs, dir, prefix string) (name string, err error) {
if dir == "" {
dir = os.TempDir()
@@ -222,7 +225,7 @@ func TempDir(fs Fs, dir, prefix string) (name string, err error) {
nconflict := 0
for i := 0; i < 10000; i++ {
try := filepath.Join(dir, prefix+nextRandom())
- err = fs.Mkdir(try, 0700)
+ err = fs.Mkdir(try, 0o700)
if os.IsExist(err) {
if nconflict++; nconflict > 10 {
randmu.Lock()
diff --git a/vendor/github.com/spf13/afero/mem/file.go b/vendor/github.com/spf13/afero/mem/file.go
index 3cf4693b..62fe4498 100644
--- a/vendor/github.com/spf13/afero/mem/file.go
+++ b/vendor/github.com/spf13/afero/mem/file.go
@@ -245,7 +245,7 @@ func (f *File) Truncate(size int64) error {
defer f.fileData.Unlock()
if size > int64(len(f.fileData.data)) {
diff := size - int64(len(f.fileData.data))
- f.fileData.data = append(f.fileData.data, bytes.Repeat([]byte{00}, int(diff))...)
+ f.fileData.data = append(f.fileData.data, bytes.Repeat([]byte{0o0}, int(diff))...)
} else {
f.fileData.data = f.fileData.data[0:size]
}
@@ -285,7 +285,7 @@ func (f *File) Write(b []byte) (n int, err error) {
tail = f.fileData.data[n+int(cur):]
}
if diff > 0 {
- f.fileData.data = append(f.fileData.data, append(bytes.Repeat([]byte{00}, int(diff)), b...)...)
+ f.fileData.data = append(f.fileData.data, append(bytes.Repeat([]byte{0o0}, int(diff)), b...)...)
f.fileData.data = append(f.fileData.data, tail...)
} else {
f.fileData.data = append(f.fileData.data[:cur], b...)
@@ -321,16 +321,19 @@ func (s *FileInfo) Name() string {
s.Unlock()
return name
}
+
func (s *FileInfo) Mode() os.FileMode {
s.Lock()
defer s.Unlock()
return s.mode
}
+
func (s *FileInfo) ModTime() time.Time {
s.Lock()
defer s.Unlock()
return s.modtime
}
+
func (s *FileInfo) IsDir() bool {
s.Lock()
defer s.Unlock()
diff --git a/vendor/github.com/spf13/afero/memmap.go b/vendor/github.com/spf13/afero/memmap.go
index d06975e7..e6b7d70b 100644
--- a/vendor/github.com/spf13/afero/memmap.go
+++ b/vendor/github.com/spf13/afero/memmap.go
@@ -15,6 +15,7 @@ package afero
import (
"fmt"
+ "io"
"log"
"os"
"path/filepath"
@@ -43,7 +44,7 @@ func (m *MemMapFs) getData() map[string]*mem.FileData {
// Root should always exist, right?
// TODO: what about windows?
root := mem.CreateDir(FilePathSeparator)
- mem.SetMode(root, os.ModeDir|0755)
+ mem.SetMode(root, os.ModeDir|0o755)
m.data[FilePathSeparator] = root
})
return m.data
@@ -96,12 +97,12 @@ func (m *MemMapFs) registerWithParent(f *mem.FileData, perm os.FileMode) {
pdir := filepath.Dir(filepath.Clean(f.Name()))
err := m.lockfreeMkdir(pdir, perm)
if err != nil {
- //log.Println("Mkdir error:", err)
+ // log.Println("Mkdir error:", err)
return
}
parent, err = m.lockfreeOpen(pdir)
if err != nil {
- //log.Println("Open after Mkdir error:", err)
+ // log.Println("Open after Mkdir error:", err)
return
}
}
@@ -237,7 +238,7 @@ func (m *MemMapFs) OpenFile(name string, flag int, perm os.FileMode) (File, erro
file = mem.NewReadOnlyFileHandle(file.(*mem.File).Data())
}
if flag&os.O_APPEND > 0 {
- _, err = file.Seek(0, os.SEEK_END)
+ _, err = file.Seek(0, io.SeekEnd)
if err != nil {
file.Close()
return nil, err
@@ -319,6 +320,18 @@ func (m *MemMapFs) Rename(oldname, newname string) error {
} else {
return &os.PathError{Op: "rename", Path: oldname, Err: ErrFileNotFound}
}
+
+ for p, fileData := range m.getData() {
+ if strings.HasPrefix(p, oldname+FilePathSeparator) {
+ m.mu.RUnlock()
+ m.mu.Lock()
+ delete(m.getData(), p)
+ p := strings.Replace(p, oldname, newname, 1)
+ m.getData()[p] = fileData
+ m.mu.Unlock()
+ m.mu.RLock()
+ }
+ }
return nil
}
diff --git a/vendor/github.com/spf13/afero/regexpfs.go b/vendor/github.com/spf13/afero/regexpfs.go
index ac359c62..218f3b23 100644
--- a/vendor/github.com/spf13/afero/regexpfs.go
+++ b/vendor/github.com/spf13/afero/regexpfs.go
@@ -10,7 +10,6 @@ import (
// The RegexpFs filters files (not directories) by regular expression. Only
// files matching the given regexp will be allowed, all others get a ENOENT error (
// "No such file or directory").
-//
type RegexpFs struct {
re *regexp.Regexp
source Fs
diff --git a/vendor/github.com/spf13/afero/symlink.go b/vendor/github.com/spf13/afero/symlink.go
index d1c6ea53..aa6ae125 100644
--- a/vendor/github.com/spf13/afero/symlink.go
+++ b/vendor/github.com/spf13/afero/symlink.go
@@ -21,9 +21,9 @@ import (
// filesystems saying so.
// It indicates support for 3 symlink related interfaces that implement the
// behaviors of the os methods:
-// - Lstat
-// - Symlink, and
-// - Readlink
+// - Lstat
+// - Symlink, and
+// - Readlink
type Symlinker interface {
Lstater
Linker
diff --git a/vendor/github.com/spf13/afero/unionFile.go b/vendor/github.com/spf13/afero/unionFile.go
index 333d367f..62dd6c93 100644
--- a/vendor/github.com/spf13/afero/unionFile.go
+++ b/vendor/github.com/spf13/afero/unionFile.go
@@ -47,7 +47,7 @@ func (f *UnionFile) Read(s []byte) (int, error) {
if (err == nil || err == io.EOF) && f.Base != nil {
// advance the file position also in the base file, the next
// call may be a write at this position (or a seek with SEEK_CUR)
- if _, seekErr := f.Base.Seek(int64(n), os.SEEK_CUR); seekErr != nil {
+ if _, seekErr := f.Base.Seek(int64(n), io.SeekCurrent); seekErr != nil {
// only overwrite err in case the seek fails: we need to
// report an eventual io.EOF to the caller
err = seekErr
@@ -130,7 +130,7 @@ func (f *UnionFile) Name() string {
type DirsMerger func(lofi, bofi []os.FileInfo) ([]os.FileInfo, error)
var defaultUnionMergeDirsFn = func(lofi, bofi []os.FileInfo) ([]os.FileInfo, error) {
- var files = make(map[string]os.FileInfo)
+ files := make(map[string]os.FileInfo)
for _, fi := range lofi {
files[fi.Name()] = fi
@@ -151,7 +151,6 @@ var defaultUnionMergeDirsFn = func(lofi, bofi []os.FileInfo) ([]os.FileInfo, err
}
return rfi, nil
-
}
// Readdir will weave the two directories together and
@@ -275,7 +274,7 @@ func copyFile(base Fs, layer Fs, name string, bfh File) error {
return err
}
if !exists {
- err = layer.MkdirAll(filepath.Dir(name), 0777) // FIXME?
+ err = layer.MkdirAll(filepath.Dir(name), 0o777) // FIXME?
if err != nil {
return err
}
diff --git a/vendor/github.com/spf13/afero/util.go b/vendor/github.com/spf13/afero/util.go
index cb7de23f..9e4cba27 100644
--- a/vendor/github.com/spf13/afero/util.go
+++ b/vendor/github.com/spf13/afero/util.go
@@ -43,7 +43,7 @@ func WriteReader(fs Fs, path string, r io.Reader) (err error) {
ospath := filepath.FromSlash(dir)
if ospath != "" {
- err = fs.MkdirAll(ospath, 0777) // rwx, rw, r
+ err = fs.MkdirAll(ospath, 0o777) // rwx, rw, r
if err != nil {
if err != os.ErrExist {
return err
@@ -71,7 +71,7 @@ func SafeWriteReader(fs Fs, path string, r io.Reader) (err error) {
ospath := filepath.FromSlash(dir)
if ospath != "" {
- err = fs.MkdirAll(ospath, 0777) // rwx, rw, r
+ err = fs.MkdirAll(ospath, 0o777) // rwx, rw, r
if err != nil {
return
}
@@ -124,7 +124,7 @@ func GetTempDir(fs Fs, subPath string) string {
return addSlash(dir)
}
- err := fs.MkdirAll(dir, 0777)
+ err := fs.MkdirAll(dir, 0o777)
if err != nil {
panic(err)
}
@@ -197,7 +197,6 @@ func FileContainsAnyBytes(fs Fs, filename string, subslices [][]byte) (bool, err
// readerContains reports whether any of the subslices is within r.
func readerContainsAny(r io.Reader, subslices ...[]byte) bool {
-
if r == nil || len(subslices) == 0 {
return false
}
diff --git a/vendor/github.com/spf13/cast/README.md b/vendor/github.com/spf13/cast/README.md
index 120a5734..58141f02 100644
--- a/vendor/github.com/spf13/cast/README.md
+++ b/vendor/github.com/spf13/cast/README.md
@@ -1,7 +1,8 @@
-cast
-====
-[![GoDoc](https://godoc.org/github.com/spf13/cast?status.svg)](https://godoc.org/github.com/spf13/cast)
-[![Build Status](https://github.com/spf13/cast/actions/workflows/go.yml/badge.svg)](https://github.com/spf13/cast/actions/workflows/go.yml)
+# cast
+
+[![Build Status](https://github.com/spf13/cast/actions/workflows/ci.yml/badge.svg)](https://github.com/spf13/cast/actions/workflows/ci.yml)
+[![PkgGoDev](https://pkg.go.dev/badge/mod/github.com/spf13/cast)](https://pkg.go.dev/mod/github.com/spf13/cast)
+![Go Version](https://img.shields.io/badge/go%20version-%3E=1.16-61CFDD.svg?style=flat-square)
[![Go Report Card](https://goreportcard.com/badge/github.com/spf13/cast)](https://goreportcard.com/report/github.com/spf13/cast)
Easy and safe casting from one type to another in Go
@@ -17,7 +18,7 @@ interface into a bool, etc. Cast does this intelligently when an obvious
conversion is possible. It doesn’t make any attempts to guess what you meant,
for example you can only convert a string to an int when it is a string
representation of an int such as “8”. Cast was developed for use in
-[Hugo](http://hugo.spf13.com), a website engine which uses YAML, TOML or JSON
+[Hugo](https://gohugo.io), a website engine which uses YAML, TOML or JSON
for meta data.
## Why use Cast?
@@ -72,4 +73,3 @@ the code for a complete set.
var eight interface{} = 8
cast.ToInt(eight) // 8
cast.ToInt(nil) // 0
-
diff --git a/vendor/github.com/spf13/cast/caste.go b/vendor/github.com/spf13/cast/caste.go
index 514d759b..d49bbf83 100644
--- a/vendor/github.com/spf13/cast/caste.go
+++ b/vendor/github.com/spf13/cast/caste.go
@@ -98,10 +98,31 @@ func ToBoolE(i interface{}) (bool, error) {
case nil:
return false, nil
case int:
- if i.(int) != 0 {
- return true, nil
- }
- return false, nil
+ return b != 0, nil
+ case int64:
+ return b != 0, nil
+ case int32:
+ return b != 0, nil
+ case int16:
+ return b != 0, nil
+ case int8:
+ return b != 0, nil
+ case uint:
+ return b != 0, nil
+ case uint64:
+ return b != 0, nil
+ case uint32:
+ return b != 0, nil
+ case uint16:
+ return b != 0, nil
+ case uint8:
+ return b != 0, nil
+ case float64:
+ return b != 0, nil
+ case float32:
+ return b != 0, nil
+ case time.Duration:
+ return b != 0, nil
case string:
return strconv.ParseBool(i.(string))
case json.Number:
@@ -1385,6 +1406,8 @@ func (f timeFormat) hasTimezone() bool {
var (
timeFormats = []timeFormat{
+ // Keep common formats at the top.
+ {"2006-01-02", timeFormatNoTimezone},
{time.RFC3339, timeFormatNumericTimezone},
{"2006-01-02T15:04:05", timeFormatNoTimezone}, // iso8601 without timezone
{time.RFC1123Z, timeFormatNumericTimezone},
@@ -1400,7 +1423,6 @@ var (
{time.UnixDate, timeFormatNamedTimezone},
{time.RubyDate, timeFormatNumericTimezone},
{"2006-01-02 15:04:05Z07:00", timeFormatNumericTimezone},
- {"2006-01-02", timeFormatNoTimezone},
{"02 Jan 2006", timeFormatNoTimezone},
{"2006-01-02 15:04:05 -07:00", timeFormatNumericTimezone},
{"2006-01-02 15:04:05 -0700", timeFormatNumericTimezone},
diff --git a/vendor/github.com/spf13/viper/.golangci.yaml b/vendor/github.com/spf13/viper/.golangci.yaml
index 16e03965..acd9eeba 100644
--- a/vendor/github.com/spf13/viper/.golangci.yaml
+++ b/vendor/github.com/spf13/viper/.golangci.yaml
@@ -16,7 +16,6 @@ linters:
disable-all: true
enable:
- bodyclose
- - deadcode
- dogsled
- dupl
- durationcheck
@@ -43,14 +42,12 @@ linters:
- rowserrcheck
- sqlclosecheck
- staticcheck
- - structcheck
- stylecheck
- tparallel
- typecheck
- unconvert
- unparam
- unused
- - varcheck
- wastedassign
- whitespace
@@ -83,6 +80,11 @@ linters:
# - goheader
# - gomodguard
+ # deprecated
+ # - deadcode
+ # - structcheck
+ # - varcheck
+
# don't enable:
# - asciicheck
# - funlen
diff --git a/vendor/github.com/spf13/viper/Makefile b/vendor/github.com/spf13/viper/Makefile
index 3f4234d3..e8d3baaa 100644
--- a/vendor/github.com/spf13/viper/Makefile
+++ b/vendor/github.com/spf13/viper/Makefile
@@ -15,8 +15,8 @@ TEST_FORMAT = short-verbose
endif
# Dependency versions
-GOTESTSUM_VERSION = 1.8.0
-GOLANGCI_VERSION = 1.50.1
+GOTESTSUM_VERSION = 1.9.0
+GOLANGCI_VERSION = 1.52.2
# Add the ability to override some variables
# Use with care
diff --git a/vendor/github.com/spf13/viper/README.md b/vendor/github.com/spf13/viper/README.md
index cd392905..4184d2a1 100644
--- a/vendor/github.com/spf13/viper/README.md
+++ b/vendor/github.com/spf13/viper/README.md
@@ -27,6 +27,9 @@ Many Go projects are built using Viper including:
* [doctl](https://github.com/digitalocean/doctl)
* [Clairctl](https://github.com/jgsqware/clairctl)
* [Mercure](https://mercure.rocks)
+* [Meshery](https://github.com/meshery/meshery)
+* [Bearer](https://github.com/bearer/bearer)
+* [Coder](https://github.com/coder/coder)
## Install
diff --git a/vendor/github.com/spf13/viper/util.go b/vendor/github.com/spf13/viper/util.go
index 64e65750..95009a14 100644
--- a/vendor/github.com/spf13/viper/util.go
+++ b/vendor/github.com/spf13/viper/util.go
@@ -31,6 +31,11 @@ func (pe ConfigParseError) Error() string {
return fmt.Sprintf("While parsing config: %s", pe.err.Error())
}
+// Unwrap returns the wrapped error.
+func (pe ConfigParseError) Unwrap() error {
+ return pe.err
+}
+
// toCaseInsensitiveValue checks if the value is a map;
// if so, create a copy and lower-case the keys recursively.
func toCaseInsensitiveValue(value interface{}) interface{} {
diff --git a/vendor/github.com/spf13/viper/viper.go b/vendor/github.com/spf13/viper/viper.go
index 06610fc5..7fb1e191 100644
--- a/vendor/github.com/spf13/viper/viper.go
+++ b/vendor/github.com/spf13/viper/viper.go
@@ -25,7 +25,6 @@ import (
"errors"
"fmt"
"io"
- "log"
"os"
"path/filepath"
"reflect"
@@ -206,6 +205,7 @@ type Viper struct {
envKeyReplacer StringReplacer
allowEmptyEnv bool
+ parents []string
config map[string]interface{}
override map[string]interface{}
defaults map[string]interface{}
@@ -232,6 +232,7 @@ func New() *Viper {
v.configPermissions = os.FileMode(0o644)
v.fs = afero.NewOsFs()
v.config = make(map[string]interface{})
+ v.parents = []string{}
v.override = make(map[string]interface{})
v.defaults = make(map[string]interface{})
v.kvstore = make(map[string]interface{})
@@ -439,13 +440,14 @@ func (v *Viper) WatchConfig() {
go func() {
watcher, err := newWatcher()
if err != nil {
- log.Fatal(err)
+ v.logger.Error(fmt.Sprintf("failed to create watcher: %s", err))
+ os.Exit(1)
}
defer watcher.Close()
// we have to watch the entire directory to pick up renames/atomic saves in a cross-platform way
filename, err := v.getConfigFile()
if err != nil {
- log.Printf("error: %v\n", err)
+ v.logger.Error(fmt.Sprintf("get config file: %s", err))
initWG.Done()
return
}
@@ -474,7 +476,7 @@ func (v *Viper) WatchConfig() {
realConfigFile = currentConfigFile
err := v.ReadInConfig()
if err != nil {
- log.Printf("error reading config file: %v\n", err)
+ v.logger.Error(fmt.Sprintf("read config file: %s", err))
}
if v.onConfigChange != nil {
v.onConfigChange(event)
@@ -486,7 +488,7 @@ func (v *Viper) WatchConfig() {
case err, ok := <-watcher.Errors:
if ok { // 'Errors' channel is not closed
- log.Printf("watcher error: %v\n", err)
+ v.logger.Error(fmt.Sprintf("watcher error: %s", err))
}
eventsWG.Done()
return
@@ -928,6 +930,8 @@ func (v *Viper) Get(key string) interface{} {
return cast.ToStringSlice(val)
case []int:
return cast.ToIntSlice(val)
+ case []time.Duration:
+ return cast.ToDurationSlice(val)
}
}
@@ -946,6 +950,10 @@ func (v *Viper) Sub(key string) *Viper {
}
if reflect.TypeOf(data).Kind() == reflect.Map {
+ subv.parents = append(v.parents, strings.ToLower(key))
+ subv.automaticEnvApplied = v.automaticEnvApplied
+ subv.envPrefix = v.envPrefix
+ subv.envKeyReplacer = v.envKeyReplacer
subv.config = cast.ToStringMap(data)
return subv
}
@@ -1099,7 +1107,7 @@ func (v *Viper) Unmarshal(rawVal interface{}, opts ...DecoderConfigOption) error
return decode(v.AllSettings(), defaultDecoderConfig(rawVal, opts...))
}
-// defaultDecoderConfig returns default mapsstructure.DecoderConfig with suppot
+// defaultDecoderConfig returns default mapstructure.DecoderConfig with support
// of time.Duration values & string slices
func defaultDecoderConfig(output interface{}, opts ...DecoderConfigOption) *mapstructure.DecoderConfig {
c := &mapstructure.DecoderConfig{
@@ -1274,8 +1282,15 @@ func (v *Viper) find(lcaseKey string, flagDefault bool) interface{} {
s = strings.TrimSuffix(s, "]")
res, _ := readAsCSV(s)
return cast.ToIntSlice(res)
+ case "durationSlice":
+ s := strings.TrimPrefix(flag.ValueString(), "[")
+ s = strings.TrimSuffix(s, "]")
+ slice := strings.Split(s, ",")
+ return cast.ToDurationSlice(slice)
case "stringToString":
return stringToStringConv(flag.ValueString())
+ case "stringToInt":
+ return stringToIntConv(flag.ValueString())
default:
return flag.ValueString()
}
@@ -1286,9 +1301,10 @@ func (v *Viper) find(lcaseKey string, flagDefault bool) interface{} {
// Env override next
if v.automaticEnvApplied {
+ envKey := strings.Join(append(v.parents, lcaseKey), ".")
// even if it hasn't been registered, if automaticEnv is used,
// check any Get request
- if val, ok := v.getEnv(v.mergeWithEnvPrefix(lcaseKey)); ok {
+ if val, ok := v.getEnv(v.mergeWithEnvPrefix(envKey)); ok {
return val
}
if nested && v.isPathShadowedInAutoEnv(path) != "" {
@@ -1355,6 +1371,13 @@ func (v *Viper) find(lcaseKey string, flagDefault bool) interface{} {
return cast.ToIntSlice(res)
case "stringToString":
return stringToStringConv(flag.ValueString())
+ case "stringToInt":
+ return stringToIntConv(flag.ValueString())
+ case "durationSlice":
+ s := strings.TrimPrefix(flag.ValueString(), "[")
+ s = strings.TrimSuffix(s, "]")
+ slice := strings.Split(s, ",")
+ return cast.ToDurationSlice(slice)
default:
return flag.ValueString()
}
@@ -1398,6 +1421,30 @@ func stringToStringConv(val string) interface{} {
return out
}
+// mostly copied from pflag's implementation of this operation here https://github.com/spf13/pflag/blob/d5e0c0615acee7028e1e2740a11102313be88de1/string_to_int.go#L68
+// alterations are: errors are swallowed, map[string]interface{} is returned in order to enable cast.ToStringMap
+func stringToIntConv(val string) interface{} {
+ val = strings.Trim(val, "[]")
+ // An empty string would cause an empty map
+ if len(val) == 0 {
+ return map[string]interface{}{}
+ }
+ ss := strings.Split(val, ",")
+ out := make(map[string]interface{}, len(ss))
+ for _, pair := range ss {
+ kv := strings.SplitN(pair, "=", 2)
+ if len(kv) != 2 {
+ return nil
+ }
+ var err error
+ out[kv[0]], err = strconv.Atoi(kv[1])
+ if err != nil {
+ return nil
+ }
+ }
+ return out
+}
+
// IsSet checks to see if the key has been set in any of the data locations.
// IsSet is case-insensitive for a key.
func IsSet(key string) bool { return v.IsSet(key) }