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{}) } } }