Compare commits

..
1 Commits
Author SHA1 Message Date
Andrew Stuart a1b8372762 Fix nil pointer on watch function (#568) 2018-09-28 01:07:09 -07:00
4 changed files with 14 additions and 110 deletions
+2 -1
View File
@@ -2,8 +2,9 @@ go_import_path: github.com/spf13/viper
language: go
go:
- 1.7.x
- 1.8.x
- 1.9.x
- 1.10.x
- tip
os:
+1 -23
View File
@@ -191,7 +191,7 @@ _When working with ENV variables, its important to recognize that Viper
treats ENV variables as case sensitive._
Viper provides a mechanism to try to ensure that ENV variables are unique. By
using `SetEnvPrefix`, you can tell Viper to use a prefix while reading from
using `SetEnvPrefix`, you can tell Viper to use add a prefix while reading from
the environment variables. Both `BindEnv` and `AutomaticEnv` will use this
prefix.
@@ -437,7 +437,6 @@ The following functions and methods exist:
* `GetTime(key string) : time.Time`
* `GetDuration(key string) : time.Duration`
* `IsSet(key string) : bool`
* `AllSettings() : map[string]interface{}`
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
@@ -591,27 +590,6 @@ if err != nil {
}
```
### Marshalling to string
You may need to marhsal all the settings held in viper into a string rather than write them to a file.
You can use your favorite format's marshaller with the config returned by `AllSettings()`.
```go
import (
yaml "gopkg.in/yaml.v2"
// ...
)
func yamlStringSettings() string {
c := viper.AllSettings()
bs, err := yaml.Marshal(c)
if err != nil {
t.Fatalf("unable to marshal config to YAML: %v", err)
}
return string(bs)
}
```
## Viper or Vipers?
Viper comes ready to use out of the box. There is no configuration or
+11 -40
View File
@@ -113,23 +113,6 @@ func (fnfe ConfigFileNotFoundError) Error() string {
return fmt.Sprintf("Config File %q Not Found in %q", fnfe.name, fnfe.locations)
}
// A DecoderConfigOption can be passed to viper.Unmarshal to configure
// mapstructure.DecoderConfig options
type DecoderConfigOption func(*mapstructure.DecoderConfig)
// DecodeHook returns a DecoderConfigOption which overrides the default
// DecoderConfig.DecodeHook value, the default is:
//
// mapstructure.ComposeDecodeHookFunc(
// mapstructure.StringToTimeDurationHookFunc(),
// mapstructure.StringToSliceHookFunc(","),
// )
func DecodeHook(hook mapstructure.DecodeHookFunc) DecoderConfigOption {
return func(c *mapstructure.DecoderConfig) {
c.DecodeHook = hook
}
}
// Viper is a prioritized configuration registry. It
// maintains a set of configuration sources, fetches
// values to populate those, and provides them according
@@ -306,7 +289,9 @@ func (v *Viper) WatchConfig() {
if err != nil {
log.Println("error:", err)
}
v.onConfigChange(event)
if v.onConfigChange != nil {
v.onConfigChange(event)
}
}
}
case err := <-watcher.Errors:
@@ -699,12 +684,6 @@ func (v *Viper) GetInt(key string) int {
return cast.ToInt(v.Get(key))
}
// GetInt32 returns the value associated with the key as an integer.
func GetInt32(key string) int32 { return v.GetInt32(key) }
func (v *Viper) GetInt32(key string) int32 {
return cast.ToInt32(v.Get(key))
}
// GetInt64 returns the value associated with the key as an integer.
func GetInt64(key string) int64 { return v.GetInt64(key) }
func (v *Viper) GetInt64(key string) int64 {
@@ -762,11 +741,9 @@ func (v *Viper) GetSizeInBytes(key string) uint {
}
// UnmarshalKey takes a single key and unmarshals it into a Struct.
func UnmarshalKey(key string, rawVal interface{}, opts ...DecoderConfigOption) error {
return v.UnmarshalKey(key, rawVal, opts...)
}
func (v *Viper) UnmarshalKey(key string, rawVal interface{}, opts ...DecoderConfigOption) error {
err := decode(v.Get(key), defaultDecoderConfig(rawVal, opts...))
func UnmarshalKey(key string, rawVal interface{}) error { return v.UnmarshalKey(key, rawVal) }
func (v *Viper) UnmarshalKey(key string, rawVal interface{}) error {
err := decode(v.Get(key), defaultDecoderConfig(rawVal))
if err != nil {
return err
@@ -779,11 +756,9 @@ func (v *Viper) UnmarshalKey(key string, rawVal interface{}, opts ...DecoderConf
// Unmarshal unmarshals the config into a Struct. Make sure that the tags
// on the fields of the structure are properly set.
func Unmarshal(rawVal interface{}, opts ...DecoderConfigOption) error {
return v.Unmarshal(rawVal, opts...)
}
func (v *Viper) Unmarshal(rawVal interface{}, opts ...DecoderConfigOption) error {
err := decode(v.AllSettings(), defaultDecoderConfig(rawVal, opts...))
func Unmarshal(rawVal interface{}) error { return v.Unmarshal(rawVal) }
func (v *Viper) Unmarshal(rawVal interface{}) error {
err := decode(v.AllSettings(), defaultDecoderConfig(rawVal))
if err != nil {
return err
@@ -796,8 +771,8 @@ func (v *Viper) Unmarshal(rawVal interface{}, opts ...DecoderConfigOption) error
// defaultDecoderConfig returns default mapsstructure.DecoderConfig with suppot
// of time.Duration values & string slices
func defaultDecoderConfig(output interface{}, opts ...DecoderConfigOption) *mapstructure.DecoderConfig {
c := &mapstructure.DecoderConfig{
func defaultDecoderConfig(output interface{}) *mapstructure.DecoderConfig {
return &mapstructure.DecoderConfig{
Metadata: nil,
Result: output,
WeaklyTypedInput: true,
@@ -806,10 +781,6 @@ func defaultDecoderConfig(output interface{}, opts ...DecoderConfigOption) *maps
mapstructure.StringToSliceHookFunc(","),
),
}
for _, opt := range opts {
opt(c)
}
return c
}
// A wrapper around mapstructure.Decode that mimics the WeakDecode functionality
-46
View File
@@ -7,7 +7,6 @@ package viper
import (
"bytes"
"encoding/json"
"fmt"
"io"
"io/ioutil"
@@ -19,7 +18,6 @@ import (
"testing"
"time"
"github.com/mitchellh/mapstructure"
"github.com/spf13/afero"
"github.com/spf13/cast"
@@ -505,42 +503,6 @@ func TestUnmarshal(t *testing.T) {
assert.Equal(t, &config{Name: "Steve", Port: 1234, Duration: time.Second + time.Millisecond}, &C)
}
func TestUnmarshalWithDecoderOptions(t *testing.T) {
Set("credentials", "{\"foo\":\"bar\"}")
opt := DecodeHook(mapstructure.ComposeDecodeHookFunc(
mapstructure.StringToTimeDurationHookFunc(),
mapstructure.StringToSliceHookFunc(","),
// Custom Decode Hook Function
func(rf reflect.Kind, rt reflect.Kind, data interface{}) (interface{}, error) {
if rf != reflect.String || rt != reflect.Map {
return data, nil
}
m := map[string]string{}
raw := data.(string)
if raw == "" {
return m, nil
}
return m, json.Unmarshal([]byte(raw), &m)
},
))
type config struct {
Credentials map[string]string
}
var C config
err := Unmarshal(&C, opt)
if err != nil {
t.Fatalf("unable to decode into struct, %v", err)
}
assert.Equal(t, &config{
Credentials: map[string]string{"foo": "bar"},
}, &C)
}
func TestBindPFlags(t *testing.T) {
v := New() // create independent Viper object
flagSet := pflag.NewFlagSet("test", pflag.ContinueOnError)
@@ -1106,10 +1068,6 @@ func TestMergeConfig(t *testing.T) {
t.Fatalf("lagrenum != 765432101234567, = %d", pop)
}
if pop := v.GetInt32("hello.pop"); pop != int32(37890) {
t.Fatalf("pop != 37890, = %d", pop)
}
if pop := v.GetInt64("hello.lagrenum"); pop != int64(765432101234567) {
t.Fatalf("int64 lagrenum != 765432101234567, = %d", pop)
}
@@ -1134,10 +1092,6 @@ func TestMergeConfig(t *testing.T) {
t.Fatalf("lagrenum != 7654321001234567, = %d", pop)
}
if pop := v.GetInt32("hello.pop"); pop != int32(45000) {
t.Fatalf("pop != 45000, = %d", pop)
}
if pop := v.GetInt64("hello.lagrenum"); pop != int64(7654321001234567) {
t.Fatalf("int64 lagrenum != 7654321001234567, = %d", pop)
}