82 lines
2.7 KiB
Go
82 lines
2.7 KiB
Go
package engine
|
|
|
|
import "gitea.maximumdirect.net/eric/ConfigKit/internal/document"
|
|
|
|
// A true entry replaces the collection itself as well as its descendants;
|
|
// false records ordinary ancestor replacement without selecting a collection
|
|
// operation at that exact path.
|
|
type collectionReplacementPaths map[string]bool
|
|
|
|
func (paths collectionReplacementPaths) contains(path Path, includeExact bool) bool {
|
|
for length := 0; length <= len(path.segments); length++ {
|
|
prefix := Path{segments: path.segments[:length]}
|
|
inclusive, found := paths[prefix.String()]
|
|
if found && (length < len(path.segments) || includeExact && inclusive) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// lowerCollectionPoliciesForClaims makes replacement eligibility independent of
|
|
// declaration order. It removes only old YAML identity/record state; new pending
|
|
// declarations and application constraints are reconciled afterward.
|
|
func lowerCollectionPoliciesForClaims(
|
|
lower collectionPolicyScope,
|
|
claims []compositionClaim,
|
|
declarations map[string][]sequenceDeclarationSpec,
|
|
application sequencePolicy,
|
|
) (collectionPolicyScope, collectionReplacementPaths) {
|
|
byPath := make(map[string]compositionClaim, len(claims))
|
|
rootPath := ""
|
|
if len(claims) != 0 {
|
|
rootPath = claims[0].path.String()
|
|
}
|
|
for _, claim := range claims {
|
|
byPath[claim.path.String()] = claim
|
|
}
|
|
replaced := make(collectionReplacementPaths)
|
|
for key, claim := range byPath {
|
|
old, hasOld := lower.collections[key]
|
|
current := declarations[key]
|
|
if claim.kind == document.Mapping && (key == rootPath || !hasOld && len(current) == 0) {
|
|
continue // Ordinary mapping combination preserves descendants.
|
|
}
|
|
mode := sequenceMode(0)
|
|
identity := old.policy.identityPresent
|
|
for _, declaration := range current {
|
|
identity = identity || declaration.identityPresent
|
|
if mode == 0 && declaration.modePresent {
|
|
mode = declaration.mode
|
|
}
|
|
}
|
|
retainedMode := sequenceMode(0)
|
|
if old.policy.explicitModePresent {
|
|
retainedMode = old.policy.explicitMode
|
|
}
|
|
_, registered := application.identityFieldsAt(claim.path)
|
|
mode = collectionOperationMode(mode, retainedMode, identity || registered)
|
|
if mode == sequenceModeReplace {
|
|
replaced[key] = true
|
|
} else if claim.kind != document.Mapping && claim.kind != document.Sequence {
|
|
replaced[key] = false
|
|
}
|
|
}
|
|
result := cloneCollectionPolicyScope(lower)
|
|
for key, entry := range result.collections {
|
|
if replaced.contains(entry.destination, true) {
|
|
clearCollectionIdentity(&entry.policy)
|
|
result.collections[key] = entry
|
|
}
|
|
}
|
|
return result, replaced
|
|
}
|
|
|
|
func clearCollectionIdentity(policy *collectionPolicy) {
|
|
policy.identityFields = nil
|
|
policy.identityPresent = false
|
|
policy.identityLocation = nil
|
|
policy.recordOrder = nil
|
|
policy.recordPolicies = nil
|
|
}
|