111 lines
4.8 KiB
Go
111 lines
4.8 KiB
Go
package engine
|
|
|
|
import (
|
|
"gitea.maximumdirect.net/eric/ConfigKit/internal/document"
|
|
)
|
|
|
|
func applyOverrides(base *composedDocument, sources []SourceInfo, overrides []Override, rule *VersionRule, limits importLimits) (*composedDocument, []SourceInfo, []Diagnostic) {
|
|
if len(overrides) == 0 {
|
|
return base, cloneSourceInfos(sources), nil
|
|
}
|
|
assembly := newAssemblyAccumulator(cloneComposedDocument(base))
|
|
allSources, diagnostics := assembly.applyOverrides(sources, overrides, rule, limits)
|
|
if len(diagnostics) != 0 {
|
|
return nil, allSources, diagnostics
|
|
}
|
|
return assembly.current, allSources, nil
|
|
}
|
|
|
|
func (a *assemblyAccumulator) applyOverrides(sources []SourceInfo, overrides []Override, rule *VersionRule, limits importLimits) ([]SourceInfo, []Diagnostic) {
|
|
if len(overrides) == 0 {
|
|
return cloneSourceInfos(sources), nil
|
|
}
|
|
prepared, allSources, diagnostics := prepareOverrides(a.current, sources, overrides, rule, limits)
|
|
if len(diagnostics) != 0 {
|
|
return allSources, diagnostics
|
|
}
|
|
for _, override := range prepared {
|
|
applyPreparedOverride(a.current, override, &a.index)
|
|
a.current.inputBytes += override.bytes
|
|
a.current.inputNodes += override.nodes
|
|
}
|
|
return allSources, nil
|
|
}
|
|
|
|
func applyPreparedOverride(result *composedDocument, override preparedOverride, index *mappingIndex) {
|
|
location := document.Location{SourceID: override.source.ID}
|
|
mergeOverlayOrigin(result.origins, Path{}, location, LayerCLI)
|
|
current := result.root
|
|
currentPath := Path{}
|
|
for segmentIndex, segment := range override.path.segments {
|
|
path := currentPath.Key(segment.key)
|
|
position := index.find(current, segment.key)
|
|
if segmentIndex < len(override.path.segments)-1 {
|
|
if position < 0 {
|
|
child := &document.Node{Kind: document.Mapping, Location: location, Mapping: []document.Entry{}}
|
|
index.append(current, document.Entry{Key: segment.key, KeyLocation: location, ValueLocation: location, Value: child})
|
|
collectOverlayOrigins(result.origins, child, path, LayerCLI)
|
|
current = child
|
|
} else {
|
|
current = current.Mapping[position].Value
|
|
mergeOverlayOrigin(result.origins, path, location, LayerCLI)
|
|
}
|
|
currentPath = path
|
|
continue
|
|
}
|
|
|
|
previous := cloneOrigin(result.origins[path.String()])
|
|
var displaced []displacedDefinition
|
|
if position < 0 {
|
|
incoming := document.Clone(override.value)
|
|
index.append(current, document.Entry{Key: segment.key, KeyLocation: location, ValueLocation: location, Value: incoming})
|
|
collectOverlayOrigins(result.origins, incoming, path, LayerCLI)
|
|
} else {
|
|
existing := current.Mapping[position].Value
|
|
displaced = affectedOverrideOrigins(existing, override.value, result.origins, path, index)
|
|
if existing.Kind == document.Mapping && override.value.Kind == document.Mapping {
|
|
mergeOverlayOrigin(result.origins, path, location, LayerCLI)
|
|
mergeOverlayMappings(result, existing, override.value, path, LayerCLI, false, nil, index)
|
|
} else {
|
|
deleteOriginSubtree(result.origins, path, existing)
|
|
current.Mapping[position] = document.Entry{Key: segment.key, KeyLocation: location, ValueLocation: location, Value: document.Clone(override.value)}
|
|
collectOverlayOrigins(result.origins, current.Mapping[position].Value, path, LayerCLI)
|
|
}
|
|
}
|
|
result.overlays = append(result.overlays, overlayRecord{change: Change{
|
|
Path: path.clone(), Origin: overlayOrigin(LayerCLI, location), Previous: previousOrigins(previous),
|
|
}, displaced: displaced})
|
|
result.applications = append(result.applications, historyApplication{
|
|
layer: LayerCLI, path: path.clone(), value: override.value,
|
|
origin: overlayOrigin(LayerCLI, location),
|
|
})
|
|
}
|
|
}
|
|
|
|
func affectedOverrideOrigins(existing, incoming *document.Node, origins map[string]Origin, path Path, index *mappingIndex) []displacedDefinition {
|
|
var displaced []displacedDefinition
|
|
collectAffectedOverrideOrigins(&displaced, existing, incoming, origins, path, index)
|
|
return sortDisplacedDefinitions(displaced)
|
|
}
|
|
|
|
func collectAffectedOverrideOrigins(displaced *[]displacedDefinition, existing, incoming *document.Node, origins map[string]Origin, path Path, index *mappingIndex) {
|
|
if existing.Kind != document.Mapping || incoming.Kind != document.Mapping {
|
|
collectDisplacedOrigins(displaced, existing, origins, path, Origin{})
|
|
return
|
|
}
|
|
*displaced = append(*displaced, displacedDefinition{path: path.clone(), origin: cloneOrigin(origins[path.String()])})
|
|
for _, entry := range incoming.Mapping {
|
|
position := index.find(existing, entry.Key)
|
|
if position < 0 {
|
|
continue
|
|
}
|
|
childPath := path.Key(entry.Key)
|
|
childExisting := existing.Mapping[position].Value
|
|
if childExisting.Kind == document.Mapping && entry.Value.Kind == document.Mapping {
|
|
collectAffectedOverrideOrigins(displaced, childExisting, entry.Value, origins, childPath, index)
|
|
} else {
|
|
collectDisplacedOrigins(displaced, childExisting, origins, childPath, Origin{})
|
|
}
|
|
}
|
|
}
|