88 lines
3.0 KiB
Go
88 lines
3.0 KiB
Go
package engine
|
|
|
|
import (
|
|
"slices"
|
|
|
|
"gitea.maximumdirect.net/eric/ConfigKit/internal/document"
|
|
)
|
|
|
|
// Retain source history at original paths. Structural operations are held once
|
|
// per relationship and projected onto a requested destination path only when
|
|
// History or Explain is queried.
|
|
func applyInheritanceMetadata(metadata *Metadata, raw *document.Node, rawOrigins map[string]Origin, overlays []overlayRecord, expansion *inheritanceScope) {
|
|
if metadata == nil || expansion == nil {
|
|
return
|
|
}
|
|
sourceView := Metadata{
|
|
fields: make(map[string]FieldInfo),
|
|
history: metadata.history,
|
|
}
|
|
walkDocument(raw, Path{}, func(path Path, node *document.Node) {
|
|
origin, found := rawOrigins[path.String()]
|
|
if !found {
|
|
origin = Origin{Layer: LayerBase, Locations: []Location{publicLocation(node.Location)}}
|
|
}
|
|
sourceView.fields[path.String()] = FieldInfo{Explicit: true, Null: node.Kind == document.Null, Origin: cloneOrigin(origin)}
|
|
})
|
|
applyOverlayMetadata(&sourceView, overlays)
|
|
metadata.history = sourceView.history
|
|
}
|
|
|
|
func historyWithInheritance(path Path, stored []Change, operations []inheritanceOperation) []Change {
|
|
split := len(stored)
|
|
for index, change := range stored {
|
|
if change.Origin.Layer == LayerCLI || change.Origin.Layer == LayerResolution {
|
|
split = index
|
|
break
|
|
}
|
|
}
|
|
history := cloneChanges(stored[:split])
|
|
for _, operation := range operations {
|
|
for _, change := range projectedInheritanceChanges(path, operation) {
|
|
if len(history) != 0 {
|
|
change.Previous = []Origin{cloneOrigin(history[len(history)-1].Origin)}
|
|
}
|
|
history = append(history, change)
|
|
}
|
|
}
|
|
for _, change := range stored[split:] {
|
|
cloned := cloneChange(change)
|
|
if len(history) != 0 {
|
|
cloned.Previous = []Origin{cloneOrigin(history[len(history)-1].Origin)}
|
|
}
|
|
history = append(history, cloned)
|
|
}
|
|
return history
|
|
}
|
|
|
|
func projectedInheritanceChanges(query Path, operation inheritanceOperation) []Change {
|
|
return inheritanceChangesForQuery(query, operation)
|
|
}
|
|
|
|
func transferredOperationOrigin(operation inheritanceOperation, destination Path) (Origin, bool) {
|
|
if inheritanceOperationIdentity(operation, destination) {
|
|
return Origin{}, false
|
|
}
|
|
relative, ok := relativeHistoryPath(operation.transfer.to, destination)
|
|
if !ok {
|
|
return Origin{}, false
|
|
}
|
|
source := appendInheritancePath(operation.transfer.from, relative)
|
|
origin, found := operation.parentOrigins[source.String()]
|
|
if !found {
|
|
return Origin{}, false
|
|
}
|
|
transferred := transferredInheritanceOrigins(map[string]Origin{source.String(): origin},
|
|
operation.transfer.from, operation.transfer.to, *operation.transfer)
|
|
return transferred[destination.String()], true
|
|
}
|
|
|
|
func inheritanceOperationIdentity(operation inheritanceOperation, path Path) bool {
|
|
if operation.transfer == nil || len(operation.identityFields) == 0 {
|
|
return false
|
|
}
|
|
relative, within := relativeHistoryPath(operation.transfer.to, path)
|
|
return within && len(relative.segments) != 0 && relative.segments[0].kind != pathSegmentIndex &&
|
|
slices.Contains(operation.identityFields, relative.segments[0].key)
|
|
}
|