Adds HasChanged and HasChangedSinceInit

These two methods return true if a value has changed.
This commit is contained in:
aeneasr 2019-07-15 13:08:37 +02:00
parent 5bace2abf4
commit 3c36e1d361
No known key found for this signature in database
GPG key ID: 998E76A674F4A689
2 changed files with 66 additions and 0 deletions

View file

@ -200,6 +200,8 @@ type Viper struct {
aliases map[string]string
typeByDefValue bool
previousValues map[string]interface{}
// Store read properties on the object so that we can write back in order with comments.
// This will only be used if the configuration read is a properties file.
properties *properties.Properties
@ -220,6 +222,7 @@ func New() *Viper {
v.override = make(map[string]interface{})
v.defaults = make(map[string]interface{})
v.kvstore = make(map[string]interface{})
v.previousValues = make(map[string]interface{})
v.pflags = make(map[string]FlagValue)
v.env = make(map[string]string)
v.aliases = make(map[string]string)
@ -685,6 +688,45 @@ func GetViper() *Viper {
return v
}
// HasChanged returns true if a key has changed and the change has not been retrieved yet using `Get()` and all
// casters `GetString()`, `GetDuration()`, ...
//
// If the value has not been retrieved at all this will also return true.
func HasChanged(key string) bool { return v.HasChanged(key) }
func (v *Viper) HasChanged(key string) bool {
lcaseKey := strings.ToLower(key)
v.lock.RLock()
defer v.lock.RUnlock()
value, ok := v.previousValues[lcaseKey]
if !ok {
return IsSet(lcaseKey)
}
// Avoid writing the change
return value != v.find(lcaseKey)
}
// HasChangedSinceInit returns true if a key has changed and the change has not been retrieved yet using `Get()` and all
// casters `GetString()`, `GetDuration()`, ...
//
// If the value has not been retrieved before at all this will return false.
func HasChangedSinceInit(key string) bool { return v.HasChangedSinceInit(key) }
func (v *Viper) HasChangedSinceInit(key string) bool {
lcaseKey := strings.ToLower(key)
v.lock.RLock()
defer v.lock.RUnlock()
value, ok := v.previousValues[lcaseKey]
if !ok {
return false
}
// Avoid writing the change
return value != v.find(lcaseKey)
}
// Get can retrieve any value given the key to use.
// Get is case-insensitive for a key.
// Get has the behavior of returning the value associated with the first
@ -696,6 +738,11 @@ func Get(key string) interface{} { return v.Get(key) }
func (v *Viper) Get(key string) interface{} {
lcaseKey := strings.ToLower(key)
val := v.find(lcaseKey)
v.lock.Lock()
v.previousValues[lcaseKey] = val
v.lock.Unlock()
if val == nil {
return nil
}

View file

@ -1761,6 +1761,25 @@ func TestArrayOfObjects(t *testing.T) {
require.NoError(t, WriteConfig())
}
func TestHasChanged(t *testing.T) {
Reset()
require.False(t, HasChanged("foo"))
require.False(t, HasChangedSinceInit("foo"))
Set("foo", "bar")
require.False(t, HasChangedSinceInit("foo"))
require.True(t, HasChanged("foo"))
require.Equal(t, "bar", Get("foo"))
require.False(t, HasChanged("foo"))
Set("foo", "baz")
require.True(t, HasChangedSinceInit("foo"))
require.True(t, HasChanged("foo"))
require.Equal(t, "baz", Get("foo"))
require.False(t, HasChanged("foo"))
require.False(t, HasChangedSinceInit("foo"))
}
func BenchmarkGetBool(b *testing.B) {
key := "BenchmarkGetBool"
v = New()