Apply CLI overrides after typed decoding
This commit is contained in:
@@ -25,10 +25,16 @@ func preparePostDecodeOverrideContext(input assembledInput, before decodedConfig
|
||||
after.final = document.Clone(assigned.final)
|
||||
|
||||
metadata := metadataFromDecoded(after)
|
||||
cliRecords := overrideMetadataRecords(before, assigned.overrides)
|
||||
var structuralOverlays []overlayRecord
|
||||
if input.inheritance != nil && input.composition != nil {
|
||||
applyInheritanceMetadata(&metadata, input.composition.root, input.composition.origins, input.composition.overlays, input.inheritance)
|
||||
structuralOverlays = input.composition.overlays
|
||||
applyInheritanceMetadata(&metadata, input.composition.root, input.composition.origins, append(cloneOverlayRecords(structuralOverlays), cliRecords...), input.inheritance)
|
||||
} else if input.composition != nil {
|
||||
applyOverlayMetadata(&metadata, input.composition.overlays)
|
||||
structuralOverlays = input.composition.overlays
|
||||
applyOverlayMetadata(&metadata, append(cloneOverlayRecords(structuralOverlays), cliRecords...))
|
||||
} else if len(cliRecords) != 0 {
|
||||
applyOverlayMetadata(&metadata, cliRecords)
|
||||
}
|
||||
|
||||
sources := cloneSourceInfos(input.sources)
|
||||
@@ -42,6 +48,9 @@ func preparePostDecodeOverrideContext(input assembledInput, before decodedConfig
|
||||
knownSources[override.source.ID] = true
|
||||
}
|
||||
}
|
||||
if input.versionState != nil {
|
||||
sources = sourceInfosWithVersionEvidence(sources, input.versionState.evidence, nil, true)
|
||||
}
|
||||
resolution := newResolutionInput(metadata, assigned.final, sources, input.contexts)
|
||||
|
||||
applications := structuralHistoryApplications(input)
|
||||
@@ -67,7 +76,54 @@ func preparePostDecodeOverrideContext(input assembledInput, before decodedConfig
|
||||
sources: sources,
|
||||
applications: applications,
|
||||
postDecodeApps: postDecodeApps,
|
||||
referenceInput: documentWithMetadataLocations(assigned.final, metadata),
|
||||
referenceInput: documentWithMetadataLocations(assigned.final, metadata, input.document),
|
||||
}
|
||||
}
|
||||
|
||||
func overrideMetadataRecords(before decodedConfiguration, overrides []preparedOverride) []overlayRecord {
|
||||
if len(overrides) == 0 {
|
||||
return nil
|
||||
}
|
||||
lookup := buildDocumentLookup(before.final)
|
||||
records := make([]overlayRecord, 0, len(overrides))
|
||||
for _, override := range overrides {
|
||||
location := document.Location{SourceID: override.source.ID}
|
||||
previous := cloneOrigin(before.origins[override.path.String()])
|
||||
var displaced []displacedDefinition
|
||||
if existing, ok := documentAtPathWithLookup(before.final, override.path, lookup); ok {
|
||||
displaced = affectedOverrideOrigins(existing, override.value, before.origins, override.path, new(mappingIndex))
|
||||
}
|
||||
records = append(records, overlayRecord{change: Change{
|
||||
Path: override.path.clone(), Origin: overlayOrigin(LayerCLI, location), Previous: previousOrigins(previous),
|
||||
}, displaced: displaced})
|
||||
}
|
||||
return records
|
||||
}
|
||||
|
||||
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{})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,18 +144,26 @@ func structuralHistoryApplications(input assembledInput) []historyApplication {
|
||||
|
||||
// documentWithMetadataLocations attaches effective origin coordinates to a
|
||||
// canonical typed projection for secret and validation diagnostics.
|
||||
func documentWithMetadataLocations(root *document.Node, metadata Metadata) *document.Node {
|
||||
func documentWithMetadataLocations(root *document.Node, metadata Metadata, fallback ...*document.Node) *document.Node {
|
||||
located := document.Clone(root)
|
||||
if located == nil {
|
||||
return nil
|
||||
}
|
||||
var fallbackRoot *document.Node
|
||||
if len(fallback) != 0 {
|
||||
fallbackRoot = fallback[0]
|
||||
}
|
||||
var visit func(*document.Node, Path)
|
||||
visit = func(node *document.Node, path Path) {
|
||||
pointer := path.String()
|
||||
if info, exists := metadata.fields[pointer]; exists {
|
||||
if location, ok := metadataFieldLocation(metadata, pointer, info.Origin); ok {
|
||||
node.Location = location
|
||||
} else if location, ok := nearestDocumentLocation(fallbackRoot, path); ok {
|
||||
node.Location = location
|
||||
}
|
||||
} else if location, ok := nearestDocumentLocation(fallbackRoot, path); ok {
|
||||
node.Location = location
|
||||
}
|
||||
switch node.Kind {
|
||||
case document.Mapping:
|
||||
@@ -110,7 +174,13 @@ func documentWithMetadataLocations(root *document.Node, metadata Metadata) *docu
|
||||
if location, ok := metadataFieldLocation(metadata, childPath.String(), info.Origin); ok {
|
||||
entry.KeyLocation = location
|
||||
entry.ValueLocation = location
|
||||
} else if location, ok := nearestDocumentLocation(fallbackRoot, childPath); ok {
|
||||
entry.KeyLocation = location
|
||||
entry.ValueLocation = location
|
||||
}
|
||||
} else if location, ok := nearestDocumentLocation(fallbackRoot, childPath); ok {
|
||||
entry.KeyLocation = location
|
||||
entry.ValueLocation = location
|
||||
}
|
||||
visit(entry.Value, childPath)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user