changeset 51420:709525b26cf5

phases: apply similar early filtering to advanceboundary advanceboundary is called the push's unbundle (but not the other unbundle) so advanceboundary did not show up the profile I looked at so far. We start with simple pre-filtering to avoid doing any work if we don't needs too.
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Thu, 22 Feb 2024 19:21:14 +0100
parents 2eb93812d2a5
children 23950e39281f
files mercurial/phases.py
diffstat 1 files changed, 22 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/phases.py	Wed Feb 21 11:09:25 2024 +0100
+++ b/mercurial/phases.py	Thu Feb 22 19:21:14 2024 +0100
@@ -665,20 +665,36 @@
         """
         if targetphase == public and not self.hasnonpublicphases(repo):
             return set()
+        repo = repo.unfiltered()
+        cl = repo.changelog
+        torev = cl.index.rev
         # Be careful to preserve shallow-copied values: do not update
         # phaseroots values, replace them.
-        if revs is None:
-            revs = []
-        if not revs and not nodes:
-            return set()
+        new_revs = set()
+        if revs is not None:
+            new_revs.update(revs)
+        if nodes is not None:
+            new_revs.update(torev(node) for node in nodes)
+        if not new_revs:  # bail out early to avoid the loadphaserevs call
+            return (
+                set()
+            )  # note: why do people call advanceboundary with nothing?
+
         if tr is None:
             phasetracking = None
         else:
             phasetracking = tr.changes.get(b'phases')
 
-        repo = repo.unfiltered()
-        revs = [repo[n].rev() for n in nodes] + [r for r in revs]
+        # filter revision already in the right phase
+        self._ensure_phase_sets(repo)
+        for phase, revs in self._phasesets.items():
+            if phase <= targetphase:
+                new_revs -= revs
+        if not new_revs:
+            return set()
 
+        # search for affected high phase changesets and roots
+        revs = new_revs
         changes = set()  # set of revisions to be changed
         delroots = []  # set of root deleted by this path
         for phase in (phase for phase in allphases if phase > targetphase):