diff --git a/config/impl.go b/config/impl.go index c7d0516..1d28de8 100644 --- a/config/impl.go +++ b/config/impl.go @@ -146,12 +146,40 @@ func (this *config) saveUser () error { return nil } -func (this *config) processUserDiff (changed []string) { - // TODO +func (this *config) processUserDiff (changed map[string] struct { }) { + for key := range changed { + // this is the user file, and nothing has precedence over it, so + // the change always matters + this.broadcastChange(key) + } } -func (this *config) processSystemDiff (index int, changed []string) { - // TODO +func (this *config) processSystemDiff (index int, changed map[string] struct { }) { + for key := range changed { + // if specified in the user file, the change doesn't matter + if this.data.user != nil { + if has, _ := this.data.user.Has(key); has { + continue + } + } + + // if specified in any system files with precedence greater than + // this one, the change doesn't matter + for _, system := range this.data.system[:index] { + if _, has := system[key]; has { + continue + } + } + + // the change does matter + this.broadcastChange(key) + } +} + +func (this *config) broadcastChange (key string) { + for _, listener := range this.on.change.Listeners() { + listener(key) + } } func (this *config) get (key string, fallback Value) (Value, error) { @@ -246,3 +274,29 @@ func (this *config) OnChange (callback func (string)) event.Cookie { defer this.lock.Unlock() return this.on.change.Connect(callback) } + +func diffValueMaps (first, second map[string] Value) map[string] struct { } { + diff := make(map[string] struct { }) + + // - keys only first has + // - keys both have, but are different + for key, firstValue := range first { + secondValue, ok := second[key] + if !ok { + diff[key] = struct { } { } + continue + } + if !firstValue.Equals(secondValue) { + diff[key] = struct { } { } + } + } + + // - keys only second has + for key := range second { + if _, has := first[key]; !has { + diff[key] = struct { } { } + } + } + + return diff +} diff --git a/config/impl_test.go b/config/impl_test.go new file mode 100644 index 0000000..a162fe1 --- /dev/null +++ b/config/impl_test.go @@ -0,0 +1,53 @@ +package config + +import "maps" +import "testing" + +func TestDiffValueMapsNone (test *testing.T) { + str := ` +thing = something + +otherThing = otherValue +# comment +otherThing = true +otherThing = 234 + +yetAnotherThing = 0.23498 +` + file1 := parseFileString(test, str) + file2 := parseFileString(test, str) + diff := diffValueMaps(file1.Map(), file2.Map()) + if len(diff) != 0 { + test.Fatalf("diff not empty:\n%v", diff) + } +} + +func TestDiffValueMaps (test *testing.T) { + file1 := parseFileString(test, +`key4=0 +key1=value1 +# comment +key2=34`) + file2 := parseFileString(test, +`key1=value2 +key2=34 +# comment + +key3=0.2`) + diff := diffValueMaps(file1.Map(), file2.Map()) + correct := map[string] struct { } { + "key1": struct { } { }, + "key3": struct { } { }, + "key4": struct { } { }, + } + if !maps.Equal(diff, correct) { + test.Error("diffs do not match") + test.Errorf("EXPECTED:\n%v", correct) + test.Errorf("GOT:\n%v", diff) + test.Fail() + } +} + +// TODO we need way more tests! +// need to test watching files. maybe make a temp dir and do it there. remember +// to defer cleaning up the dir and closing of the config.