topic: instroduce a fast path when computing stack
We do some stack related computation during transaction now. The current
inefficiency of the revset is hurting us too much. We pre-compute a subset using
native set operation to speed things up.
--- a/hgext3rd/topic/stack.py Fri Oct 20 22:44:12 2017 +0200
+++ b/hgext3rd/topic/stack.py Mon Oct 23 15:11:48 2017 +0200
@@ -9,6 +9,7 @@
error,
node,
phases,
+ obsolete,
util,
)
from .evolvebits import builddependencies, _singlesuccessor
@@ -23,6 +24,25 @@
if not util.safehasattr(context.basectx, 'isunstable'):
context.basectx.isunstable = context.basectx.troubled
+def _stackcandidates(repo):
+ """build the smaller set of revs that might be part of a stack.
+
+ The intend is to build something more efficient than what revsets do in
+ this area.
+ """
+ phasecache = repo._phasecache
+ if not phasecache._phasesets:
+ return repo.revs('(not public()) - obsolete()')
+ if any(s is None for s in phasecache._phasesets):
+ return repo.revs('(not public()) - obsolete()')
+
+ result = set()
+ for s in phasecache._phasesets[phases.draft:]:
+ result |= s
+
+ result -= obsolete.getrevs(repo, 'obsolete')
+ return result
+
class stack(object):
"""object represent a stack and common logic associated to it."""
@@ -31,12 +51,15 @@
self.branch = branch
self.topic = topic
self.behinderror = None
+
+ subset = _stackcandidates(repo)
+
if topic is not None and branch is not None:
raise error.ProgrammingError('both branch and topic specified (not defined yet)')
elif topic is not None:
- trevs = repo.revs("not obsolete() and topic(%s)", topic)
+ trevs = repo.revs("%ld and topic(%s)", subset, topic)
elif branch is not None:
- trevs = repo.revs("not public() and branch(%s) - obsolete() - topic()", branch)
+ trevs = repo.revs("%ld and branch(%s) - topic()", subset, branch)
else:
raise error.ProgrammingError('neither branch and topic specified (not defined yet)')
self._revs = trevs