changeset 40004:fa3dc85a747e

storageutil: extract functionality for resolving strip revisions I found myself having to copy this method as part of implementing a new storage backend. With a little tweaking, we can extract it to a standalone function so it can be reused easily. We'll likely want to implement a better method for removing revisions on the storage interface someday. But until then, let's use what we have. Differential Revision: https://phab.mercurial-scm.org/D4799
author Gregory Szorc <gregory.szorc@gmail.com>
date Fri, 28 Sep 2018 11:29:05 -0700
parents ad8389ecd3f5
children 1d97a332c6d9
files mercurial/revlog.py mercurial/utils/storageutil.py
diffstat 2 files changed, 55 insertions(+), 33 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/revlog.py	Fri Sep 28 11:16:44 2018 -0700
+++ b/mercurial/revlog.py	Fri Sep 28 11:29:05 2018 -0700
@@ -2096,39 +2096,9 @@
         Returns a tuple containing the minimum rev and a set of all revs that
         have linkrevs that will be broken by this strip.
         """
-        brokenrevs = set()
-        strippoint = len(self)
-
-        heads = {}
-        futurelargelinkrevs = set()
-        for head in self.headrevs():
-            headlinkrev = self.linkrev(head)
-            heads[head] = headlinkrev
-            if headlinkrev >= minlink:
-                futurelargelinkrevs.add(headlinkrev)
-
-        # This algorithm involves walking down the rev graph, starting at the
-        # heads. Since the revs are topologically sorted according to linkrev,
-        # once all head linkrevs are below the minlink, we know there are
-        # no more revs that could have a linkrev greater than minlink.
-        # So we can stop walking.
-        while futurelargelinkrevs:
-            strippoint -= 1
-            linkrev = heads.pop(strippoint)
-
-            if linkrev < minlink:
-                brokenrevs.add(strippoint)
-            else:
-                futurelargelinkrevs.remove(linkrev)
-
-            for p in self.parentrevs(strippoint):
-                if p != nullrev:
-                    plinkrev = self.linkrev(p)
-                    heads[p] = plinkrev
-                    if plinkrev >= minlink:
-                        futurelargelinkrevs.add(plinkrev)
-
-        return strippoint, brokenrevs
+        return storageutil.resolvestripinfo(minlink, len(self) - 1,
+                                            self.headrevs(),
+                                            self.linkrev, self.parentrevs)
 
     def strip(self, minlink, transaction):
         """truncate the revlog on the first revision with a linkrev >= minlink
--- a/mercurial/utils/storageutil.py	Fri Sep 28 11:16:44 2018 -0700
+++ b/mercurial/utils/storageutil.py	Fri Sep 28 11:29:05 2018 -0700
@@ -14,6 +14,7 @@
 from ..node import (
     bin,
     nullid,
+    nullrev,
 )
 from .. import (
     error,
@@ -155,3 +156,54 @@
         pass
 
     raise error.LookupError(fileid, identifier, _('no match found'))
+
+def resolvestripinfo(minlinkrev, tiprev, headrevs, linkrevfn, parentrevsfn):
+    """Resolve information needed to strip revisions.
+
+    Finds the minimum revision number that must be stripped in order to
+    strip ``minlinkrev``.
+
+    Returns a 2-tuple of the minimum revision number to do that and a set
+    of all revision numbers that have linkrevs that would be broken
+    by that strip.
+
+    ``tiprev`` is the current tip-most revision. It is ``len(store) - 1``.
+    ``headrevs`` is an iterable of head revisions.
+    ``linkrevfn`` is a callable that receives a revision and returns a linked
+    revision.
+    ``parentrevsfn`` is a callable that receives a revision number and returns
+    an iterable of its parent revision numbers.
+    """
+    brokenrevs = set()
+    strippoint = tiprev + 1
+
+    heads = {}
+    futurelargelinkrevs = set()
+    for head in headrevs:
+        headlinkrev = linkrevfn(head)
+        heads[head] = headlinkrev
+        if headlinkrev >= minlinkrev:
+            futurelargelinkrevs.add(headlinkrev)
+
+    # This algorithm involves walking down the rev graph, starting at the
+    # heads. Since the revs are topologically sorted according to linkrev,
+    # once all head linkrevs are below the minlink, we know there are
+    # no more revs that could have a linkrev greater than minlink.
+    # So we can stop walking.
+    while futurelargelinkrevs:
+        strippoint -= 1
+        linkrev = heads.pop(strippoint)
+
+        if linkrev < minlinkrev:
+            brokenrevs.add(strippoint)
+        else:
+            futurelargelinkrevs.remove(linkrev)
+
+        for p in parentrevsfn(strippoint):
+            if p != nullrev:
+                plinkrev = linkrevfn(p)
+                heads[p] = plinkrev
+                if plinkrev >= minlinkrev:
+                    futurelargelinkrevs.add(plinkrev)
+
+    return strippoint, brokenrevs