From b53595fb56a492ecef90ee0457595a999eb6ec15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Pedersen?= Date: Mon, 18 Jul 2016 23:48:14 +0200 Subject: [PATCH 01/17] Bump Travis to Go 1.6.3 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 4bb6878..f27ab60 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,7 @@ language: go go: - 1.4.3 - 1.5.4 - - 1.6.2 + - 1.6.3 - tip os: From 7402856f06d639275f36058cd60fb1d8a10d2a52 Mon Sep 17 00:00:00 2001 From: Schley Andrew Kutz Date: Fri, 5 Aug 2016 02:15:24 -0500 Subject: [PATCH 02/17] Handle TOML Library Licensing This patch updates the package used for parsing TOML content from "github.com/BurntSushi/toml" to "github.com/pelletier/go-toml" as the latter uses a more accepted OSS license (MIT), enabling the inclusion of Viper or projects that depend on Viper in projects that have licensing requirements incongruent with the license of the previous TOML package. This patch replaces the PR https://github.com/spf13/viper/pull/208 after discussing the matter with @spf13 and deciding to update the TOML parser instead of making TOML build-optional. --- util.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/util.go b/util.go index 0cc4553..3c4a320 100644 --- a/util.go +++ b/util.go @@ -21,9 +21,9 @@ import ( "strings" "unicode" - "github.com/BurntSushi/toml" "github.com/hashicorp/hcl" "github.com/magiconair/properties" + toml "github.com/pelletier/go-toml" "github.com/spf13/cast" jww "github.com/spf13/jwalterweatherman" "gopkg.in/yaml.v2" @@ -155,9 +155,14 @@ func unmarshallConfigReader(in io.Reader, c map[string]interface{}, configType s } case "toml": - if _, err := toml.Decode(buf.String(), &c); err != nil { + tree, err := toml.LoadReader(buf) + if err != nil { return ConfigParseError{err} } + tmap := tree.ToMap() + for k, v := range tmap { + c[k] = v + } case "properties", "props", "prop": var p *properties.Properties From 6d2589cd85af2ffe1b01db0c6aebb5b68d9e87e4 Mon Sep 17 00:00:00 2001 From: Bryan Liles Date: Fri, 5 Aug 2016 03:15:51 -0400 Subject: [PATCH 03/17] Update Readme with doit's new location doit has been moved and renamed to doctl --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cad242d..4ebd8dd 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Many Go projects are built using Viper including: * [Nanobox](https://github.com/nanobox-io/nanobox)/[Nanopack](https://github.com/nanopack) * [Docker Notary](https://github.com/docker/Notary) * [BloomApi](https://www.bloomapi.com/) -* [DOIt](https://github.com/bryanl/doit) +* [doctl(https://github.com/digitalocean/doctl) [![Build Status](https://travis-ci.org/spf13/viper.svg)](https://travis-ci.org/spf13/viper) [![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) From 64dc6f681062822d3823f74c615e3f6c1f79a30c Mon Sep 17 00:00:00 2001 From: Chuanjian Wang Date: Fri, 5 Aug 2016 15:16:55 +0800 Subject: [PATCH 04/17] Add GetInt64 --- viper.go | 6 ++++++ viper_test.go | 18 ++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/viper.go b/viper.go index a2633b0..e5a360a 100644 --- a/viper.go +++ b/viper.go @@ -551,6 +551,12 @@ func (v *Viper) GetInt(key string) int { return cast.ToInt(v.Get(key)) } +// 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 { + return cast.ToInt64(v.Get(key)) +} + // Returns the value associated with the key as a float64 func GetFloat64(key string) float64 { return v.GetFloat64(key) } func (v *Viper) GetFloat64(key string) float64 { diff --git a/viper_test.go b/viper_test.go index 858caff..aa9d7fe 100644 --- a/viper_test.go +++ b/viper_test.go @@ -763,6 +763,7 @@ func TestSub(t *testing.T) { var yamlMergeExampleTgt = []byte(` hello: pop: 37890 + lagrenum: 765432101234567 world: - us - uk @@ -773,6 +774,7 @@ hello: var yamlMergeExampleSrc = []byte(` hello: pop: 45000 + lagrenum: 7654321001234567 universe: - mw - ad @@ -790,6 +792,14 @@ func TestMergeConfig(t *testing.T) { t.Fatalf("pop != 37890, = %d", pop) } + if pop := v.GetInt("hello.lagrenum"); pop != 765432101234567 { + t.Fatalf("lagrenum != 765432101234567, = %d", pop) + } + + if pop := v.GetInt64("hello.lagrenum"); pop != int64(765432101234567) { + t.Fatalf("int64 lagrenum != 765432101234567, = %d", pop) + } + if world := v.GetStringSlice("hello.world"); len(world) != 4 { t.Fatalf("len(world) != 4, = %d", len(world)) } @@ -806,6 +816,14 @@ func TestMergeConfig(t *testing.T) { t.Fatalf("pop != 45000, = %d", pop) } + if pop := v.GetInt("hello.lagrenum"); pop != 7654321001234567 { + t.Fatalf("lagrenum != 7654321001234567, = %d", pop) + } + + if pop := v.GetInt64("hello.lagrenum"); pop != int64(7654321001234567) { + t.Fatalf("int64 lagrenum != 7654321001234567, = %d", pop) + } + if world := v.GetStringSlice("hello.world"); len(world) != 4 { t.Fatalf("len(world) != 4, = %d", len(world)) } From 5619c0edbec91139df79dd0d0d8d4967f4646a08 Mon Sep 17 00:00:00 2001 From: Roland Schilter Date: Fri, 5 Aug 2016 09:18:19 +0200 Subject: [PATCH 05/17] Reset cache on config name change I stumbled over this when trying to merge multiple configs. ``` viper.SetConfigName("default") err := viper.MergeInConfig() ``` which caches file path resolvemenet in `v.configFile` and then ``` viper.SetConfigName("prod") err := viper.MergeInConfig() ``` which reuses `v.configFile` without updating it accordingly to the new name. See https://github.com/spf13/viper/blob/c1ccc378a054ea8d4e38d8c67f6938d4760b53dd/viper.go#L1240 --- viper.go | 1 + viper_test.go | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/viper.go b/viper.go index e5a360a..d800395 100644 --- a/viper.go +++ b/viper.go @@ -1214,6 +1214,7 @@ func SetConfigName(in string) { v.SetConfigName(in) } func (v *Viper) SetConfigName(in string) { if in != "" { v.configName = in + v.configFile = "" } } diff --git a/viper_test.go b/viper_test.go index aa9d7fe..0c0c7e5 100644 --- a/viper_test.go +++ b/viper_test.go @@ -901,3 +901,9 @@ func TestUnmarshalingWithAliases(t *testing.T) { assert.Equal(t, &C, &config{Id: 1, FirstName: "Steve", Surname: "Owen"}) } + +func TestSetConfigNameClearsFileCache(t *testing.T) { + SetConfigFile("/tmp/config.yaml") + SetConfigName("default") + assert.Empty(t, v.getConfigFile()) +} From 4cf0bd27897685ffc5c5409b6a2f8ff5b04cf525 Mon Sep 17 00:00:00 2001 From: Matthieu Grieger Date: Fri, 5 Aug 2016 00:24:49 -0700 Subject: [PATCH 06/17] Add support for Afero filesystems --- util.go | 2 +- viper.go | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/util.go b/util.go index 3c4a320..6b34e14 100644 --- a/util.go +++ b/util.go @@ -77,7 +77,7 @@ func absPathify(inPath string) string { // Check if File / Directory Exists func exists(path string) (bool, error) { - _, err := os.Stat(path) + _, err := fs.Stat(path) if err == nil { return true, nil } diff --git a/viper.go b/viper.go index d800395..ba3c190 100644 --- a/viper.go +++ b/viper.go @@ -23,7 +23,6 @@ import ( "bytes" "fmt" "io" - "io/ioutil" "log" "os" "path/filepath" @@ -33,15 +32,18 @@ import ( "github.com/fsnotify/fsnotify" "github.com/mitchellh/mapstructure" + "github.com/spf13/afero" "github.com/spf13/cast" jww "github.com/spf13/jwalterweatherman" "github.com/spf13/pflag" ) var v *Viper +var fs afero.Fs func init() { v = New() + fs = afero.NewOsFs() } type remoteConfigFactory interface { @@ -936,7 +938,7 @@ func (v *Viper) ReadInConfig() error { return UnsupportedConfigError(v.getConfigType()) } - file, err := ioutil.ReadFile(v.getConfigFile()) + file, err := afero.ReadFile(fs, v.getConfigFile()) if err != nil { return err } @@ -954,7 +956,7 @@ func (v *Viper) MergeInConfig() error { return UnsupportedConfigError(v.getConfigType()) } - file, err := ioutil.ReadFile(v.getConfigFile()) + file, err := afero.ReadFile(fs, v.getConfigFile()) if err != nil { return err } From d0c2644870d873080734367010e57b96a0234259 Mon Sep 17 00:00:00 2001 From: Albert Date: Fri, 5 Aug 2016 12:25:24 +0500 Subject: [PATCH 07/17] Add dot in BindPFlag comment --- viper.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/viper.go b/viper.go index ba3c190..e39a564 100644 --- a/viper.go +++ b/viper.go @@ -668,8 +668,8 @@ func (v *Viper) BindPFlags(flags *pflag.FlagSet) (err error) { return v.BindFlagValues(pflagValueSet{flags}) } -// Bind a specific key to a pflag (as used by cobra) -// Example(where serverCmd is a Cobra instance): +// Bind a specific key to a pflag (as used by cobra). +// Example (where serverCmd is a Cobra instance): // // serverCmd.Flags().Int("port", 1138, "Port to run Application server on") // Viper.BindPFlag("port", serverCmd.Flags().Lookup("port")) From a59dcccc828173bb1f58d1650619724b59d18af5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Pedersen?= Date: Fri, 5 Aug 2016 09:45:58 +0200 Subject: [PATCH 08/17] Move the Afero fs to the Viper type And make a exported setter for it. --- util.go | 2 +- viper.go | 16 ++++++++++++---- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/util.go b/util.go index 6b34e14..fe6cb45 100644 --- a/util.go +++ b/util.go @@ -77,7 +77,7 @@ func absPathify(inPath string) string { // Check if File / Directory Exists func exists(path string) (bool, error) { - _, err := fs.Stat(path) + _, err := v.fs.Stat(path) if err == nil { return true, nil } diff --git a/viper.go b/viper.go index e39a564..cdf2113 100644 --- a/viper.go +++ b/viper.go @@ -39,11 +39,9 @@ import ( ) var v *Viper -var fs afero.Fs func init() { v = New() - fs = afero.NewOsFs() } type remoteConfigFactory interface { @@ -134,6 +132,9 @@ type Viper struct { // A set of paths to look for the config file in configPaths []string + // The filesystem to read config from. + fs afero.Fs + // A set of remote providers to search for the configuration remoteProviders []*defaultRemoteProvider @@ -163,6 +164,7 @@ func New() *Viper { v := new(Viper) v.keyDelim = "." v.configName = "config" + v.fs = afero.NewOsFs() v.config = make(map[string]interface{}) v.override = make(map[string]interface{}) v.defaults = make(map[string]interface{}) @@ -938,7 +940,7 @@ func (v *Viper) ReadInConfig() error { return UnsupportedConfigError(v.getConfigType()) } - file, err := afero.ReadFile(fs, v.getConfigFile()) + file, err := afero.ReadFile(v.fs, v.getConfigFile()) if err != nil { return err } @@ -956,7 +958,7 @@ func (v *Viper) MergeInConfig() error { return UnsupportedConfigError(v.getConfigType()) } - file, err := afero.ReadFile(fs, v.getConfigFile()) + file, err := afero.ReadFile(v.fs, v.getConfigFile()) if err != nil { return err } @@ -1210,6 +1212,12 @@ func (v *Viper) AllSettings() map[string]interface{} { return m } +// Se the filesystem to use to read configuration. +func SetFs(fs afero.Fs) { v.SetFs(fs) } +func (v *Viper) SetFs(fs afero.Fs) { + v.fs = fs +} + // Name for the config file. // Does not include extension. func SetConfigName(in string) { v.SetConfigName(in) } From abafbf243b9583ac1360ae4ef680d8acaa361089 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Pedersen?= Date: Fri, 5 Aug 2016 11:20:27 +0200 Subject: [PATCH 09/17] Revert "Handle TOML Library Licensing" It breaks Hugo, will have to test/investigate. Erro when building Hugo docs: ``` ERROR: 2016/08/05 11:19:23 site.go:1208: unable to process menus in site config ERROR: 2016/08/05 11:19:23 site.go:1209: Unable to Cast map[string]interface {}{"pre":"", "weight":-20, "url":"/commands/", "name":"Hugo Cmd Reference", "identifier":"commands"} of type map[string]interface {} to []interface{} ``` This reverts commit 7402856f06d639275f36058cd60fb1d8a10d2a52. --- util.go | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/util.go b/util.go index fe6cb45..46f923c 100644 --- a/util.go +++ b/util.go @@ -21,9 +21,9 @@ import ( "strings" "unicode" + "github.com/BurntSushi/toml" "github.com/hashicorp/hcl" "github.com/magiconair/properties" - toml "github.com/pelletier/go-toml" "github.com/spf13/cast" jww "github.com/spf13/jwalterweatherman" "gopkg.in/yaml.v2" @@ -155,14 +155,9 @@ func unmarshallConfigReader(in io.Reader, c map[string]interface{}, configType s } case "toml": - tree, err := toml.LoadReader(buf) - if err != nil { + if _, err := toml.Decode(buf.String(), &c); err != nil { return ConfigParseError{err} } - tmap := tree.ToMap() - for k, v := range tmap { - c[k] = v - } case "properties", "props", "prop": var p *properties.Properties From 346299ea79e446ebdddb834371ceba2e5926b732 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Pedersen?= Date: Sat, 6 Aug 2016 18:06:49 +0200 Subject: [PATCH 10/17] Add getter for global Viper --- viper.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/viper.go b/viper.go index cdf2113..f17790e 100644 --- a/viper.go +++ b/viper.go @@ -450,6 +450,11 @@ func (v *Viper) SetTypeByDefaultValue(enable bool) { v.typeByDefValue = enable } +// GetViper gets the global Viper instance. +func GetViper() *Viper { + return v +} + // Viper is essentially repository for configurations // Get can retrieve any value given the key to use // Get has the behavior of returning the value associated with the first From 654fc7bb54d0c138ef80405ff577391f79c0c32d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Pedersen?= Date: Tue, 16 Aug 2016 10:09:34 +0200 Subject: [PATCH 11/17] Bump Travis to Go 1.7 --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index f27ab60..46d5247 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,8 @@ language: go go: - - 1.4.3 - 1.5.4 - 1.6.3 + - 1.7 - tip os: @@ -12,6 +12,7 @@ os: matrix: allow_failures: - go: tip + fast_finish: true script: - go test -v ./... From fe9c8b59e176537a2a08498fe6a5e131a3b6a304 Mon Sep 17 00:00:00 2001 From: Schley Andrew Kutz Date: Sat, 20 Aug 2016 08:03:44 -0500 Subject: [PATCH 12/17] Add Hugo CI Step to Validate Viper Since Hugo is such a heavy user of Viper, this patch adds an after_success section to the Travis-CI build that validates the Viper commit by attempting to build Hugo and executing `hugo -s docs`. This patch handles issue #222. --- .travis.yml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 46d5247..e793edb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,10 +1,12 @@ +go_import_path: github.com/spf13/viper + language: go go: - 1.5.4 - 1.6.3 - 1.7 - tip - + os: - linux - osx @@ -15,5 +17,11 @@ matrix: fast_finish: true script: + - go install ./... - go test -v ./... + +after_success: + - go get -u -d github.com/spf13/hugo + - cd $GOPATH/src/github.com/spf13/hugo && make && ./hugo -s docs && cd - + sudo: false From 7fb2782df3d83e0036cc89f461ed0422628776f4 Mon Sep 17 00:00:00 2001 From: Vladimir Vivien Date: Fri, 12 Aug 2016 14:14:35 -0400 Subject: [PATCH 13/17] Handle TOML Library Licensing This patch updates the package used for parsing TOML content from "github.com/BurntSushi/toml" to "github.com/pelletier/go-toml" as the latter uses a more accepted OSS license (MIT), enabling the inclusion of Viper or projects that depend on Viper in projects that have licensing requirements incongruent with the license of the previous TOML package. Closes #228 Closes #225 Fixes #179 --- util.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/util.go b/util.go index 46f923c..fe6cb45 100644 --- a/util.go +++ b/util.go @@ -21,9 +21,9 @@ import ( "strings" "unicode" - "github.com/BurntSushi/toml" "github.com/hashicorp/hcl" "github.com/magiconair/properties" + toml "github.com/pelletier/go-toml" "github.com/spf13/cast" jww "github.com/spf13/jwalterweatherman" "gopkg.in/yaml.v2" @@ -155,9 +155,14 @@ func unmarshallConfigReader(in io.Reader, c map[string]interface{}, configType s } case "toml": - if _, err := toml.Decode(buf.String(), &c); err != nil { + tree, err := toml.LoadReader(buf) + if err != nil { return ConfigParseError{err} } + tmap := tree.ToMap() + for k, v := range tmap { + c[k] = v + } case "properties", "props", "prop": var p *properties.Properties From 16990631d4aa7e38f73dbbbf37fa13e67c648531 Mon Sep 17 00:00:00 2001 From: Albert Date: Tue, 30 Aug 2016 19:32:46 +0500 Subject: [PATCH 14/17] Fix typo in README (#227) Fixed typo & superfluous white space in README --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 4ebd8dd..cf17560 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Many Go projects are built using Viper including: * [Nanobox](https://github.com/nanobox-io/nanobox)/[Nanopack](https://github.com/nanopack) * [Docker Notary](https://github.com/docker/Notary) * [BloomApi](https://www.bloomapi.com/) -* [doctl(https://github.com/digitalocean/doctl) +* [doctl](https://github.com/digitalocean/doctl) [![Build Status](https://travis-ci.org/spf13/viper.svg)](https://travis-ci.org/spf13/viper) [![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) @@ -110,7 +110,7 @@ Gone are the days of needing to restart a server to have a config take effect, viper powered applications can read an update to a config file while running and not miss a beat. -Simply tell the viper instance to watchConfig. +Simply tell the viper instance to watchConfig. Optionally you can provide a function for Viper to run each time a change occurs. **Make sure you add all of the configPaths prior to calling `WatchConfig()`** @@ -298,7 +298,7 @@ type myFlagSet struct { func (f myFlagSet) VisitAll(fn func(FlagValue)) { for _, flag := range flags { - fn(flag) + fn(flag) } } ``` From 2f6a41490bc86fa9a8fb2fc03526a5795e904a17 Mon Sep 17 00:00:00 2001 From: Max Wolter Date: Mon, 19 Sep 2016 19:37:56 +0200 Subject: [PATCH 15/17] Prevent shadowning of keys when a nested key's value is nil. --- viper.go | 6 ++++-- viper_test.go | 9 +++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/viper.go b/viper.go index f17790e..bad121e 100644 --- a/viper.go +++ b/viper.go @@ -802,8 +802,10 @@ func (v *Viper) find(key string) interface{} { if source != nil { if reflect.TypeOf(source).Kind() == reflect.Map { val := v.searchMap(cast.ToStringMap(source), path[1:]) - jww.TRACE.Println(key, "found in nested config:", val) - return val + if val != nil { + jww.TRACE.Println(key, "found in nested config:", val) + return val + } } } } diff --git a/viper_test.go b/viper_test.go index 0c0c7e5..fdbe4d9 100644 --- a/viper_test.go +++ b/viper_test.go @@ -907,3 +907,12 @@ func TestSetConfigNameClearsFileCache(t *testing.T) { SetConfigName("default") assert.Empty(t, v.getConfigFile()) } + +func TestShadowedNestedValue(t *testing.T) { + polyester := "polyester" + initYAML() + SetDefault("clothing.shirt", polyester) + + assert.Equal(t, GetString("clothing.jacket"), "leather") + assert.Equal(t, GetString("clothing.shirt"), polyester) +} From a78f70b5b977efe08e313a9e2341c3f5457abdaf Mon Sep 17 00:00:00 2001 From: Albert Date: Tue, 20 Sep 2016 10:17:41 +0200 Subject: [PATCH 16/17] Small refactorings (#230) * Fix typo in description of UnmarshalExact * Omit 2nd values from range loops * Delete findCWD method from util (was unused) * Edit documentation according to golint * Fix documentation in util * Use RemoteProvider interface instead of defaultRemoteProvider * Fix err variable in BindFlagValues --- flags_test.go | 2 +- util.go | 33 ++------ viper.go | 205 +++++++++++++++++++++++--------------------------- viper_test.go | 2 +- 4 files changed, 100 insertions(+), 142 deletions(-) diff --git a/flags_test.go b/flags_test.go index 5489278..5bffca3 100644 --- a/flags_test.go +++ b/flags_test.go @@ -22,7 +22,7 @@ func TestBindFlagValueSet(t *testing.T) { "endpoint": "/public", } - for name, _ := range testValues { + for name := range testValues { testValues[name] = flagSet.String(name, "", "test") } diff --git a/util.go b/util.go index fe6cb45..5f93d65 100644 --- a/util.go +++ b/util.go @@ -29,12 +29,12 @@ import ( "gopkg.in/yaml.v2" ) -// Denotes failing to parse configuration file. +// ConfigParseError denotes failing to parse configuration file. type ConfigParseError struct { err error } -// Returns the formatted configuration error. +// Error returns the formatted configuration error. func (pe ConfigParseError) Error() string { return fmt.Sprintf("While parsing config: %s", pe.err.Error()) } @@ -68,10 +68,10 @@ func absPathify(inPath string) string { p, err := filepath.Abs(inPath) if err == nil { return filepath.Clean(p) - } else { - jww.ERROR.Println("Couldn't discover absolute path") - jww.ERROR.Println(err) } + + jww.ERROR.Println("Couldn't discover absolute path") + jww.ERROR.Println(err) return "" } @@ -107,29 +107,6 @@ func userHomeDir() string { return os.Getenv("HOME") } -func findCWD() (string, error) { - serverFile, err := filepath.Abs(os.Args[0]) - - if err != nil { - return "", fmt.Errorf("Can't get absolute path for executable: %v", err) - } - - path := filepath.Dir(serverFile) - realFile, err := filepath.EvalSymlinks(serverFile) - - if err != nil { - if _, err = os.Stat(serverFile + ".exe"); err == nil { - realFile = filepath.Clean(serverFile + ".exe") - } - } - - if err == nil && realFile != serverFile { - path = filepath.Dir(realFile) - } - - return path, nil -} - func unmarshallConfigReader(in io.Reader, c map[string]interface{}, configType string) error { buf := new(bytes.Buffer) buf.ReadFrom(in) diff --git a/viper.go b/viper.go index bad121e..bc1bf5e 100644 --- a/viper.go +++ b/viper.go @@ -52,40 +52,40 @@ type remoteConfigFactory interface { // RemoteConfig is optional, see the remote package var RemoteConfig remoteConfigFactory -// Denotes encountering an unsupported +// UnsupportedConfigError denotes encountering an unsupported // configuration filetype. type UnsupportedConfigError string -// Returns the formatted configuration error. +// Error returns the formatted configuration error. func (str UnsupportedConfigError) Error() string { return fmt.Sprintf("Unsupported Config Type %q", string(str)) } -// Denotes encountering an unsupported remote +// UnsupportedRemoteProviderError denotes encountering an unsupported remote // provider. Currently only etcd and Consul are // supported. type UnsupportedRemoteProviderError string -// Returns the formatted remote provider error. +// Error returns the formatted remote provider error. func (str UnsupportedRemoteProviderError) Error() string { return fmt.Sprintf("Unsupported Remote Provider Type %q", string(str)) } -// Denotes encountering an error while trying to +// RemoteConfigError denotes encountering an error while trying to // pull the configuration from the remote provider. type RemoteConfigError string -// 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)) } -// Denotes failing to find configuration file. +// ConfigFileNotFoundError denotes failing to find configuration file. type ConfigFileNotFoundError struct { name, locations string } -// Returns the formatted configuration error. +// Error returns the formatted configuration error. func (fnfe ConfigFileNotFoundError) Error() string { return fmt.Sprintf("Config File %q Not Found in %q", fnfe.name, fnfe.locations) } @@ -159,7 +159,7 @@ type Viper struct { onConfigChange func(fsnotify.Event) } -// Returns an initialized Viper instance. +// New returns an initialized Viper instance. func New() *Viper { v := new(Viper) v.keyDelim = "." @@ -220,11 +220,11 @@ type RemoteProvider interface { SecretKeyring() string } -// Universally supported extensions. -var SupportedExts []string = []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl"} +// SupportedExts are universally supported extensions. +var SupportedExts = []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl"} -// Universally supported remote providers. -var SupportedRemoteProviders []string = []string{"etcd", "consul"} +// SupportedRemoteProviders are universally supported remote providers. +var SupportedRemoteProviders = []string{"etcd", "consul"} func OnConfigChange(run func(in fsnotify.Event)) { v.OnConfigChange(run) } func (v *Viper) OnConfigChange(run func(in fsnotify.Event)) { @@ -270,7 +270,7 @@ func (v *Viper) WatchConfig() { }() } -// Explicitly define the path, name and extension of the config file +// SetConfigFile explicitly defines the path, name and extension of the config file // Viper will use this and not check any of the config paths func SetConfigFile(in string) { v.SetConfigFile(in) } func (v *Viper) SetConfigFile(in string) { @@ -279,7 +279,7 @@ func (v *Viper) SetConfigFile(in string) { } } -// Define a prefix that ENVIRONMENT variables will use. +// SetEnvPrefix defines a prefix that ENVIRONMENT variables will use. // E.g. if your prefix is "spf", the env registry // will look for env. variables that start with "SPF_" func SetEnvPrefix(in string) { v.SetEnvPrefix(in) } @@ -301,7 +301,7 @@ func (v *Viper) mergeWithEnvPrefix(in string) string { // rewriting keys many things, Ex: Get('someKey') -> some_key // (cammel case to snake case for JSON keys perhaps) -// getEnv s a wrapper around os.Getenv which replaces characters in the original +// getEnv is a wrapper around os.Getenv which replaces characters in the original // key. This allows env vars which have different keys then the config object // keys func (v *Viper) getEnv(key string) string { @@ -311,11 +311,11 @@ func (v *Viper) getEnv(key string) string { return os.Getenv(key) } -// Return the file used to populate the config registry +// ConfigFileUsed returns the file used to populate the config registry func ConfigFileUsed() string { return v.ConfigFileUsed() } func (v *Viper) ConfigFileUsed() string { return v.configFile } -// Add a path for Viper to search for the config file in. +// AddConfigPath adds a path for Viper to search for the config file in. // Can be called multiple times to define multiple search paths. func AddConfigPath(in string) { v.AddConfigPath(in) } func (v *Viper) AddConfigPath(in string) { @@ -455,8 +455,7 @@ func GetViper() *Viper { return v } -// Viper is essentially repository for configurations -// Get can retrieve any value given the key to use +// Get can retrieve any value given the key to use. // Get has the behavior of returning the value associated with the first // place from where it is set. Viper will check in the following order: // override, flag, env, config file, key/value store, default @@ -529,7 +528,7 @@ func (v *Viper) Get(key string) interface{} { return val } -// Returns new Viper instance representing a sub tree of this instance +// Sub returns new Viper instance representing a sub tree of this instance. func Sub(key string) *Viper { return v.Sub(key) } func (v *Viper) Sub(key string) *Viper { subv := New() @@ -537,78 +536,77 @@ func (v *Viper) Sub(key string) *Viper { if reflect.TypeOf(data).Kind() == reflect.Map { subv.config = cast.ToStringMap(data) return subv - } else { - return nil } + return nil } -// Returns the value associated with the key as a string +// GetString returns the value associated with the key as a string. func GetString(key string) string { return v.GetString(key) } func (v *Viper) GetString(key string) string { return cast.ToString(v.Get(key)) } -// Returns the value associated with the key as a boolean +// GetBool returns the value associated with the key as a boolean. func GetBool(key string) bool { return v.GetBool(key) } func (v *Viper) GetBool(key string) bool { return cast.ToBool(v.Get(key)) } -// Returns the value associated with the key as an integer +// GetInt returns the value associated with the key as an integer. func GetInt(key string) int { return v.GetInt(key) } func (v *Viper) GetInt(key string) int { return cast.ToInt(v.Get(key)) } -// Returns the value associated with the key as an integer +// 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 { return cast.ToInt64(v.Get(key)) } -// Returns the value associated with the key as a float64 +// GetFloat64 returns the value associated with the key as a float64. func GetFloat64(key string) float64 { return v.GetFloat64(key) } func (v *Viper) GetFloat64(key string) float64 { return cast.ToFloat64(v.Get(key)) } -// Returns the value associated with the key as time +// GetTime returns the value associated with the key as time. func GetTime(key string) time.Time { return v.GetTime(key) } func (v *Viper) GetTime(key string) time.Time { return cast.ToTime(v.Get(key)) } -// Returns the value associated with the key as a duration +// GetDuration returns the value associated with the key as a duration. func GetDuration(key string) time.Duration { return v.GetDuration(key) } func (v *Viper) GetDuration(key string) time.Duration { return cast.ToDuration(v.Get(key)) } -// Returns the value associated with the key as a slice of strings +// GetStringSlice returns the value associated with the key as a slice of strings. func GetStringSlice(key string) []string { return v.GetStringSlice(key) } func (v *Viper) GetStringSlice(key string) []string { return cast.ToStringSlice(v.Get(key)) } -// Returns the value associated with the key as a map of interfaces +// GetStringMap returns the value associated with the key as a map of interfaces. func GetStringMap(key string) map[string]interface{} { return v.GetStringMap(key) } func (v *Viper) GetStringMap(key string) map[string]interface{} { return cast.ToStringMap(v.Get(key)) } -// Returns the value associated with the key as a map of strings +// GetStringMapString returns the value associated with the key as a map of strings. func GetStringMapString(key string) map[string]string { return v.GetStringMapString(key) } func (v *Viper) GetStringMapString(key string) map[string]string { return cast.ToStringMapString(v.Get(key)) } -// Returns the value associated with the key as a map to a slice of strings. +// GetStringMapStringSlice returns the value associated with the key as a map to a slice of strings. func GetStringMapStringSlice(key string) map[string][]string { return v.GetStringMapStringSlice(key) } func (v *Viper) GetStringMapStringSlice(key string) map[string][]string { return cast.ToStringMapStringSlice(v.Get(key)) } -// Returns the size of the value associated with the given key +// GetSizeInBytes returns the size of the value associated with the given key // in bytes. func GetSizeInBytes(key string) uint { return v.GetSizeInBytes(key) } func (v *Viper) GetSizeInBytes(key string) uint { @@ -616,13 +614,13 @@ func (v *Viper) GetSizeInBytes(key string) uint { return parseSizeInBytes(sizeStr) } -// Takes a single key and unmarshals it into a Struct +// UnmarshalKey takes a single key and unmarshals it into a Struct. func UnmarshalKey(key string, rawVal interface{}) error { return v.UnmarshalKey(key, rawVal) } func (v *Viper) UnmarshalKey(key string, rawVal interface{}) error { return mapstructure.Decode(v.Get(key), rawVal) } -// Unmarshals the config into a Struct. Make sure that the tags +// 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{}) error { return v.Unmarshal(rawVal) } func (v *Viper) Unmarshal(rawVal interface{}) error { @@ -638,7 +636,7 @@ func (v *Viper) Unmarshal(rawVal interface{}) error { } // A wrapper around mapstructure.Decode that mimics the WeakDecode functionality -// while erroring on non existing vals in the destination struct +// while erroring on non existing vals in the destination struct. func weakDecodeExact(input, output interface{}) error { config := &mapstructure.DecoderConfig{ ErrorUnused: true, @@ -654,8 +652,8 @@ func weakDecodeExact(input, output interface{}) error { return decoder.Decode(input) } -// Unmarshals the config into a Struct, erroring if a field is non-existant -// in the destination struct +// UnmarshalExact unmarshals the config into a Struct, erroring if a field is nonexistent +// in the destination struct. func (v *Viper) UnmarshalExact(rawVal interface{}) error { err := weakDecodeExact(v.AllSettings(), rawVal) @@ -668,27 +666,27 @@ func (v *Viper) UnmarshalExact(rawVal interface{}) error { return nil } -// Bind a full flag set to the configuration, using each flag's long +// BindPFlags binds a full flag set to the configuration, using each flag's long // name as the config key. -func BindPFlags(flags *pflag.FlagSet) (err error) { return v.BindPFlags(flags) } -func (v *Viper) BindPFlags(flags *pflag.FlagSet) (err error) { +func BindPFlags(flags *pflag.FlagSet) error { return v.BindPFlags(flags) } +func (v *Viper) BindPFlags(flags *pflag.FlagSet) error { return v.BindFlagValues(pflagValueSet{flags}) } -// Bind a specific key to a pflag (as used by cobra). +// BindPFlag binds a specific key to a pflag (as used by cobra). // Example (where serverCmd is a Cobra instance): // // serverCmd.Flags().Int("port", 1138, "Port to run Application server on") // Viper.BindPFlag("port", serverCmd.Flags().Lookup("port")) // -func BindPFlag(key string, flag *pflag.Flag) (err error) { return v.BindPFlag(key, flag) } -func (v *Viper) BindPFlag(key string, flag *pflag.Flag) (err error) { +func BindPFlag(key string, flag *pflag.Flag) error { return v.BindPFlag(key, flag) } +func (v *Viper) BindPFlag(key string, flag *pflag.Flag) error { return v.BindFlagValue(key, pflagValue{flag}) } -// Bind a full FlagValue set to the configuration, using each flag's long +// BindFlagValues binds a full FlagValue set to the configuration, using each flag's long // name as the config key. -func BindFlagValues(flags FlagValueSet) (err error) { return v.BindFlagValues(flags) } +func BindFlagValues(flags FlagValueSet) error { return v.BindFlagValues(flags) } func (v *Viper) BindFlagValues(flags FlagValueSet) (err error) { flags.VisitAll(func(flag FlagValue) { if err = v.BindFlagValue(flag.Name(), flag); err != nil { @@ -698,14 +696,14 @@ func (v *Viper) BindFlagValues(flags FlagValueSet) (err error) { return nil } -// Bind a specific key to a FlagValue. +// BindFlagValue binds a specific key to a FlagValue. // Example(where serverCmd is a Cobra instance): // // serverCmd.Flags().Int("port", 1138, "Port to run Application server on") // Viper.BindFlagValue("port", serverCmd.Flags().Lookup("port")) // -func BindFlagValue(key string, flag FlagValue) (err error) { return v.BindFlagValue(key, flag) } -func (v *Viper) BindFlagValue(key string, flag FlagValue) (err error) { +func BindFlagValue(key string, flag FlagValue) error { return v.BindFlagValue(key, flag) } +func (v *Viper) BindFlagValue(key string, flag FlagValue) error { if flag == nil { return fmt.Errorf("flag for %q is nil", key) } @@ -713,12 +711,12 @@ func (v *Viper) BindFlagValue(key string, flag FlagValue) (err error) { return nil } -// Binds a Viper key to a ENV variable -// ENV variables are case sensitive +// BindEnv binds a Viper key to a ENV variable. +// ENV variables are case sensitive. // If only a key is provided, it will use the env key matching the key, uppercased. // EnvPrefix will be used when set when env name is not provided. -func BindEnv(input ...string) (err error) { return v.BindEnv(input...) } -func (v *Viper) BindEnv(input ...string) (err error) { +func BindEnv(input ...string) error { return v.BindEnv(input...) } +func (v *Viper) BindEnv(input ...string) error { var key, envkey string if len(input) == 0 { return fmt.Errorf("BindEnv missing key to bind to") @@ -737,10 +735,10 @@ func (v *Viper) BindEnv(input ...string) (err error) { return nil } -// Given a key, find the value +// Given a key, find the value. // Viper will check in the following order: -// flag, env, config file, key/value store, default -// Viper will check to see if an alias exists first +// flag, env, config file, key/value store, default. +// Viper will check to see if an alias exists first. func (v *Viper) find(key string) interface{} { var val interface{} var exists bool @@ -783,9 +781,8 @@ func (v *Viper) find(key string) interface{} { if val = v.getEnv(envkey); val != "" { jww.TRACE.Println(envkey, "found in environment with val:", val) return val - } else { - jww.TRACE.Println(envkey, "env value unset:") } + jww.TRACE.Println(envkey, "env value unset:") } val, exists = v.config[key] @@ -825,7 +822,7 @@ func (v *Viper) find(key string) interface{} { return nil } -// Check to see if the key has been set in any of the data locations +// IsSet checks to see if the key has been set in any of the data locations. func IsSet(key string) bool { return v.IsSet(key) } func (v *Viper) IsSet(key string) bool { path := strings.Split(key, v.keyDelim) @@ -845,7 +842,7 @@ func (v *Viper) IsSet(key string) bool { return val != nil } -// Have Viper check ENV variables for all +// AutomaticEnv has Viper check ENV variables for all. // keys set in config, default & flags func AutomaticEnv() { v.AutomaticEnv() } func (v *Viper) AutomaticEnv() { @@ -904,12 +901,11 @@ func (v *Viper) realKey(key string) string { if exists { jww.DEBUG.Println("Alias", key, "to", newkey) return v.realKey(newkey) - } else { - return key } + return key } -// Check to see if the given key (or an alias) is in the config file +// InConfig checks to see if the given key (or an alias) is in the config file. func InConfig(key string) bool { return v.InConfig(key) } func (v *Viper) InConfig(key string) bool { // if the requested key is an alias, then return the proper key @@ -919,7 +915,7 @@ func (v *Viper) InConfig(key string) bool { return exists } -// Set the default value for this key. +// SetDefault sets the default value for this key. // Default only used when no value is provided by the user via flag, config or ENV. func SetDefault(key string, value interface{}) { v.SetDefault(key, value) } func (v *Viper) SetDefault(key string, value interface{}) { @@ -928,9 +924,9 @@ func (v *Viper) SetDefault(key string, value interface{}) { v.defaults[key] = value } -// Sets the value for the key in the override regiser. +// Set sets the value for the key in the override regiser. // Will be used instead of values obtained via -// flags, config file, ENV, default, or key/value store +// flags, config file, ENV, default, or key/value store. func Set(key string, value interface{}) { v.Set(key, value) } func (v *Viper) Set(key string, value interface{}) { // If alias passed in, then set the proper override @@ -938,7 +934,7 @@ func (v *Viper) Set(key string, value interface{}) { v.override[key] = value } -// Viper will discover and load the configuration file from disk +// ReadInConfig will discover and load the configuration file from disk // and key/value stores, searching in one of the defined paths. func ReadInConfig() error { return v.ReadInConfig() } func (v *Viper) ReadInConfig() error { @@ -973,7 +969,7 @@ func (v *Viper) MergeInConfig() error { return v.MergeConfig(bytes.NewReader(file)) } -// Viper will read a configuration file, setting existing keys to nil if the +// ReadConfig will read a configuration file, setting existing keys to nil if the // key does not exist in the file. func ReadConfig(in io.Reader) error { return v.ReadConfig(in) } func (v *Viper) ReadConfig(in io.Reader) error { @@ -1075,34 +1071,20 @@ func mergeMaps( } } -// func ReadBufConfig(buf *bytes.Buffer) error { return v.ReadBufConfig(buf) } -// func (v *Viper) ReadBufConfig(buf *bytes.Buffer) error { -// v.config = make(map[string]interface{}) -// return v.unmarshalReader(buf, v.config) -// } - -// Attempts to get configuration from a remote source +// ReadRemoteConfig attempts to get configuration from a remote source // and read it in the remote configuration registry. func ReadRemoteConfig() error { return v.ReadRemoteConfig() } func (v *Viper) ReadRemoteConfig() error { - err := v.getKeyValueConfig() - if err != nil { - return err - } - return nil + return v.getKeyValueConfig() } func WatchRemoteConfig() error { return v.WatchRemoteConfig() } func (v *Viper) WatchRemoteConfig() error { - err := v.watchKeyValueConfig() - if err != nil { - return err - } - return nil + return v.watchKeyValueConfig() } -// Unmarshall a Reader into a map -// Should probably be an unexported function +// Unmarshall a Reader into a map. +// Should probably be an unexported function. func unmarshalReader(in io.Reader, c map[string]interface{}) error { return v.unmarshalReader(in, c) } @@ -1118,7 +1100,7 @@ func (v *Viper) insensitiviseMaps() { insensitiviseMap(v.kvstore) } -// retrieve the first found remote configuration +// Retrieve the first found remote configuration. func (v *Viper) getKeyValueConfig() error { if RemoteConfig == nil { return RemoteConfigError("Enable the remote features by doing a blank import of the viper/remote package: '_ github.com/spf13/viper/remote'") @@ -1135,8 +1117,7 @@ func (v *Viper) getKeyValueConfig() error { return RemoteConfigError("No Files Found") } -func (v *Viper) getRemoteConfig(provider *defaultRemoteProvider) (map[string]interface{}, error) { - +func (v *Viper) getRemoteConfig(provider RemoteProvider) (map[string]interface{}, error) { reader, err := RemoteConfig.Get(provider) if err != nil { return nil, err @@ -1145,7 +1126,7 @@ func (v *Viper) getRemoteConfig(provider *defaultRemoteProvider) (map[string]int return v.kvstore, err } -// retrieve the first found remote configuration +// Retrieve the first found remote configuration. func (v *Viper) watchKeyValueConfig() error { for _, rp := range v.remoteProviders { val, err := v.watchRemoteConfig(rp) @@ -1158,7 +1139,7 @@ func (v *Viper) watchKeyValueConfig() error { return RemoteConfigError("No Files Found") } -func (v *Viper) watchRemoteConfig(provider *defaultRemoteProvider) (map[string]interface{}, error) { +func (v *Viper) watchRemoteConfig(provider RemoteProvider) (map[string]interface{}, error) { reader, err := RemoteConfig.Watch(provider) if err != nil { return nil, err @@ -1167,48 +1148,48 @@ func (v *Viper) watchRemoteConfig(provider *defaultRemoteProvider) (map[string]i return v.kvstore, err } -// Return all keys regardless where they are set +// AllKeys returns all keys regardless where they are set. func AllKeys() []string { return v.AllKeys() } func (v *Viper) AllKeys() []string { m := map[string]struct{}{} - for key, _ := range v.defaults { + for key := range v.defaults { m[strings.ToLower(key)] = struct{}{} } - for key, _ := range v.pflags { + for key := range v.pflags { m[strings.ToLower(key)] = struct{}{} } - for key, _ := range v.env { + for key := range v.env { m[strings.ToLower(key)] = struct{}{} } - for key, _ := range v.config { + for key := range v.config { m[strings.ToLower(key)] = struct{}{} } - for key, _ := range v.kvstore { + for key := range v.kvstore { m[strings.ToLower(key)] = struct{}{} } - for key, _ := range v.override { + for key := range v.override { m[strings.ToLower(key)] = struct{}{} } - for key, _ := range v.aliases { + for key := range v.aliases { m[strings.ToLower(key)] = struct{}{} } a := []string{} - for x, _ := range m { + for x := range m { a = append(a, x) } return a } -// Return all settings as a map[string]interface{} +// AllSettings returns all settings as a map[string]interface{}. func AllSettings() map[string]interface{} { return v.AllSettings() } func (v *Viper) AllSettings() map[string]interface{} { m := map[string]interface{}{} @@ -1219,13 +1200,13 @@ func (v *Viper) AllSettings() map[string]interface{} { return m } -// Se the filesystem to use to read configuration. +// SetFs sets the filesystem to use to read configuration. func SetFs(fs afero.Fs) { v.SetFs(fs) } func (v *Viper) SetFs(fs afero.Fs) { v.fs = fs } -// Name for the config file. +// SetConfigName sets name for the config file. // Does not include extension. func SetConfigName(in string) { v.SetConfigName(in) } func (v *Viper) SetConfigName(in string) { @@ -1235,7 +1216,7 @@ func (v *Viper) SetConfigName(in string) { } } -// Sets the type of the configuration returned by the +// SetConfigType sets the type of the configuration returned by the // remote source, e.g. "json". func SetConfigType(in string) { v.SetConfigType(in) } func (v *Viper) SetConfigType(in string) { @@ -1254,9 +1235,9 @@ func (v *Viper) getConfigType() string { if len(ext) > 1 { return ext[1:] - } else { - return "" } + + return "" } func (v *Viper) getConfigFile() string { @@ -1287,8 +1268,8 @@ func (v *Viper) searchInPath(in string) (filename string) { return "" } -// search all configPaths for any config file. -// Returns the first path that exists (and is a config file) +// Search all configPaths for any config file. +// Returns the first path that exists (and is a config file). func (v *Viper) findConfigFile() (string, error) { jww.INFO.Println("Searching for config in ", v.configPaths) @@ -1302,7 +1283,7 @@ func (v *Viper) findConfigFile() (string, error) { return "", ConfigFileNotFoundError{v.configName, fmt.Sprintf("%s", v.configPaths)} } -// Prints all configuration registries for debugging +// Debug prints all configuration registries for debugging // purposes. func Debug() { v.Debug() } func (v *Viper) Debug() { diff --git a/viper_test.go b/viper_test.go index fdbe4d9..cf897d6 100644 --- a/viper_test.go +++ b/viper_test.go @@ -491,7 +491,7 @@ func TestBindPFlags(t *testing.T) { "endpoint": "/public", } - for name, _ := range testValues { + for name := range testValues { testValues[name] = flagSet.String(name, "", "test") } From ed0a9674c6ef3646e218d8bb70708d250e94354b Mon Sep 17 00:00:00 2001 From: Cameron Moore Date: Thu, 22 Sep 2016 13:19:24 -0500 Subject: [PATCH 17/17] Fix retrieval of pflag stringSlice (#240) Fixes #112 Changes some logging directives to use Printf --- viper.go | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/viper.go b/viper.go index bc1bf5e..8a32482 100644 --- a/viper.go +++ b/viper.go @@ -749,12 +749,15 @@ func (v *Viper) find(key string) interface{} { // PFlag Override first flag, exists := v.pflags[key] if exists && flag.HasChanged() { - jww.TRACE.Println(key, "found in override (via pflag):", flag.ValueString()) + jww.TRACE.Printf("%q found in pflag override (%s): %s", key, flag.ValueType(), flag.ValueString()) switch flag.ValueType() { case "int", "int8", "int16", "int32", "int64": return cast.ToInt(flag.ValueString()) case "bool": return cast.ToBool(flag.ValueString()) + case "stringSlice": + s := strings.TrimPrefix(flag.ValueString(), "[") + return strings.TrimSuffix(s, "]") default: return flag.ValueString() } @@ -762,7 +765,7 @@ func (v *Viper) find(key string) interface{} { val, exists = v.override[key] if exists { - jww.TRACE.Println(key, "found in override:", val) + jww.TRACE.Printf("%q found in override: %s", key, val) return val } @@ -770,24 +773,24 @@ func (v *Viper) find(key string) interface{} { // even if it hasn't been registered, if automaticEnv is used, // check any Get request if val = v.getEnv(v.mergeWithEnvPrefix(key)); val != "" { - jww.TRACE.Println(key, "found in environment with val:", val) + jww.TRACE.Printf("%q found in environment: %s", key, val) return val } } envkey, exists := v.env[key] if exists { - jww.TRACE.Println(key, "registered as env var", envkey) + jww.TRACE.Printf("%q registered as env var %q", key, envkey) if val = v.getEnv(envkey); val != "" { - jww.TRACE.Println(envkey, "found in environment with val:", val) + jww.TRACE.Printf("%q found in environment: %s", envkey, val) return val } - jww.TRACE.Println(envkey, "env value unset:") + jww.TRACE.Printf("%q env value unset", envkey) } val, exists = v.config[key] if exists { - jww.TRACE.Println(key, "found in config:", val) + jww.TRACE.Printf("%q found in config (%T): %s", key, val, val) return val } @@ -800,7 +803,7 @@ func (v *Viper) find(key string) interface{} { if reflect.TypeOf(source).Kind() == reflect.Map { val := v.searchMap(cast.ToStringMap(source), path[1:]) if val != nil { - jww.TRACE.Println(key, "found in nested config:", val) + jww.TRACE.Printf("%q found in nested config: %s", key, val) return val } } @@ -809,13 +812,13 @@ func (v *Viper) find(key string) interface{} { val, exists = v.kvstore[key] if exists { - jww.TRACE.Println(key, "found in key/value store:", val) + jww.TRACE.Printf("%q found in key/value store: %s", key, val) return val } val, exists = v.defaults[key] if exists { - jww.TRACE.Println(key, "found in defaults:", val) + jww.TRACE.Printf("%q found in defaults: ", key, val) return val }