phases: add a getrevset method to phasecache
authorJun Wu <quark@fb.com>
Fri, 17 Feb 2017 22:49:05 -0800
changeset 31016 bf81d3b7b2ba
parent 31015 1076f7eba964
child 31017 17b5cda5a84a
phases: add a getrevset method to phasecache This is part of a refactoring that moves some phase query optimization from revset.py to phases.py. The motivation behind this was chg repo preloading - to make the obsstore depend on less things (like the revset language). The refactoring also looks good by itself - phasecache does not expose its private field "_phasesets" via public methods and revset.py is accessing it in a hacky way. This patch adds a "getrevset" method, which takes multiple phases and returns a revset in an best-effort efficient way - for "public" phase, it returns a lazy generatorset; for "draft" and "secret", it returns efficient "baseset".
mercurial/phases.py
--- a/mercurial/phases.py	Fri Feb 17 20:59:29 2017 -0800
+++ b/mercurial/phases.py	Fri Feb 17 22:49:05 2017 -0800
@@ -115,6 +115,7 @@
 from . import (
     encoding,
     error,
+    smartset,
 )
 
 allphases = public, draft, secret = range(3)
@@ -170,6 +171,27 @@
             self.filterunknown(repo)
             self.opener = repo.svfs
 
+    def getrevset(self, repo, phases):
+        """return a smartset for the given phases"""
+        self.loadphaserevs(repo) # ensure phase's sets are loaded
+
+        if self._phasesets and all(self._phasesets[p] is not None
+                                   for p in phases):
+            # fast path - use _phasesets
+            revs = self._phasesets[phases[0]]
+            if len(phases) > 1:
+                revs = revs.copy() # only copy when needed
+                for p in phases[1:]:
+                    revs.update(self._phasesets[p])
+            if repo.changelog.filteredrevs:
+                revs = revs - repo.changelog.filteredrevs
+            return smartset.baseset(revs)
+        else:
+            # slow path - enumerate all revisions
+            phase = self.phase
+            revs = (r for r in repo if phase(repo, r) in phases)
+            return smartset.generatorset(revs, iterasc=True)
+
     def copy(self):
         # Shallow copy meant to ensure isolation in
         # advance/retractboundary(), nothing more.