Reuse owned assembly across configuration layers
This commit is contained in:
@@ -18,24 +18,41 @@ type displacedDefinition struct {
|
||||
}
|
||||
|
||||
func overlayDocuments(base *composedDocument, overlay *document.Node) (*composedDocument, []Diagnostic) {
|
||||
if base == nil || base.root == nil || base.root.Kind != document.Mapping || overlay == nil || overlay.Kind != document.Mapping {
|
||||
return nil, []Diagnostic{{
|
||||
Code: CodeOverlayInvalid, Severity: SeverityError,
|
||||
Message: "overlay requires mapping document roots",
|
||||
}}
|
||||
if base == nil {
|
||||
return nil, invalidOverlayDocument()
|
||||
}
|
||||
result := cloneComposedDocument(base)
|
||||
mergeOverlayOrigin(result.origins, Path{}, overlay.Location, LayerOverlay)
|
||||
mergeOverlayMappings(result, result.root, overlay, Path{}, LayerOverlay, true)
|
||||
result.applications = append(result.applications, historyApplication{layer: LayerOverlay, value: overlay})
|
||||
return result, nil
|
||||
assembly := newAssemblyAccumulator(cloneComposedDocument(base))
|
||||
if diagnostics := assembly.applyOverlay(overlay, nil, nil, LayerOverlay); len(diagnostics) != 0 {
|
||||
return nil, diagnostics
|
||||
}
|
||||
return assembly.current, nil
|
||||
}
|
||||
|
||||
func mergeOverlayMappings(result *composedDocument, target, overlay *document.Node, current Path, layer Layer, recordReplacements bool) {
|
||||
mergeOverlayMappingsIndexed(result, target, overlay, current, layer, recordReplacements, new(mappingIndex))
|
||||
func invalidOverlayDocument() []Diagnostic {
|
||||
return []Diagnostic{{
|
||||
Code: CodeOverlayInvalid, Severity: SeverityError,
|
||||
Message: "overlay requires mapping document roots",
|
||||
}}
|
||||
}
|
||||
|
||||
func mergeOverlayMappingsIndexed(result *composedDocument, target, overlay *document.Node, current Path, layer Layer, recordReplacements bool, index *mappingIndex) {
|
||||
func (a *assemblyAccumulator) applyOverlay(overlay *document.Node, incomingOrigins map[string]Origin, applications []historyApplication, layer Layer) []Diagnostic {
|
||||
if a == nil || a.current == nil || a.current.root == nil || a.current.root.Kind != document.Mapping || overlay == nil || overlay.Kind != document.Mapping {
|
||||
return invalidOverlayDocument()
|
||||
}
|
||||
mergeOriginContribution(a.current.origins, Path{}, incomingOrigin(incomingOrigins, Path{}, overlay, layer))
|
||||
mergeOverlayMappings(a.current, a.current.root, overlay, Path{}, layer, true, incomingOrigins, &a.index)
|
||||
if len(applications) == 0 {
|
||||
a.current.applications = append(a.current.applications, historyApplication{layer: layer, value: overlay})
|
||||
} else {
|
||||
for _, application := range applications {
|
||||
application.layer = layer
|
||||
a.current.applications = append(a.current.applications, application)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func mergeOverlayMappings(result *composedDocument, target, overlay *document.Node, current Path, layer Layer, recordReplacements bool, incomingOrigins map[string]Origin, index *mappingIndex) {
|
||||
for _, incoming := range overlay.Mapping {
|
||||
path := current.Key(incoming.Key)
|
||||
position := index.find(target, incoming.Key)
|
||||
@@ -43,27 +60,27 @@ func mergeOverlayMappingsIndexed(result *composedDocument, target, overlay *docu
|
||||
cloned := incoming
|
||||
cloned.Value = document.Clone(incoming.Value)
|
||||
index.append(target, cloned)
|
||||
collectOverlayOrigins(result.origins, incoming.Value, path, layer)
|
||||
collectOverlayOriginsFrom(result.origins, incomingOrigins, incoming.Value, path, layer)
|
||||
continue
|
||||
}
|
||||
|
||||
existing := target.Mapping[position].Value
|
||||
if existing.Kind == document.Mapping && incoming.Value.Kind == document.Mapping {
|
||||
mergeOverlayOrigin(result.origins, path, incoming.Value.Location, layer)
|
||||
mergeOverlayMappingsIndexed(result, existing, incoming.Value, path, layer, recordReplacements, index)
|
||||
mergeOriginContribution(result.origins, path, incomingOrigin(incomingOrigins, path, incoming.Value, layer))
|
||||
mergeOverlayMappings(result, existing, incoming.Value, path, layer, recordReplacements, incomingOrigins, index)
|
||||
continue
|
||||
}
|
||||
|
||||
displaced := displacedOrigins(existing, result.origins, path)
|
||||
previous := cloneOrigin(result.origins[path.String()])
|
||||
deleteOriginSubtree(result.origins, path)
|
||||
deleteOriginSubtree(result.origins, path, existing)
|
||||
target.Mapping[position] = incoming
|
||||
target.Mapping[position].Value = document.Clone(incoming.Value)
|
||||
collectOverlayOrigins(result.origins, incoming.Value, path, layer)
|
||||
collectOverlayOriginsFrom(result.origins, incomingOrigins, incoming.Value, path, layer)
|
||||
if recordReplacements {
|
||||
result.overlays = append(result.overlays, overlayRecord{
|
||||
change: Change{
|
||||
Path: path.clone(), Origin: overlayOrigin(layer, incoming.Value.Location),
|
||||
Path: path.clone(), Origin: incomingOrigin(incomingOrigins, path, incoming.Value, layer),
|
||||
Previous: previousOrigins(previous),
|
||||
},
|
||||
displaced: displaced,
|
||||
@@ -73,27 +90,44 @@ func mergeOverlayMappingsIndexed(result *composedDocument, target, overlay *docu
|
||||
}
|
||||
|
||||
func collectOverlayOrigins(origins map[string]Origin, node *document.Node, path Path, layer Layer) {
|
||||
origins[path.String()] = overlayOrigin(layer, node.Location)
|
||||
collectOverlayOriginsFrom(origins, nil, node, path, layer)
|
||||
}
|
||||
|
||||
func collectOverlayOriginsFrom(origins, incomingOrigins map[string]Origin, node *document.Node, path Path, layer Layer) {
|
||||
origins[path.String()] = incomingOrigin(incomingOrigins, path, node, layer)
|
||||
switch node.Kind {
|
||||
case document.Mapping:
|
||||
for _, entry := range node.Mapping {
|
||||
collectOverlayOrigins(origins, entry.Value, path.Key(entry.Key), layer)
|
||||
collectOverlayOriginsFrom(origins, incomingOrigins, entry.Value, path.Key(entry.Key), layer)
|
||||
}
|
||||
case document.Sequence:
|
||||
for index, child := range node.Sequence {
|
||||
collectOverlayOrigins(origins, child, path.Index(index), layer)
|
||||
collectOverlayOriginsFrom(origins, incomingOrigins, child, path.Index(index), layer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func mergeOverlayOrigin(origins map[string]Origin, path Path, location document.Location, layer Layer) {
|
||||
mergeOriginContribution(origins, path, overlayOrigin(layer, location))
|
||||
}
|
||||
|
||||
func mergeOriginContribution(origins map[string]Origin, path Path, incoming Origin) {
|
||||
pointer := path.String()
|
||||
origin := cloneOrigin(origins[pointer])
|
||||
origin.Layer = layer
|
||||
origin.Locations = append(origin.Locations, publicLocation(location))
|
||||
origin := origins[pointer]
|
||||
origin.Layer = incoming.Layer
|
||||
origin.Locations = append(origin.Locations, incoming.Locations...)
|
||||
origins[pointer] = origin
|
||||
}
|
||||
|
||||
func incomingOrigin(origins map[string]Origin, path Path, node *document.Node, layer Layer) Origin {
|
||||
if origin, ok := origins[path.String()]; ok {
|
||||
origin = cloneOrigin(origin)
|
||||
origin.Layer = layer
|
||||
return origin
|
||||
}
|
||||
return overlayOrigin(layer, node.Location)
|
||||
}
|
||||
|
||||
func overlayOrigin(layer Layer, location document.Location) Origin {
|
||||
return Origin{Layer: layer, Locations: []Location{publicLocation(location)}}
|
||||
}
|
||||
@@ -133,11 +167,16 @@ func collectDisplacedOrigins(displaced *[]displacedDefinition, node *document.No
|
||||
}
|
||||
}
|
||||
|
||||
func deleteOriginSubtree(origins map[string]Origin, path Path) {
|
||||
prefix := path.String()
|
||||
for pointer := range origins {
|
||||
if pointer == prefix || strings.HasPrefix(pointer, prefix+"/") {
|
||||
delete(origins, pointer)
|
||||
func deleteOriginSubtree(origins map[string]Origin, path Path, node *document.Node) {
|
||||
delete(origins, path.String())
|
||||
switch node.Kind {
|
||||
case document.Mapping:
|
||||
for _, entry := range node.Mapping {
|
||||
deleteOriginSubtree(origins, path.Key(entry.Key), entry.Value)
|
||||
}
|
||||
case document.Sequence:
|
||||
for index, child := range node.Sequence {
|
||||
deleteOriginSubtree(origins, path.Index(index), child)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user