stablerange: extract the core API into a 'stablerangecore' class
authorPierre-Yves David <pierre-yves.david@octobus.net>
Wed, 29 Nov 2017 11:18:53 -0500
changeset 3250 8eaf30e1019f
parent 3249 94f80f229a89
child 3251 0e4a05907c5e
stablerange: extract the core API into a 'stablerangecore' class To clarify what the code is doing without all the caching and algorithmic improvement, we extract a core class that highlight the basic API expected from the class.
hgext3rd/evolve/stablerange.py
--- a/hgext3rd/evolve/stablerange.py	Sat Dec 09 22:17:00 2017 +0100
+++ b/hgext3rd/evolve/stablerange.py	Wed Nov 29 11:18:53 2017 -0500
@@ -7,6 +7,7 @@
 # This software may be used and distributed according to the terms of the
 # GNU General Public License version 2 or any later version.
 
+import abc
 import heapq
 import math
 import os
@@ -153,7 +154,56 @@
         else:
             ui.status('%s - %s\n' % (rstr, subsstr))
 
-class stablerange(object):
+class abstractstablerange(object):
+    """The official API for a stablerange"""
+
+    __metaclass__ = abc.ABCMeta
+
+    @abc.abstractmethod
+    def subranges(self, repo, rangeid):
+        """return the stable sub-ranges of a rangeid"""
+        raise NotImplemented()
+
+    @abc.abstractmethod
+    def revsfromrange(self, repo, rangeid):
+        """return revision contained in a range"""
+        raise NotImplemented()
+
+    @abc.abstractmethod
+    def depthrev(self, repo, rev):
+        """depth a revision"""
+        # Exist to allow basic implementation to ignore the depthcache
+        # Could be demoted to _depthrev.
+        raise NotImplemented()
+
+    @abc.abstractmethod
+    def warmup(self, repo, upto=None):
+        """warmup the stable range cache"""
+        raise NotImplemented()
+
+    def rangelength(self, repo, rangeid):
+        """number of revision in <range>"""
+        headrev, index = rangeid[0], rangeid[1]
+        return self.depthrev(repo, headrev) - index
+
+    def _slicepoint(self, repo, rangeid):
+        """find the standard slicing point for a range"""
+        rangedepth = self.depthrev(repo, rangeid[0])
+        step = _hlp2(rangedepth)
+        standard_start = 0
+        while standard_start < rangeid[1] and 0 < step:
+            if standard_start + step < rangedepth:
+                standard_start += step
+            step //= 2
+        if rangeid[1] == standard_start:
+            slicesize = _hlp2(self.rangelength(repo, rangeid))
+            slicepoint = rangeid[1] + slicesize
+        else:
+            assert standard_start < rangedepth
+            slicepoint = standard_start
+        return slicepoint
+
+class stablerange(abstractstablerange):
 
     def __init__(self, lrusize=2000):
         # The point up to which we have data in cache
@@ -251,10 +301,6 @@
     def depthrev(self, repo, rev):
         return repo.depthcache.get(rev)
 
-    def rangelength(self, repo, rangeid):
-        headrev, index = rangeid[0], rangeid[1]
-        return self.depthrev(repo, headrev) - index
-
     def subranges(self, repo, rangeid):
         cached = self._getsub(rangeid)
         if cached is not None:
@@ -416,22 +462,6 @@
         # look like we found a relevent parentrange with no cache yet
         return reurange
 
-    def _slicepoint(self, repo, rangeid):
-        rangedepth = self.depthrev(repo, rangeid[0])
-        step = _hlp2(rangedepth)
-        standard_start = 0
-        while standard_start < rangeid[1] and 0 < step:
-            if standard_start + step < rangedepth:
-                standard_start += step
-            step //= 2
-        if rangeid[1] == standard_start:
-            slicesize = _hlp2(self.rangelength(repo, rangeid))
-            slicepoint = rangeid[1] + slicesize
-        else:
-            assert standard_start < rangedepth
-            slicepoint = standard_start
-        return slicepoint
-
     def _slicesrangeat(self, repo, rangeid, globalindex):
         p1, p2 = self._parents(rangeid[0], repo.changelog.parentrevs)
         if p2 == nodemod.nullrev: