package engine import ( "slices" "gitea.maximumdirect.net/eric/ConfigKit/internal/document" ) func directInheritanceOrigins(node *document.Node, root Path, input map[string]Origin) map[string]Origin { result := make(map[string]Origin) walkDocument(node, root, func(path Path, value *document.Node) { origin, found := input[path.String()] if !found { origin = Origin{Layer: LayerBase, Locations: []Location{publicLocation(value.Location)}} } origin = cloneOrigin(origin) if len(origin.contributors) == 0 { origin.contributors = make([]inheritanceContributor, len(origin.Locations)) for index, location := range origin.Locations { origin.contributors[index] = inheritanceContributor{ source: path.clone(), location: location, } } } result[path.String()] = origin }) return result } func transferredInheritanceOrigins(parent map[string]Origin, from, to Path, control inheritanceTransfer) map[string]Origin { result := make(map[string]Origin, len(parent)) transfer := control // one immutable edge shared by every matching contributor links := make(map[*inheritanceTrace]*inheritanceTrace) for pointer, origin := range parent { path, err := ParsePath(pointer) if err != nil { continue } relative, ok := relativeHistoryPath(from, path) if !ok { continue } destination := appendInheritancePath(to, relative) origin = cloneOrigin(origin) for index, contributor := range origin.contributors { link, found := links[contributor.trace] if !found { link = &inheritanceTrace{previous: contributor.trace, transfer: &transfer} links[contributor.trace] = link } origin.contributors[index].trace = link } result[destination.String()] = origin } return result } func appendInheritancePath(root, relative Path) Path { return Path{segments: append(clonePathSegments(root.segments, len(relative.segments)), relative.segments...)} } func mergeInheritanceOrigin(origins map[string]Origin, path Path, incoming Origin) { pointer := path.String() current := origins[pointer] current.Layer = incoming.Layer current.Locations = append(current.Locations, incoming.Locations...) current.contributors = append(current.contributors, incoming.contributors...) origins[pointer] = current } func copyInheritanceSubtree(target, incoming map[string]Origin, node *document.Node, root Path) { walkDocument(node, root, func(path Path, _ *document.Node) { target[path.String()] = cloneOrigin(incoming[path.String()]) }) } // Materialize concrete steps only for an inspection record. The linked private // traces remain compact when one parent supplies many descendant values. func projectInheritanceSteps(origin Origin) []InheritanceStep { steps := cloneInheritanceSteps(origin.Inheritance) for _, contributor := range origin.contributors { var reverse []*inheritanceTrace for link := contributor.trace; link != nil; link = link.previous { reverse = append(reverse, link) } current := contributor.source for index := len(reverse) - 1; index >= 0; index-- { transfer := reverse[index].transfer relative, ok := relativeHistoryPath(transfer.from, current) if !ok { continue } next := appendInheritancePath(transfer.to, relative) step := InheritanceStep{ From: current.clone(), To: next.clone(), Reference: transfer.reference.clone(), Locations: cloneLocations(transfer.locations), } if !slices.ContainsFunc(steps, func(existing InheritanceStep) bool { return existing.From.String() == step.From.String() && existing.To.String() == step.To.String() && existing.Reference.String() == step.Reference.String() && slices.Equal(existing.Locations, step.Locations) }) { steps = append(steps, step) } current = next } } return steps } func sameInheritanceTrace(left, right *inheritanceTrace) bool { for left != nil && right != nil { if left == right { return true } l, r := left.transfer, right.transfer if !slices.Equal(l.from.segments, r.from.segments) || !slices.Equal(l.to.segments, r.to.segments) || !slices.Equal(l.reference.segments, r.reference.segments) || !slices.Equal(l.locations, r.locations) { return false } left, right = left.previous, right.previous } return left == nil && right == nil }