Add config.File.Diff to diff two config files

This commit is contained in:
Sasha Koshka 2024-08-22 19:13:00 -04:00
parent a8878e1e20
commit b4328edd73
2 changed files with 82 additions and 1 deletions

View File

@ -143,6 +143,14 @@ func ParseValue (str string) (Value, error) {
}
}
// Has returns whether the key exists. If the key is invalid, it returns false,
// ErrMalformedKey.
func (this *File) Has (key string) (bool, error) {
if !KeyValid(key) { return false, ErrMalformedKey }
_, ok := this.keys[key]
return ok, nil
}
// Get gets the keyed value. If the value is unspecified, it returns nil,
// ErrNonexistentEntry. If the key is invalid, it returns nil, ErrMalformedKey.
func (this *File) Get (key string) (Value, error) {
@ -186,7 +194,7 @@ func (this *File) Reset (key string) error {
return nil
}
// Map returns a map of keys to values.
// Map creates and returns a map of keys to values.
func (this *File) Map () map[string] Value {
mp := make(map[string] Value)
for key, index := range this.keys {
@ -197,6 +205,33 @@ func (this *File) Map () map[string] Value {
return mp
}
// Diff returns a set of keys that are different from the other file.
func (this *File) Diff (other *File) map[string] struct { } {
diff := make(map[string] struct { })
// - keys only we have
// - keys we both have, but are different
for key, index := range this.keys {
otherIndex, ok := other.keys[key]
if !ok {
diff[key] = struct { } { }
continue
}
if !this.lines[index].(entry).value.Equals(other.lines[otherIndex].(entry).value) {
diff[key] = struct { } { }
}
}
// - keys only they have
for key := range other.keys {
if _, has := this.keys[key]; !has {
diff[key] = struct { } { }
}
}
return diff
}
// WriteTo writes the data in this file to an io.Writer.
func (file *File) WriteTo (writer io.Writer) (n int64, err error) {
for _, lin := range file.lines {

View File

@ -1,6 +1,7 @@
package config
import "math"
import "maps"
import "strings"
import "testing"
@ -103,6 +104,51 @@ key1=7
`)
}
func TestDiffNone (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 := file1.Diff(file2)
if len(diff) != 0 {
test.Fatalf("diff not empty:\n%v", diff)
}
}
func TestDiff (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 := file1.Diff(file2)
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()
}
}
func testParseEntry (test *testing.T, str string, key string, value Value) {
ent, err := parseEntry(str)
if err != nil { test.Fatal(err) }