bump dependencies

This commit is contained in:
raf 2025-02-08 16:32:45 +03:00
commit b7319e6bfc
No known key found for this signature in database
GPG key ID: EED98D11B85A2819
466 changed files with 17912 additions and 12742 deletions

12
vendor/github.com/spf13/afero/.editorconfig generated vendored Normal file
View file

@ -0,0 +1,12 @@
root = true
[*]
charset = utf-8
end_of_line = lf
indent_size = 4
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
[*.go]
indent_style = tab

18
vendor/github.com/spf13/afero/.golangci.yaml generated vendored Normal file
View file

@ -0,0 +1,18 @@
linters-settings:
gci:
sections:
- standard
- default
- prefix(github.com/spf13/afero)
linters:
disable-all: true
enable:
- gci
- gofmt
- gofumpt
- staticcheck
issues:
exclude-dirs:
- gcsfs/internal/stiface

View file

@ -12,7 +12,7 @@ types and methods. Afero has an exceptionally clean interface and simple design
without needless constructors or initialization methods.
Afero is also a library providing a base set of interoperable backend
filesystems that make it easy to work with afero while retaining all the power
filesystems that make it easy to work with, while retaining all the power
and benefit of the os and ioutil packages.
Afero provides significant improvements over using the os package alone, most

View file

@ -255,7 +255,6 @@ func (f fromIOFSFile) Readdir(count int) ([]os.FileInfo, error) {
ret := make([]os.FileInfo, len(entries))
for i := range entries {
ret[i], err = entries[i].Info()
if err != nil {
return nil, err
}

View file

@ -16,11 +16,9 @@ package afero
import (
"fmt"
"io"
"log"
"os"
"path/filepath"
"sort"
"strings"
"sync"

View file

@ -1,9 +1,9 @@
# cast
[![Build Status](https://github.com/spf13/cast/actions/workflows/ci.yml/badge.svg)](https://github.com/spf13/cast/actions/workflows/ci.yml)
[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/spf13/cast/test.yaml?branch=master&style=flat-square)](https://github.com/spf13/cast/actions/workflows/test.yaml)
[![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)
[![Go Report Card](https://goreportcard.com/badge/github.com/spf13/cast?style=flat-square)](https://goreportcard.com/report/github.com/spf13/cast)
Easy and safe casting from one type to another in Go

View file

@ -18,6 +18,14 @@ import (
var errNegativeNotAllowed = errors.New("unable to cast negative value")
type float64EProvider interface {
Float64() (float64, error)
}
type float64Provider interface {
Float64() float64
}
// ToTimeE casts an interface to a time.Time type.
func ToTimeE(i interface{}) (tim time.Time, err error) {
return ToTimeInDefaultLocationE(i, time.UTC)
@ -77,11 +85,14 @@ func ToDurationE(i interface{}) (d time.Duration, err error) {
d, err = time.ParseDuration(s + "ns")
}
return
case json.Number:
case float64EProvider:
var v float64
v, err = s.Float64()
d = time.Duration(v)
return
case float64Provider:
d = time.Duration(s.Float64())
return
default:
err = fmt.Errorf("unable to cast %#v of type %T to Duration", i, i)
return
@ -174,12 +185,14 @@ func ToFloat64E(i interface{}) (float64, error) {
return v, nil
}
return 0, fmt.Errorf("unable to cast %#v of type %T to float64", i, i)
case json.Number:
case float64EProvider:
v, err := s.Float64()
if err == nil {
return v, nil
}
return 0, fmt.Errorf("unable to cast %#v of type %T to float64", i, i)
case float64Provider:
return s.Float64(), nil
case bool:
if s {
return 1, nil
@ -230,12 +243,14 @@ func ToFloat32E(i interface{}) (float32, error) {
return float32(v), nil
}
return 0, fmt.Errorf("unable to cast %#v of type %T to float32", i, i)
case json.Number:
case float64EProvider:
v, err := s.Float64()
if err == nil {
return float32(v), nil
}
return 0, fmt.Errorf("unable to cast %#v of type %T to float32", i, i)
case float64Provider:
return float32(s.Float64()), nil
case bool:
if s {
return 1, nil
@ -598,12 +613,12 @@ func ToUint64E(i interface{}) (uint64, error) {
switch s := i.(type) {
case string:
v, err := strconv.ParseInt(trimZeroDecimal(s), 0, 0)
v, err := strconv.ParseUint(trimZeroDecimal(s), 0, 0)
if err == nil {
if v < 0 {
return 0, errNegativeNotAllowed
}
return uint64(v), nil
return v, nil
}
return 0, fmt.Errorf("unable to cast %#v of type %T to uint64", i, i)
case json.Number:
@ -917,8 +932,8 @@ func indirectToStringerOrError(a interface{}) interface{} {
return nil
}
var errorType = reflect.TypeOf((*error)(nil)).Elem()
var fmtStringerType = reflect.TypeOf((*fmt.Stringer)(nil)).Elem()
errorType := reflect.TypeOf((*error)(nil)).Elem()
fmtStringerType := reflect.TypeOf((*fmt.Stringer)(nil)).Elem()
v := reflect.ValueOf(a)
for !v.Type().Implements(fmtStringerType) && !v.Type().Implements(errorType) && v.Kind() == reflect.Ptr && !v.IsNil() {
@ -987,7 +1002,7 @@ func ToStringE(i interface{}) (string, error) {
// ToStringMapStringE casts an interface to a map[string]string type.
func ToStringMapStringE(i interface{}) (map[string]string, error) {
var m = map[string]string{}
m := map[string]string{}
switch v := i.(type) {
case map[string]string:
@ -1017,7 +1032,7 @@ func ToStringMapStringE(i interface{}) (map[string]string, error) {
// ToStringMapStringSliceE casts an interface to a map[string][]string type.
func ToStringMapStringSliceE(i interface{}) (map[string][]string, error) {
var m = map[string][]string{}
m := map[string][]string{}
switch v := i.(type) {
case map[string][]string:
@ -1081,7 +1096,7 @@ func ToStringMapStringSliceE(i interface{}) (map[string][]string, error) {
// ToStringMapBoolE casts an interface to a map[string]bool type.
func ToStringMapBoolE(i interface{}) (map[string]bool, error) {
var m = map[string]bool{}
m := map[string]bool{}
switch v := i.(type) {
case map[interface{}]interface{}:
@ -1106,7 +1121,7 @@ func ToStringMapBoolE(i interface{}) (map[string]bool, error) {
// ToStringMapE casts an interface to a map[string]interface{} type.
func ToStringMapE(i interface{}) (map[string]interface{}, error) {
var m = map[string]interface{}{}
m := map[string]interface{}{}
switch v := i.(type) {
case map[interface{}]interface{}:
@ -1126,7 +1141,7 @@ func ToStringMapE(i interface{}) (map[string]interface{}, error) {
// ToStringMapIntE casts an interface to a map[string]int{} type.
func ToStringMapIntE(i interface{}) (map[string]int, error) {
var m = map[string]int{}
m := map[string]int{}
if i == nil {
return m, fmt.Errorf("unable to cast %#v of type %T to map[string]int", i, i)
}
@ -1167,7 +1182,7 @@ func ToStringMapIntE(i interface{}) (map[string]int, error) {
// ToStringMapInt64E casts an interface to a map[string]int64{} type.
func ToStringMapInt64E(i interface{}) (map[string]int64, error) {
var m = map[string]int64{}
m := map[string]int64{}
if i == nil {
return m, fmt.Errorf("unable to cast %#v of type %T to map[string]int64", i, i)
}
@ -1404,38 +1419,35 @@ func (f timeFormat) hasTimezone() bool {
return f.typ >= timeFormatNumericTimezone && f.typ <= timeFormatNumericAndNamedTimezone
}
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},
{time.RFC1123, timeFormatNamedTimezone},
{time.RFC822Z, timeFormatNumericTimezone},
{time.RFC822, timeFormatNamedTimezone},
{time.RFC850, timeFormatNamedTimezone},
{"2006-01-02 15:04:05.999999999 -0700 MST", timeFormatNumericAndNamedTimezone}, // Time.String()
{"2006-01-02T15:04:05-0700", timeFormatNumericTimezone}, // RFC3339 without timezone hh:mm colon
{"2006-01-02 15:04:05Z0700", timeFormatNumericTimezone}, // RFC3339 without T or timezone hh:mm colon
{"2006-01-02 15:04:05", timeFormatNoTimezone},
{time.ANSIC, timeFormatNoTimezone},
{time.UnixDate, timeFormatNamedTimezone},
{time.RubyDate, timeFormatNumericTimezone},
{"2006-01-02 15:04:05Z07:00", timeFormatNumericTimezone},
{"02 Jan 2006", timeFormatNoTimezone},
{"2006-01-02 15:04:05 -07:00", timeFormatNumericTimezone},
{"2006-01-02 15:04:05 -0700", timeFormatNumericTimezone},
{time.Kitchen, timeFormatTimeOnly},
{time.Stamp, timeFormatTimeOnly},
{time.StampMilli, timeFormatTimeOnly},
{time.StampMicro, timeFormatTimeOnly},
{time.StampNano, timeFormatTimeOnly},
}
)
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},
{time.RFC1123, timeFormatNamedTimezone},
{time.RFC822Z, timeFormatNumericTimezone},
{time.RFC822, timeFormatNamedTimezone},
{time.RFC850, timeFormatNamedTimezone},
{"2006-01-02 15:04:05.999999999 -0700 MST", timeFormatNumericAndNamedTimezone}, // Time.String()
{"2006-01-02T15:04:05-0700", timeFormatNumericTimezone}, // RFC3339 without timezone hh:mm colon
{"2006-01-02 15:04:05Z0700", timeFormatNumericTimezone}, // RFC3339 without T or timezone hh:mm colon
{"2006-01-02 15:04:05", timeFormatNoTimezone},
{time.ANSIC, timeFormatNoTimezone},
{time.UnixDate, timeFormatNamedTimezone},
{time.RubyDate, timeFormatNumericTimezone},
{"2006-01-02 15:04:05Z07:00", timeFormatNumericTimezone},
{"02 Jan 2006", timeFormatNoTimezone},
{"2006-01-02 15:04:05 -07:00", timeFormatNumericTimezone},
{"2006-01-02 15:04:05 -0700", timeFormatNumericTimezone},
{time.Kitchen, timeFormatTimeOnly},
{time.Stamp, timeFormatTimeOnly},
{time.StampMilli, timeFormatTimeOnly},
{time.StampMicro, timeFormatTimeOnly},
{time.StampNano, timeFormatTimeOnly},
}
func parseDateWith(s string, location *time.Location, formats []timeFormat) (d time.Time, e error) {
for _, format := range formats {
if d, e = time.Parse(format.format, s); e == nil {

12
vendor/github.com/spf13/pflag/.editorconfig generated vendored Normal file
View file

@ -0,0 +1,12 @@
root = true
[*]
charset = utf-8
end_of_line = lf
indent_size = 4
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
[*.go]
indent_style = tab

4
vendor/github.com/spf13/pflag/.golangci.yaml generated vendored Normal file
View file

@ -0,0 +1,4 @@
linters:
disable-all: true
enable:
- nolintlint

View file

@ -160,7 +160,7 @@ type FlagSet struct {
args []string // arguments after flags
argsLenAtDash int // len(args) when a '--' was located when parsing, or -1 if no --
errorHandling ErrorHandling
output io.Writer // nil means stderr; use out() accessor
output io.Writer // nil means stderr; use Output() accessor
interspersed bool // allow interspersed option/non-option args
normalizeNameFunc func(f *FlagSet, name string) NormalizedName
@ -255,13 +255,20 @@ func (f *FlagSet) normalizeFlagName(name string) NormalizedName {
return n(f, name)
}
func (f *FlagSet) out() io.Writer {
// Output returns the destination for usage and error messages. os.Stderr is returned if
// output was not set or was set to nil.
func (f *FlagSet) Output() io.Writer {
if f.output == nil {
return os.Stderr
}
return f.output
}
// Name returns the name of the flag set.
func (f *FlagSet) Name() string {
return f.name
}
// SetOutput sets the destination for usage and error messages.
// If output is nil, os.Stderr is used.
func (f *FlagSet) SetOutput(output io.Writer) {
@ -358,7 +365,7 @@ func (f *FlagSet) ShorthandLookup(name string) *Flag {
}
if len(name) > 1 {
msg := fmt.Sprintf("can not look up shorthand which is more than one ASCII character: %q", name)
fmt.Fprintf(f.out(), msg)
fmt.Fprintf(f.Output(), msg)
panic(msg)
}
c := name[0]
@ -482,7 +489,7 @@ func (f *FlagSet) Set(name, value string) error {
}
if flag.Deprecated != "" {
fmt.Fprintf(f.out(), "Flag --%s has been deprecated, %s\n", flag.Name, flag.Deprecated)
fmt.Fprintf(f.Output(), "Flag --%s has been deprecated, %s\n", flag.Name, flag.Deprecated)
}
return nil
}
@ -523,7 +530,7 @@ func Set(name, value string) error {
// otherwise, the default values of all defined flags in the set.
func (f *FlagSet) PrintDefaults() {
usages := f.FlagUsages()
fmt.Fprint(f.out(), usages)
fmt.Fprint(f.Output(), usages)
}
// defaultIsZeroValue returns true if the default value for this flag represents
@ -758,7 +765,7 @@ func PrintDefaults() {
// defaultUsage is the default function to print a usage message.
func defaultUsage(f *FlagSet) {
fmt.Fprintf(f.out(), "Usage of %s:\n", f.name)
fmt.Fprintf(f.Output(), "Usage of %s:\n", f.name)
f.PrintDefaults()
}
@ -844,7 +851,7 @@ func (f *FlagSet) AddFlag(flag *Flag) {
_, alreadyThere := f.formal[normalizedFlagName]
if alreadyThere {
msg := fmt.Sprintf("%s flag redefined: %s", f.name, flag.Name)
fmt.Fprintln(f.out(), msg)
fmt.Fprintln(f.Output(), msg)
panic(msg) // Happens only if flags are declared with identical names
}
if f.formal == nil {
@ -860,7 +867,7 @@ func (f *FlagSet) AddFlag(flag *Flag) {
}
if len(flag.Shorthand) > 1 {
msg := fmt.Sprintf("%q shorthand is more than one ASCII character", flag.Shorthand)
fmt.Fprintf(f.out(), msg)
fmt.Fprintf(f.Output(), msg)
panic(msg)
}
if f.shorthands == nil {
@ -870,7 +877,7 @@ func (f *FlagSet) AddFlag(flag *Flag) {
used, alreadyThere := f.shorthands[c]
if alreadyThere {
msg := fmt.Sprintf("unable to redefine %q shorthand in %q flagset: it's already used for %q flag", c, f.name, used.Name)
fmt.Fprintf(f.out(), msg)
fmt.Fprintf(f.Output(), msg)
panic(msg)
}
f.shorthands[c] = flag
@ -909,7 +916,7 @@ func VarP(value Value, name, shorthand, usage string) {
func (f *FlagSet) failf(format string, a ...interface{}) error {
err := fmt.Errorf(format, a...)
if f.errorHandling != ContinueOnError {
fmt.Fprintln(f.out(), err)
fmt.Fprintln(f.Output(), err)
f.usage()
}
return err
@ -1060,7 +1067,7 @@ func (f *FlagSet) parseSingleShortArg(shorthands string, args []string, fn parse
}
if flag.ShorthandDeprecated != "" {
fmt.Fprintf(f.out(), "Flag shorthand -%s has been deprecated, %s\n", flag.Shorthand, flag.ShorthandDeprecated)
fmt.Fprintf(f.Output(), "Flag shorthand -%s has been deprecated, %s\n", flag.Shorthand, flag.ShorthandDeprecated)
}
err = fn(flag, value)

View file

@ -16,6 +16,9 @@ func newIPValue(val net.IP, p *net.IP) *ipValue {
func (i *ipValue) String() string { return net.IP(*i).String() }
func (i *ipValue) Set(s string) error {
if s == "" {
return nil
}
ip := net.ParseIP(strings.TrimSpace(s))
if ip == nil {
return fmt.Errorf("failed to parse IP: %q", s)

147
vendor/github.com/spf13/pflag/ipnet_slice.go generated vendored Normal file
View file

@ -0,0 +1,147 @@
package pflag
import (
"fmt"
"io"
"net"
"strings"
)
// -- ipNetSlice Value
type ipNetSliceValue struct {
value *[]net.IPNet
changed bool
}
func newIPNetSliceValue(val []net.IPNet, p *[]net.IPNet) *ipNetSliceValue {
ipnsv := new(ipNetSliceValue)
ipnsv.value = p
*ipnsv.value = val
return ipnsv
}
// Set converts, and assigns, the comma-separated IPNet argument string representation as the []net.IPNet value of this flag.
// If Set is called on a flag that already has a []net.IPNet assigned, the newly converted values will be appended.
func (s *ipNetSliceValue) Set(val string) error {
// remove all quote characters
rmQuote := strings.NewReplacer(`"`, "", `'`, "", "`", "")
// read flag arguments with CSV parser
ipNetStrSlice, err := readAsCSV(rmQuote.Replace(val))
if err != nil && err != io.EOF {
return err
}
// parse ip values into slice
out := make([]net.IPNet, 0, len(ipNetStrSlice))
for _, ipNetStr := range ipNetStrSlice {
_, n, err := net.ParseCIDR(strings.TrimSpace(ipNetStr))
if err != nil {
return fmt.Errorf("invalid string being converted to CIDR: %s", ipNetStr)
}
out = append(out, *n)
}
if !s.changed {
*s.value = out
} else {
*s.value = append(*s.value, out...)
}
s.changed = true
return nil
}
// Type returns a string that uniquely represents this flag's type.
func (s *ipNetSliceValue) Type() string {
return "ipNetSlice"
}
// String defines a "native" format for this net.IPNet slice flag value.
func (s *ipNetSliceValue) String() string {
ipNetStrSlice := make([]string, len(*s.value))
for i, n := range *s.value {
ipNetStrSlice[i] = n.String()
}
out, _ := writeAsCSV(ipNetStrSlice)
return "[" + out + "]"
}
func ipNetSliceConv(val string) (interface{}, error) {
val = strings.Trim(val, "[]")
// Emtpy string would cause a slice with one (empty) entry
if len(val) == 0 {
return []net.IPNet{}, nil
}
ss := strings.Split(val, ",")
out := make([]net.IPNet, len(ss))
for i, sval := range ss {
_, n, err := net.ParseCIDR(strings.TrimSpace(sval))
if err != nil {
return nil, fmt.Errorf("invalid string being converted to CIDR: %s", sval)
}
out[i] = *n
}
return out, nil
}
// GetIPNetSlice returns the []net.IPNet value of a flag with the given name
func (f *FlagSet) GetIPNetSlice(name string) ([]net.IPNet, error) {
val, err := f.getFlagType(name, "ipNetSlice", ipNetSliceConv)
if err != nil {
return []net.IPNet{}, err
}
return val.([]net.IPNet), nil
}
// IPNetSliceVar defines a ipNetSlice flag with specified name, default value, and usage string.
// The argument p points to a []net.IPNet variable in which to store the value of the flag.
func (f *FlagSet) IPNetSliceVar(p *[]net.IPNet, name string, value []net.IPNet, usage string) {
f.VarP(newIPNetSliceValue(value, p), name, "", usage)
}
// IPNetSliceVarP is like IPNetSliceVar, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) IPNetSliceVarP(p *[]net.IPNet, name, shorthand string, value []net.IPNet, usage string) {
f.VarP(newIPNetSliceValue(value, p), name, shorthand, usage)
}
// IPNetSliceVar defines a []net.IPNet flag with specified name, default value, and usage string.
// The argument p points to a []net.IPNet variable in which to store the value of the flag.
func IPNetSliceVar(p *[]net.IPNet, name string, value []net.IPNet, usage string) {
CommandLine.VarP(newIPNetSliceValue(value, p), name, "", usage)
}
// IPNetSliceVarP is like IPNetSliceVar, but accepts a shorthand letter that can be used after a single dash.
func IPNetSliceVarP(p *[]net.IPNet, name, shorthand string, value []net.IPNet, usage string) {
CommandLine.VarP(newIPNetSliceValue(value, p), name, shorthand, usage)
}
// IPNetSlice defines a []net.IPNet flag with specified name, default value, and usage string.
// The return value is the address of a []net.IPNet variable that stores the value of that flag.
func (f *FlagSet) IPNetSlice(name string, value []net.IPNet, usage string) *[]net.IPNet {
p := []net.IPNet{}
f.IPNetSliceVarP(&p, name, "", value, usage)
return &p
}
// IPNetSliceP is like IPNetSlice, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) IPNetSliceP(name, shorthand string, value []net.IPNet, usage string) *[]net.IPNet {
p := []net.IPNet{}
f.IPNetSliceVarP(&p, name, shorthand, value, usage)
return &p
}
// IPNetSlice defines a []net.IPNet flag with specified name, default value, and usage string.
// The return value is the address of a []net.IP variable that stores the value of the flag.
func IPNetSlice(name string, value []net.IPNet, usage string) *[]net.IPNet {
return CommandLine.IPNetSliceP(name, "", value, usage)
}
// IPNetSliceP is like IPNetSlice, but accepts a shorthand letter that can be used after a single dash.
func IPNetSliceP(name, shorthand string, value []net.IPNet, usage string) *[]net.IPNet {
return CommandLine.IPNetSliceP(name, shorthand, value, usage)
}

View file

@ -31,11 +31,7 @@ func (s *stringArrayValue) Append(val string) error {
func (s *stringArrayValue) Replace(val []string) error {
out := make([]string, len(val))
for i, d := range val {
var err error
out[i] = d
if err != nil {
return err
}
}
*s.value = out
return nil

View file

@ -7,6 +7,16 @@ linters-settings:
- standard
- default
- prefix(github.com/spf13/viper)
gocritic:
# Enable multiple checks by tags. See "Tags" section in https://github.com/go-critic/go-critic#usage.
enabled-tags:
- diagnostic
- experimental
- opinionated
- style
disabled-checks:
- importShadow
- unnamedResult
golint:
min-confidence: 0
goimports:
@ -22,6 +32,8 @@ linters:
- exhaustive
- exportloopref
- gci
- gocritic
- godot
- gofmt
- gofumpt
- goimports
@ -62,9 +74,7 @@ linters:
# - gochecknoinits
# - gocognit
# - goconst
# - gocritic
# - gocyclo
# - godot
# - gosec
# - gosimple
# - ifshort

View file

@ -11,7 +11,7 @@
[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/spf13/viper/ci.yaml?branch=master&style=flat-square)](https://github.com/spf13/viper/actions?query=workflow%3ACI)
[![Join the chat at https://gitter.im/spf13/viper](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/spf13/viper?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Go Report Card](https://goreportcard.com/badge/github.com/spf13/viper?style=flat-square)](https://goreportcard.com/report/github.com/spf13/viper)
![Go Version](https://img.shields.io/badge/go%20version-%3E=1.19-61CFDD.svg?style=flat-square)
![Go Version](https://img.shields.io/badge/go%20version-%3E=1.20-61CFDD.svg?style=flat-square)
[![PkgGoDev](https://pkg.go.dev/badge/mod/github.com/spf13/viper)](https://pkg.go.dev/mod/github.com/spf13/viper)
**Go configuration with fangs!**
@ -39,7 +39,7 @@ Many Go projects are built using Viper including:
go get github.com/spf13/viper
```
**Note:** Viper uses [Go Modules](https://github.com/golang/go/wiki/Modules) to manage dependencies.
**Note:** Viper uses [Go Modules](https://go.dev/wiki/Modules) to manage dependencies.
## What is Viper?
@ -418,7 +418,9 @@ in a Key/Value store such as etcd or Consul. These values take precedence over
default values, but are overridden by configuration values retrieved from disk,
flags, or environment variables.
Viper uses [crypt](https://github.com/bketelsen/crypt) to retrieve
Viper supports multiple hosts. To use, pass a list of endpoints separated by `;`. For example `http://127.0.0.1:4001;http://127.0.0.1:4002`.
Viper uses [crypt](https://github.com/sagikazarmark/crypt) to retrieve
configuration from the K/V store, which means that you can store your
configuration values encrypted and have them automatically decrypted if you have
the correct gpg keyring. Encryption is optional.
@ -430,7 +432,7 @@ independently of it.
K/V store. `crypt` defaults to etcd on http://127.0.0.1:4001.
```bash
$ go get github.com/bketelsen/crypt/bin/crypt
$ go get github.com/sagikazarmark/crypt/bin/crypt
$ crypt set -plaintext /config/hugo.json /Users/hugo/settings/config.json
```
@ -563,6 +565,9 @@ One important thing to recognize is that each Get function will return a zero
value if its not found. To check if a given key exists, the `IsSet()` method
has been provided.
The zero value will also be returned if the value is set, but fails to parse
as the requested type.
Example:
```go
viper.GetString("logfile") // case-insensitive Setting & Getting

View file

@ -15,10 +15,10 @@ cannot find package "github.com/hashicorp/hcl/tree/hcl1" in any of:
```
As the error message suggests, Go tries to look up dependencies in `GOPATH` mode (as it's commonly called) from the `GOPATH`.
Viper opted to use [Go Modules](https://github.com/golang/go/wiki/Modules) to manage its dependencies. While in many cases the two methods are interchangeable, once a dependency releases new (major) versions, `GOPATH` mode is no longer able to decide which version to use, so it'll either use one that's already present or pick a version (usually the `master` branch).
Viper opted to use [Go Modules](https://go.dev/wiki/Modules) to manage its dependencies. While in many cases the two methods are interchangeable, once a dependency releases new (major) versions, `GOPATH` mode is no longer able to decide which version to use, so it'll either use one that's already present or pick a version (usually the `master` branch).
The solution is easy: switch to using Go Modules.
Please refer to the [wiki](https://github.com/golang/go/wiki/Modules) on how to do that.
Please refer to the [wiki](https://go.dev/wiki/Modules) on how to do that.
**tl;dr* `export GO111MODULE=on`

View file

@ -43,7 +43,7 @@ func (v *Viper) searchInPath(in string) (filename string) {
return ""
}
// Check if file Exists
// exists checks if file exists.
func exists(fs afero.Fs, path string) (bool, error) {
stat, err := fs.Stat(path)
if err == nil {

View file

@ -31,7 +31,7 @@ func (p pflagValueSet) VisitAll(fn func(flag FlagValue)) {
}
// pflagValue is a wrapper around *pflag.flag
// that implements FlagValue
// that implements FlagValue.
type pflagValue struct {
flag *pflag.Flag
}

View file

@ -8,11 +8,11 @@
"pre-commit-hooks": "pre-commit-hooks"
},
"locked": {
"lastModified": 1687972261,
"narHash": "sha256-+mxvZfwMVoaZYETmuQWqTi/7T9UKoAE+WpdSQkOVJ2g=",
"lastModified": 1707817777,
"narHash": "sha256-vHyIs1OULQ3/91wD6xOiuayfI71JXALGA5KLnDKAcy0=",
"owner": "cachix",
"repo": "devenv",
"rev": "e85df562088573305e55906eaa964341f8cb0d9f",
"rev": "5a30b9e5ac7c6167e61b1f4193d5130bb9f8defa",
"type": "github"
},
"original": {
@ -42,11 +42,11 @@
"nixpkgs-lib": "nixpkgs-lib"
},
"locked": {
"lastModified": 1687762428,
"narHash": "sha256-DIf7mi45PKo+s8dOYF+UlXHzE0Wl/+k3tXUyAoAnoGE=",
"lastModified": 1706830856,
"narHash": "sha256-a0NYyp+h9hlb7ddVz4LUn1vT/PLwqfrWYcHMvFB1xYg=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "37dd7bb15791c86d55c5121740a1887ab55ee836",
"rev": "b253292d9c0a5ead9bc98c4e9a26c6312e27d69f",
"type": "github"
},
"original": {
@ -56,12 +56,15 @@
}
},
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1667395993,
"narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=",
"lastModified": 1685518550,
"narHash": "sha256-o2d0KcvaXzTrPRIo0kOLV0/QXHhDQ5DTi+OxcjO8xqY=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f",
"rev": "a1720a10a6cfe8234c0e93907ffe81be440f4cef",
"type": "github"
},
"original": {
@ -151,11 +154,11 @@
"nixpkgs-lib": {
"locked": {
"dir": "lib",
"lastModified": 1685564631,
"narHash": "sha256-8ywr3AkblY4++3lIVxmrWZFzac7+f32ZEhH/A8pNscI=",
"lastModified": 1706550542,
"narHash": "sha256-UcsnCG6wx++23yeER4Hg18CXWbgNpqNXcHIo5/1Y+hc=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "4f53efe34b3a8877ac923b9350c874e3dcd5dc0a",
"rev": "97b17f32362e475016f942bbdfda4a4a72a8a652",
"type": "github"
},
"original": {
@ -184,27 +187,27 @@
},
"nixpkgs-stable": {
"locked": {
"lastModified": 1678872516,
"narHash": "sha256-/E1YwtMtFAu2KUQKV/1+KFuReYPANM2Rzehk84VxVoc=",
"lastModified": 1685801374,
"narHash": "sha256-otaSUoFEMM+LjBI1XL/xGB5ao6IwnZOXc47qhIgJe8U=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "9b8e5abb18324c7fe9f07cb100c3cd4a29cda8b8",
"rev": "c37ca420157f4abc31e26f436c1145f8951ff373",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-22.11",
"ref": "nixos-23.05",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1687886075,
"narHash": "sha256-PeayJDDDy+uw1Ats4moZnRdL1OFuZm1Tj+KiHlD67+o=",
"lastModified": 1707939175,
"narHash": "sha256-D1xan0lgxbmXDyzVqXTiSYHLmAMrMRdD+alKzEO/p3w=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "a565059a348422af5af9026b5174dc5c0dcefdae",
"rev": "f7e8132daca31b1e3859ac0fb49741754375ac3d",
"type": "github"
},
"original": {
@ -229,11 +232,11 @@
"nixpkgs-stable": "nixpkgs-stable"
},
"locked": {
"lastModified": 1686050334,
"narHash": "sha256-R0mczWjDzBpIvM3XXhO908X5e2CQqjyh/gFbwZk/7/Q=",
"lastModified": 1704725188,
"narHash": "sha256-qq8NbkhRZF1vVYQFt1s8Mbgo8knj+83+QlL5LBnYGpI=",
"owner": "cachix",
"repo": "pre-commit-hooks.nix",
"rev": "6881eb2ae5d8a3516e34714e7a90d9d95914c4dc",
"rev": "ea96f0c05924341c551a797aaba8126334c505d2",
"type": "github"
},
"original": {
@ -248,6 +251,21 @@
"flake-parts": "flake-parts",
"nixpkgs": "nixpkgs_2"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
}
},
"root": "root",

View file

@ -20,6 +20,7 @@
default = {
languages = {
go.enable = true;
go.package = pkgs.go_1_22;
};
pre-commit.hooks = {

View file

@ -8,8 +8,8 @@ import (
// flattenAndMergeMap recursively flattens the given map into a new map
// Code is based on the function with the same name in the main package.
// TODO: move it to a common place
func flattenAndMergeMap(shadow map[string]any, m map[string]any, prefix string, delimiter string) map[string]any {
// TODO: move it to a common place.
func flattenAndMergeMap(shadow, m map[string]any, prefix, delimiter string) map[string]any {
if shadow != nil && prefix != "" && shadow[prefix] != nil {
// prefix is shadowed => nothing more to flatten
return shadow

View file

@ -41,8 +41,8 @@ func deepSearch(m map[string]any, path []string) map[string]any {
// flattenAndMergeMap recursively flattens the given map into a new map
// Code is based on the function with the same name in the main package.
// TODO: move it to a common place
func flattenAndMergeMap(shadow map[string]any, m map[string]any, prefix string, delimiter string) map[string]any {
// TODO: move it to a common place.
func flattenAndMergeMap(shadow, m map[string]any, prefix, delimiter string) map[string]any {
if shadow != nil && prefix != "" && shadow[prefix] != nil {
// prefix is shadowed => nothing more to flatten
return shadow

View file

@ -41,8 +41,8 @@ func deepSearch(m map[string]any, path []string) map[string]any {
// flattenAndMergeMap recursively flattens the given map into a new map
// Code is based on the function with the same name in the main package.
// TODO: move it to a common place
func flattenAndMergeMap(shadow map[string]any, m map[string]any, prefix string, delimiter string) map[string]any {
// TODO: move it to a common place.
func flattenAndMergeMap(shadow, m map[string]any, prefix, delimiter string) map[string]any {
if shadow != nil && prefix != "" && shadow[prefix] != nil {
// prefix is shadowed => nothing more to flatten
return shadow

View file

@ -0,0 +1,5 @@
//go:build viper_bind_struct
package features
const BindStruct = true

View file

@ -0,0 +1,5 @@
//go:build !viper_bind_struct
package features
const BindStruct = false

View file

@ -156,7 +156,7 @@ func safeMul(a, b uint) uint {
return c
}
// parseSizeInBytes converts strings like 1GB or 12 mb into an unsigned integer number of bytes
// parseSizeInBytes converts strings like 1GB or 12 mb into an unsigned integer number of bytes.
func parseSizeInBytes(sizeStr string) uint {
sizeStr = strings.TrimSpace(sizeStr)
lastChar := len(sizeStr) - 1

View file

@ -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.
@ -77,7 +78,7 @@ type remoteConfigFactory interface {
WatchChannel(rp RemoteProvider) (<-chan *RemoteResponse, chan bool)
}
// RemoteConfig is optional, see the remote package
// RemoteConfig is optional, see the remote package.
var RemoteConfig remoteConfigFactory
// UnsupportedConfigError denotes encountering an unsupported
@ -102,7 +103,7 @@ func (str UnsupportedRemoteProviderError) Error() string {
// pull the configuration from the remote provider.
type RemoteConfigError string
// Error returns the formatted remote provider error
// Error returns the formatted remote provider error.
func (rce RemoteConfigError) Error() string {
return fmt.Sprintf("Remote Configurations Error: %s", string(rce))
}
@ -126,7 +127,7 @@ func (faee ConfigFileAlreadyExistsError) Error() string {
}
// A DecoderConfigOption can be passed to viper.Unmarshal to configure
// mapstructure.DecoderConfig options
// mapstructure.DecoderConfig options.
type DecoderConfigOption func(*mapstructure.DecoderConfig)
// DecodeHook returns a DecoderConfigOption which overrides the default
@ -305,7 +306,7 @@ func Reset() {
SupportedRemoteProviders = []string{"etcd", "etcd3", "consul", "firestore", "nats"}
}
// TODO: make this lazy initialization instead
// TODO: make this lazy initialization instead.
func (v *Viper) resetEncoding() {
encoderRegistry := encoding.NewEncoderRegistry()
decoderRegistry := encoding.NewDecoderRegistry()
@ -439,7 +440,7 @@ func (v *Viper) WatchConfig() {
initWG := sync.WaitGroup{}
initWG.Add(1)
go func() {
watcher, err := newWatcher()
watcher, err := fsnotify.NewWatcher()
if err != nil {
v.logger.Error(fmt.Sprintf("failed to create watcher: %s", err))
os.Exit(1)
@ -590,7 +591,7 @@ func (v *Viper) AddConfigPath(in string) {
// path is the path in the k/v store to retrieve configuration
// To retrieve a config file called myapp.json from /configs/myapp.json
// you should set path to /configs and set config name (SetConfigName()) to
// "myapp"
// "myapp".
func AddRemoteProvider(provider, endpoint, path string) error {
return v.AddRemoteProvider(provider, endpoint, path)
}
@ -622,8 +623,8 @@ func (v *Viper) AddRemoteProvider(provider, endpoint, path string) error {
// path is the path in the k/v store to retrieve configuration
// To retrieve a config file called myapp.json from /configs/myapp.json
// you should set path to /configs and set config name (SetConfigName()) to
// "myapp"
// Secure Remote Providers are implemented with github.com/bketelsen/crypt
// "myapp".
// Secure Remote Providers are implemented with github.com/sagikazarmark/crypt.
func AddSecureRemoteProvider(provider, endpoint, path, secretkeyring string) error {
return v.AddSecureRemoteProvider(provider, endpoint, path, secretkeyring)
}
@ -827,10 +828,12 @@ func (v *Viper) isPathShadowedInDeepMap(path []string, m map[string]any) string
// "foo.bar.baz" in a lower-priority map
func (v *Viper) isPathShadowedInFlatMap(path []string, mi any) string {
// unify input map
var m map[string]any
switch mi.(type) {
case map[string]string, map[string]FlagValue:
m = cast.ToStringMap(mi)
var m map[string]interface{}
switch miv := mi.(type) {
case map[string]string:
m = castMapStringToMapInterface(miv)
case map[string]FlagValue:
m = castMapFlagToMapInterface(miv)
default:
return ""
}
@ -957,7 +960,8 @@ func (v *Viper) Sub(key string) *Viper {
}
if reflect.TypeOf(data).Kind() == reflect.Map {
subv.parents = append(v.parents, strings.ToLower(key))
subv.parents = append([]string(nil), v.parents...)
subv.parents = append(subv.parents, strings.ToLower(key))
subv.automaticEnvApplied = v.automaticEnvApplied
subv.envPrefix = v.envPrefix
subv.envKeyReplacer = v.envKeyReplacer
@ -1111,11 +1115,42 @@ func Unmarshal(rawVal any, opts ...DecoderConfigOption) error {
}
func (v *Viper) Unmarshal(rawVal any, opts ...DecoderConfigOption) error {
return decode(v.AllSettings(), defaultDecoderConfig(rawVal, opts...))
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(keys), defaultDecoderConfig(rawVal, opts...))
}
func (v *Viper) decodeStructKeys(input any, opts ...DecoderConfigOption) ([]string, error) {
var structKeyMap map[string]any
err := decode(input, defaultDecoderConfig(&structKeyMap, opts...))
if err != nil {
return nil, err
}
flattenedStructKeyMap := v.flattenAndMergeMap(map[string]bool{}, structKeyMap, "")
r := make([]string, 0, len(flattenedStructKeyMap))
for v := range flattenedStructKeyMap {
r = append(r, v)
}
return r, nil
}
// defaultDecoderConfig returns default mapstructure.DecoderConfig with support
// of time.Duration values & string slices
// of time.Duration values & string slices.
func defaultDecoderConfig(output any, opts ...DecoderConfigOption) *mapstructure.DecoderConfig {
c := &mapstructure.DecoderConfig{
Metadata: nil,
@ -1132,7 +1167,7 @@ func defaultDecoderConfig(output any, opts ...DecoderConfigOption) *mapstructure
return c
}
// A wrapper around mapstructure.Decode that mimics the WeakDecode functionality
// decode is a wrapper around mapstructure.Decode that mimics the WeakDecode functionality.
func decode(input any, config *mapstructure.DecoderConfig) error {
decoder, err := mapstructure.NewDecoder(config)
if err != nil {
@ -1151,7 +1186,20 @@ func (v *Viper) UnmarshalExact(rawVal any, opts ...DecoderConfigOption) error {
config := defaultDecoderConfig(rawVal, opts...)
config.ErrorUnused = true
return decode(v.AllSettings(), config)
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(keys), config)
}
// BindPFlags binds a full flag set to the configuration, using each flag's long
@ -1405,11 +1453,11 @@ func readAsCSV(val string) ([]string, error) {
}
// mostly copied from pflag's implementation of this operation here https://github.com/spf13/pflag/blob/master/string_to_string.go#L79
// alterations are: errors are swallowed, map[string]any is returned in order to enable cast.ToStringMap
// alterations are: errors are swallowed, map[string]any is returned in order to enable cast.ToStringMap.
func stringToStringConv(val string) any {
val = strings.Trim(val, "[]")
// An empty string would cause an empty map
if len(val) == 0 {
if val == "" {
return map[string]any{}
}
r := csv.NewReader(strings.NewReader(val))
@ -1429,11 +1477,11 @@ func stringToStringConv(val string) any {
}
// 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]any is returned in order to enable cast.ToStringMap
// alterations are: errors are swallowed, map[string]any is returned in order to enable cast.ToStringMap.
func stringToIntConv(val string) any {
val = strings.Trim(val, "[]")
// An empty string would cause an empty map
if len(val) == 0 {
if val == "" {
return map[string]any{}
}
ss := strings.Split(val, ",")
@ -1481,13 +1529,13 @@ func (v *Viper) SetEnvKeyReplacer(r *strings.Replacer) {
// RegisterAlias creates an alias that provides another accessor for the same key.
// This enables one to change a name without breaking the application.
func RegisterAlias(alias string, key string) { v.RegisterAlias(alias, key) }
func RegisterAlias(alias, key string) { v.RegisterAlias(alias, key) }
func (v *Viper) RegisterAlias(alias string, key string) {
func (v *Viper) RegisterAlias(alias, key string) {
v.registerAlias(alias, strings.ToLower(key))
}
func (v *Viper) registerAlias(alias string, key string) {
func (v *Viper) registerAlias(alias, key string) {
alias = strings.ToLower(alias)
if alias != key && alias != v.realKey(key) {
_, exists := v.aliases[alias]
@ -1743,12 +1791,6 @@ func (v *Viper) writeConfig(filename string, force bool) error {
return f.Sync()
}
// Unmarshal a Reader into a map.
// Should probably be an unexported function.
func unmarshalReader(in io.Reader, c map[string]any) error {
return v.unmarshalReader(in, c)
}
func (v *Viper) unmarshalReader(in io.Reader, c map[string]any) error {
buf := new(bytes.Buffer)
buf.ReadFrom(in)
@ -2012,7 +2054,7 @@ func (v *Viper) watchRemoteConfig(provider RemoteProvider) (map[string]any, erro
}
// AllKeys returns all keys holding a value, regardless of where they are set.
// Nested keys are returned with a v.keyDelim separator
// Nested keys are returned with a v.keyDelim separator.
func AllKeys() []string { return v.AllKeys() }
func (v *Viper) AllKeys() []string {
@ -2098,9 +2140,13 @@ outer:
func AllSettings() map[string]any { return v.AllSettings() }
func (v *Viper) AllSettings() map[string]any {
return v.getSettings(v.AllKeys())
}
func (v *Viper) getSettings(keys []string) map[string]any {
m := map[string]any{}
// start from the list of keys, and construct the map one value at a time
for _, k := range v.AllKeys() {
for _, k := range keys {
value := v.Get(k)
if value == nil {
// should not happen, since AllKeys() returns only keys holding a value,

View file

@ -1,11 +0,0 @@
//go:build darwin || dragonfly || freebsd || openbsd || linux || netbsd || solaris || windows
package viper
import "github.com/fsnotify/fsnotify"
type watcher = fsnotify.Watcher
func newWatcher() (*watcher, error) {
return fsnotify.NewWatcher()
}

View file

@ -1,31 +0,0 @@
//go:build appengine || (!darwin && !dragonfly && !freebsd && !openbsd && !linux && !netbsd && !solaris && !windows)
package viper
import (
"fmt"
"runtime"
"github.com/fsnotify/fsnotify"
)
func newWatcher() (*watcher, error) {
return &watcher{}, fmt.Errorf("fsnotify not supported on %s", runtime.GOOS)
}
type watcher struct {
Events chan fsnotify.Event
Errors chan error
}
func (*watcher) Close() error {
return nil
}
func (*watcher) Add(name string) error {
return nil
}
func (*watcher) Remove(name string) error {
return nil
}