subranges: remove the recursivity of the call to isubranges(parentrange)
We add some logic to ensure we'll have hot cache for the parent ranges when that
matters, the cache is filled from ancestors to descendant to ensure this. The
range are still 'created from descendant to ancestors to fill the revsfromrange
cache since it important.
--- a/hgext3rd/evolve/stablerange.py Thu Mar 23 10:19:59 2017 +0100
+++ b/hgext3rd/evolve/stablerange.py Thu Mar 23 10:44:12 2017 +0100
@@ -298,8 +298,45 @@
if self.rangelength(repo, rangeid) == 1:
return []
slicepoint = self._slicepoint(repo, rangeid)
+
+ # make sure we have cache for all relevant parent first to prevent
+ # recursion (python is bad with recursion
+ stack = []
+ current = rangeid
+ while current is not None:
+ current = self._unpreparedparentrange(repo, current, slicepoint)
+ if current is not None:
+ stack.append(current)
+ while stack:
+ # these call will directly compute the subranges
+ self.subranges(repo, stack.pop())
return self._slicesrangeat(repo, rangeid, slicepoint)
+ def _unpreparedparentrange(self, repo, rangeid, slicepoint):
+ """return parent range that it would be useful to prepare to slice
+ rangeid at slicepoint
+
+ This function also have the important task to update the revscache of
+ the parent revs if possible and needed"""
+ # is this is a merge, there is not need to prepare the parents.
+ p1, p2 = repo.changelog.parentrevs(rangeid[0])
+ if p2 != nodemod.nullrev:
+ return None
+ parentrange = (p1, rangeid[1])
+ # if we have an entry for the current range, lets update the cache
+ revscache = self._revsinrangecache
+ if rangeid in revscache and parentrange not in revscache:
+ parentrevs = self._revsinrangecache[rangeid][:-1]
+ self._revsinrangecache[parentrange] = parentrevs
+ # if we already have subrange for this range, no need to prepare it.
+ if self._subrangescache.get(parentrange) is not None:
+ return None
+ # if we reached the slicepoint, no need to go further
+ if self.depthrev(repo, parentrange[0]) == slicepoint:
+ return None
+ # look like we found a relevent parentrange with no cache yet
+ return parentrange
+
def _slicepoint(self, repo, rangeid):
rangedepth = self.depthrev(repo, rangeid[0])
step = _hlp2(rangedepth)
@@ -334,12 +371,10 @@
top = (rangeid[0], globalindex)
return [parentrange, top]
else:
- # XXX recursive call, python have issue with them
- # The best way to break it would be directly 'self.subranges'
- # In that other method we could make sure subrangess for
- # (p1(rev), idx) are available before slicing (rev, idx). But the
- # heavy object approach makes it a bit inconvenient so that will
- # wait for that heavy object to be gone.
+ # This will not initiate a recursion since we took appropriate
+ # precaution in the caller of this method to ensure it will be so.
+ # It the parent is a merge that will not be the case but computing
+ # subranges from a merge will not recurse.
parentsubranges = self.subranges(repo, parentrange)
slices = parentsubranges[:-1] # pop the top
top = (rangeid[0], globalindex)