2026-11-02 14:41:42 +00:00
|
|
|
package engine
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"cmp"
|
|
|
|
|
"slices"
|
|
|
|
|
|
|
|
|
|
"go.maximumdirect.net/configkit/internal/document"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// compareResolutionValues reports field-level changes at stable list positions.
|
2026-11-02 14:43:48 +00:00
|
|
|
func compareResolutionValues(before, after *document.Node, correspondence ...resolutionCorrespondence) []documentDelta {
|
2026-11-02 14:41:42 +00:00
|
|
|
var deltas []documentDelta
|
|
|
|
|
var compare func(*document.Node, *document.Node, Path)
|
|
|
|
|
compare = func(left, right *document.Node, path Path) {
|
|
|
|
|
if left == nil || right == nil || left.Kind != right.Kind {
|
|
|
|
|
compareConfigurationValue(left, right, path, &deltas)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
switch left.Kind {
|
|
|
|
|
case document.Mapping:
|
|
|
|
|
leftEntries := make(map[string]*document.Node, len(left.Mapping))
|
|
|
|
|
for _, entry := range left.Mapping {
|
|
|
|
|
leftEntries[entry.Key] = entry.Value
|
|
|
|
|
}
|
|
|
|
|
for _, entry := range right.Mapping {
|
|
|
|
|
compare(leftEntries[entry.Key], entry.Value, path.Key(entry.Key))
|
|
|
|
|
delete(leftEntries, entry.Key)
|
|
|
|
|
}
|
|
|
|
|
for key, value := range leftEntries {
|
|
|
|
|
compare(value, nil, path.Key(key))
|
|
|
|
|
}
|
|
|
|
|
case document.Sequence:
|
2026-11-02 14:43:48 +00:00
|
|
|
if len(correspondence) != 0 {
|
|
|
|
|
if collection, registered := correspondence[0].collections[path.String()]; registered {
|
|
|
|
|
if !collection.eligible {
|
|
|
|
|
if !configurationValuesEqual(left, right) {
|
|
|
|
|
deltas = append(deltas, documentDelta{path: path.clone(), kind: documentReplaced})
|
|
|
|
|
}
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if collection.structural {
|
|
|
|
|
deltas = append(deltas, documentDelta{path: path.clone(), kind: documentReplaced})
|
|
|
|
|
}
|
|
|
|
|
for finalIndex, entryIndex := range collection.finalToEntry {
|
|
|
|
|
if entryIndex >= 0 {
|
|
|
|
|
compare(left.Sequence[entryIndex], right.Sequence[finalIndex], path.Index(finalIndex))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-11-02 14:41:42 +00:00
|
|
|
if len(left.Sequence) != len(right.Sequence) {
|
|
|
|
|
deltas = append(deltas, documentDelta{path: path.clone(), kind: documentReplaced})
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
for index := range left.Sequence {
|
|
|
|
|
compare(left.Sequence[index], right.Sequence[index], path.Index(index))
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
compareConfigurationValue(left, right, path, &deltas)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
compare(before, after, Path{})
|
|
|
|
|
slices.SortFunc(deltas, func(a, b documentDelta) int {
|
|
|
|
|
if order := cmp.Compare(a.path.String(), b.path.String()); order != 0 {
|
|
|
|
|
return order
|
|
|
|
|
}
|
|
|
|
|
return int(a.kind) - int(b.kind)
|
|
|
|
|
})
|
|
|
|
|
return deltas
|
|
|
|
|
}
|