aboutsummaryrefslogtreecommitdiff
path: root/commitquery/ancestor.go
diff options
context:
space:
mode:
authorGravatar Runxi Yu2026-03-11 20:41:32 +0800
committerGravatar Runxi Yu2026-03-11 20:41:32 +0800
commit040b572d95e4ca27e1ada6113c405b8a1eb4a669 (patch)
tree68d826f4d91144105802c9d1c67175ba9b314e29 /commitquery/ancestor.go
parentresearch: Maybe drop mmap in packfile_bloom (diff)
signatureNo signature
commitquery: Merge from ancestor and mergebases
Diffstat (limited to 'commitquery/ancestor.go')
-rw-r--r--commitquery/ancestor.go48
1 files changed, 48 insertions, 0 deletions
diff --git a/commitquery/ancestor.go b/commitquery/ancestor.go
new file mode 100644
index 00000000..671ea460
--- /dev/null
+++ b/commitquery/ancestor.go
@@ -0,0 +1,48 @@
+package commitquery
+
+import "codeberg.org/lindenii/furgit/objectid"
+
+// IsAncestor reports whether ancestor is reachable from descendant through
+// commit parent edges.
+//
+// Both inputs are peeled through annotated tags before commit traversal.
+func (query *Query) IsAncestor(ancestor, descendant objectid.ObjectID) (bool, error) {
+ ancestorIdx, err := query.resolveCommitish(ancestor)
+ if err != nil {
+ return false, err
+ }
+
+ descendantIdx, err := query.resolveCommitish(descendant)
+ if err != nil {
+ return false, err
+ }
+
+ return query.isAncestor(ancestorIdx, descendantIdx)
+}
+
+func (query *Query) isAncestor(ancestor, descendant nodeIndex) (bool, error) {
+ if ancestor == descendant {
+ return true, nil
+ }
+
+ ancestorGeneration := query.effectiveGeneration(ancestor)
+ descendantGeneration := query.effectiveGeneration(descendant)
+
+ if ancestorGeneration != generationInfinity &&
+ descendantGeneration != generationInfinity &&
+ ancestorGeneration > descendantGeneration {
+ return false, nil
+ }
+
+ minGeneration := uint64(0)
+ if ancestorGeneration != generationInfinity {
+ minGeneration = ancestorGeneration
+ }
+
+ err := query.paintDownToCommon(ancestor, []nodeIndex{descendant}, minGeneration)
+ if err != nil {
+ return false, err
+ }
+
+ return query.hasAnyMarks(ancestor, markRight), nil
+}