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 }