head-revs: teach the pure indexes about the `headrevs` method
authorPierre-Yves David <pierre-yves.david@octobus.net>
Wed, 25 Sep 2024 17:18:40 +0200
changeset 51969 22da1dc97281
parent 51968 8060257fd918
child 51970 e5dcaf6d4ac0
head-revs: teach the pure indexes about the `headrevs` method Having this computation done at the index level unify the API and remove revlog side complexity. It might also be a front runner of handing more responsability to the index.
mercurial/pure/parsers.py
mercurial/repoview.py
mercurial/revlog.py
mercurial/revlogutils/revlogv0.py
--- a/mercurial/pure/parsers.py	Thu Sep 26 00:50:21 2024 +0200
+++ b/mercurial/pure/parsers.py	Wed Sep 25 17:18:40 2024 +0200
@@ -696,6 +696,22 @@
             p = p[revlog_constants.INDEX_HEADER.size :]
         return p
 
+    def headrevs(self, excluded_revs=None):
+        count = len(self)
+        if not count:
+            return [nullrev]
+        # we won't iter over filtered rev so nobody is a head at start
+        ishead = [0] * (count + 1)
+        revs = range(count)
+        if excluded_revs is not None:
+            revs = (r for r in revs if r not in excluded_revs)
+
+        for r in revs:
+            ishead[r] = 1  # I may be an head
+            e = self[r]
+            ishead[e[5]] = ishead[e[6]] = 0  # my parent are not
+        return [r for r, val in enumerate(ishead) if val]
+
 
 class IndexObject(BaseIndexObject):
     def __init__(self, data):
--- a/mercurial/repoview.py	Thu Sep 26 00:50:21 2024 +0200
+++ b/mercurial/repoview.py	Wed Sep 25 17:18:40 2024 +0200
@@ -312,12 +312,7 @@
 
     def headrevs(self, revs=None):
         if revs is None:
-            try:
-                return self.index.headrevs(self.filteredrevs)
-            # AttributeError covers non-c-extension environments and
-            # old c extensions without filter handling.
-            except AttributeError:
-                return self._headrevs()
+            return self.index.headrevs(self.filteredrevs)
 
         revs = self._checknofilteredinrevs(revs)
         return super(filteredchangelogmixin, self).headrevs(revs)
--- a/mercurial/revlog.py	Thu Sep 26 00:50:21 2024 +0200
+++ b/mercurial/revlog.py	Wed Sep 25 17:18:40 2024 +0200
@@ -2382,10 +2382,7 @@
 
     def headrevs(self, revs=None):
         if revs is None:
-            try:
-                return self.index.headrevs()
-            except AttributeError:
-                return self._headrevs()
+            return self.index.headrevs()
         if rustdagop is not None and self.index.rust_ext_compat:
             return rustdagop.headrevs(self.index, revs)
         return dagop.headrevs(revs, self._uncheckedparentrevs)
@@ -2399,19 +2396,6 @@
     def computephases(self, roots):
         return self.index.computephasesmapsets(roots)
 
-    def _headrevs(self):
-        count = len(self)
-        if not count:
-            return [nullrev]
-        # we won't iter over filtered rev so nobody is a head at start
-        ishead = [0] * (count + 1)
-        index = self.index
-        for r in self:
-            ishead[r] = 1  # I may be an head
-            e = index[r]
-            ishead[e[5]] = ishead[e[6]] = 0  # my parent are not
-        return [r for r, val in enumerate(ishead) if val]
-
     def _head_node_ids(self):
         try:
             return self.index.head_node_ids()
--- a/mercurial/revlogutils/revlogv0.py	Thu Sep 26 00:50:21 2024 +0200
+++ b/mercurial/revlogutils/revlogv0.py	Wed Sep 25 17:18:40 2024 +0200
@@ -111,6 +111,22 @@
         )
         return INDEX_ENTRY_V0.pack(*e2)
 
+    def headrevs(self, excluded_revs=None):
+        count = len(self)
+        if not count:
+            return [node.nullrev]
+        # we won't iter over filtered rev so nobody is a head at start
+        ishead = [0] * (count + 1)
+        revs = range(count)
+        if excluded_revs is not None:
+            revs = (r for r in revs if r not in excluded_revs)
+
+        for r in revs:
+            ishead[r] = 1  # I may be an head
+            e = self[r]
+            ishead[e[5]] = ishead[e[6]] = 0  # my parent are not
+        return [r for r, val in enumerate(ishead) if val]
+
 
 def parse_index_v0(data, inline):
     s = INDEX_ENTRY_V0.size