Patchwork D9232: phases: allow registration and boundary advancement with revsion sets

login
register
mail settings
Submitter phabricator
Date Oct. 20, 2020, 3:33 p.m.
Message ID <differential-rev-PHID-DREV-3t7tw7pepjhvneh3oqex-req@mercurial-scm.org>
Download mbox | patch
Permalink /patch/47497/
State Superseded
Headers show

Comments

phabricator - Oct. 20, 2020, 3:33 p.m.
joerg.sonnenberger created this revision.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REVISION SUMMARY
  The core internals either use revision sets already or can trivially use
  them. Use the new interface in cg1unpacker.apply to avoid materializing
  the list of all new nodes as it is normally just a revision range. This
  avoids about 67 Bytes / changeset on AMD64 in peak RSS.

REPOSITORY
  rHG Mercurial

BRANCH
  default

REVISION DETAIL
  https://phab.mercurial-scm.org/D9232

AFFECTED FILES
  mercurial/changegroup.py
  mercurial/phases.py

CHANGE DETAILS




To: joerg.sonnenberger, #hg-reviewers
Cc: mercurial-patches, mercurial-devel

Patch

diff --git a/mercurial/phases.py b/mercurial/phases.py
--- a/mercurial/phases.py
+++ b/mercurial/phases.py
@@ -510,21 +510,23 @@ 
         tr.addfilegenerator(b'phase', (b'phaseroots',), self._write)
         tr.hookargs[b'phases_moved'] = b'1'
 
-    def registernew(self, repo, tr, targetphase, nodes):
+    def registernew(self, repo, tr, targetphase, nodes, revs=[]):
         repo = repo.unfiltered()
-        self._retractboundary(repo, tr, targetphase, nodes)
+        self._retractboundary(repo, tr, targetphase, nodes, revs=revs)
         if tr is not None and b'phases' in tr.changes:
             phasetracking = tr.changes[b'phases']
             torev = repo.changelog.rev
             phase = self.phase
-            revs = [torev(node) for node in nodes]
+            revs = [torev(node) for node in nodes] + sorted(revs)
             revs.sort()
             for rev in revs:
                 revphase = phase(repo, rev)
                 _trackphasechange(phasetracking, rev, None, revphase)
         repo.invalidatevolatilesets()
 
-    def advanceboundary(self, repo, tr, targetphase, nodes, dryrun=None):
+    def advanceboundary(
+        self, repo, tr, targetphase, nodes, revs=[], dryrun=None
+    ):
         """Set all 'nodes' to phase 'targetphase'
 
         Nodes with a phase lower than 'targetphase' are not affected.
@@ -541,20 +543,19 @@ 
             phasetracking = tr.changes.get(b'phases')
 
         repo = repo.unfiltered()
+        revs = [repo[n].rev() for n in nodes] + [r for r in 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):
             # filter nodes that are not in a compatible phase already
-            nodes = [
-                n for n in nodes if self.phase(repo, repo[n].rev()) >= phase
-            ]
-            if not nodes:
+            revs = [rev for rev in revs if self.phase(repo, rev) >= phase]
+            if not revs:
                 break  # no roots to move anymore
 
             olds = self.phaseroots[phase]
 
-            affected = repo.revs(b'%ln::%ln', olds, nodes)
+            affected = repo.revs(b'%ln::%ld', olds, revs)
             changes.update(affected)
             if dryrun:
                 continue
@@ -611,7 +612,7 @@ 
                     _trackphasechange(phasetracking, r, phase, targetphase)
         repo.invalidatevolatilesets()
 
-    def _retractboundary(self, repo, tr, targetphase, nodes):
+    def _retractboundary(self, repo, tr, targetphase, nodes, revs=[]):
         # Be careful to preserve shallow-copied values: do not update
         # phaseroots values, replace them.
         if targetphase in (archived, internal) and not supportinternal(repo):
@@ -624,7 +625,7 @@ 
         tonode = repo.changelog.node
         currentroots = {torev(node) for node in self.phaseroots[targetphase]}
         finalroots = oldroots = set(currentroots)
-        newroots = [torev(node) for node in nodes]
+        newroots = [torev(node) for node in nodes] + [r for r in revs]
         newroots = [
             rev for rev in newroots if self.phase(repo, rev) < targetphase
         ]
@@ -679,7 +680,7 @@ 
         self.invalidate()
 
 
-def advanceboundary(repo, tr, targetphase, nodes, dryrun=None):
+def advanceboundary(repo, tr, targetphase, nodes, revs=[], dryrun=None):
     """Add nodes to a phase changing other nodes phases if necessary.
 
     This function move boundary *forward* this means that all nodes
@@ -693,7 +694,7 @@ 
     """
     phcache = repo._phasecache.copy()
     changes = phcache.advanceboundary(
-        repo, tr, targetphase, nodes, dryrun=dryrun
+        repo, tr, targetphase, nodes, revs=revs, dryrun=dryrun
     )
     if not dryrun:
         repo._phasecache.replace(phcache)
@@ -713,14 +714,14 @@ 
     repo._phasecache.replace(phcache)
 
 
-def registernew(repo, tr, targetphase, nodes):
+def registernew(repo, tr, targetphase, nodes, revs=[]):
     """register a new revision and its phase
 
     Code adding revisions to the repository should use this function to
     set new changeset in their target phase (or higher).
     """
     phcache = repo._phasecache.copy()
-    phcache.registernew(repo, tr, targetphase, nodes)
+    phcache.registernew(repo, tr, targetphase, nodes, revs=revs)
     repo._phasecache.replace(phcache)
 
 
diff --git a/mercurial/changegroup.py b/mercurial/changegroup.py
--- a/mercurial/changegroup.py
+++ b/mercurial/changegroup.py
@@ -318,12 +318,12 @@ 
             efilesset = set()
             cgnodes = []
 
+            def ondupchangelog(cl, node):
+                if cl.rev(node) < clstart:
+                    cgnodes.append(node)
+
             def onchangelog(cl, node):
                 efilesset.update(cl.readfiles(node))
-                cgnodes.append(node)
-
-            def ondupchangelog(cl, node):
-                cgnodes.append(node)
 
             self.changelogheader()
             deltas = self.deltaiter()
@@ -365,7 +365,7 @@ 
                 for cset in pycompat.xrange(clstart, clend):
                     mfnode = cl.changelogrevision(cset).manifest
                     mfest = ml[mfnode].readdelta()
-                    # store file cgnodes we must see
+                    # store file nodes we must see
                     for f, n in pycompat.iteritems(mfest):
                         needfiles.setdefault(f, set()).add(n)
 
@@ -423,7 +423,7 @@ 
                     **pycompat.strkwargs(hookargs)
                 )
 
-            added = [cl.node(r) for r in pycompat.xrange(clstart, clend)]
+            added = pycompat.xrange(clstart, clend)
             phaseall = None
             if srctype in (b'push', b'serve'):
                 # Old servers can not push the boundary themselves.
@@ -443,9 +443,10 @@ 
                     # ignored.
                     targetphase = phaseall = phases.draft
             if added:
-                phases.registernew(repo, tr, targetphase, added)
+                phases.registernew(repo, tr, targetphase, [], revs=added)
             if phaseall is not None:
-                phases.advanceboundary(repo, tr, phaseall, cgnodes)
+                phases.advanceboundary(repo, tr, phaseall, cgnodes, revs=added)
+                cgnodes = []
 
             if changesets > 0:
 
@@ -458,9 +459,9 @@ 
 
                     repo.hook(b"changegroup", **pycompat.strkwargs(hookargs))
 
-                    for n in added:
+                    for rev in added:
                         args = hookargs.copy()
-                        args[b'node'] = hex(n)
+                        args[b'node'] = hex(cl.node(rev))
                         del args[b'node_last']
                         repo.hook(b"incoming", **pycompat.strkwargs(args))