D7092: widening: duplicate generateellipsesbundle2() for widening

martinvonz (Martin von Zweigbergk) phabricator at mercurial-scm.org
Mon Oct 14 13:57:08 EDT 2019


martinvonz created this revision.
Herald added a reviewer: durin42.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  The widening and the non-widening code are quite different. It will be
  clearer to have them as sepearate functions. To start with, I've just
  copied it exactly, so it's clearer over the next few patches how
  they're different.
  
  The new function should gradually become more similar to
  bundle2.widen_bundle(), and should perhaps eventually be merged with
  that function. However, I've left it in narrowbundle2.py for now since
  it still depends on constants like _KILLNODESIGNAL there.

REPOSITORY
  rHG Mercurial

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

AFFECTED FILES
  hgext/narrow/narrowbundle2.py
  hgext/narrow/narrowwirepeer.py

CHANGE DETAILS

diff --git a/hgext/narrow/narrowwirepeer.py b/hgext/narrow/narrowwirepeer.py
--- a/hgext/narrow/narrowwirepeer.py
+++ b/hgext/narrow/narrowwirepeer.py
@@ -120,7 +120,7 @@
                 ellipses,
             )
         else:
-            narrowbundle2.generateellipsesbundle2(
+            narrowbundle2.generate_ellipses_bundle2_for_widening(
                 bundler,
                 repo,
                 oldincludes,
diff --git a/hgext/narrow/narrowbundle2.py b/hgext/narrow/narrowbundle2.py
--- a/hgext/narrow/narrowbundle2.py
+++ b/hgext/narrow/narrowbundle2.py
@@ -184,6 +184,105 @@
             part.addparam(b'treemanifest', b'1')
 
 
+def generate_ellipses_bundle2_for_widening(
+    bundler,
+    repo,
+    oldinclude,
+    oldexclude,
+    newinclude,
+    newexclude,
+    version,
+    common,
+    heads,
+    known,
+    depth,
+):
+    newmatch = narrowspec.match(
+        repo.root, include=newinclude, exclude=newexclude
+    )
+    if depth is not None:
+        depth = int(depth)
+        if depth < 1:
+            raise error.Abort(_(b'depth must be positive, got %d') % depth)
+
+    heads = set(heads or repo.heads())
+    common = set(common or [nullid])
+    if known and (oldinclude != newinclude or oldexclude != newexclude):
+        # Steps:
+        # 1. Send kill for "$known & ::common"
+        #
+        # 2. Send changegroup for ::common
+        #
+        # 3. Proceed.
+        #
+        # In the future, we can send kills for only the specific
+        # nodes we know should go away or change shape, and then
+        # send a data stream that tells the client something like this:
+        #
+        # a) apply this changegroup
+        # b) apply nodes XXX, YYY, ZZZ that you already have
+        # c) goto a
+        #
+        # until they've built up the full new state.
+        # Convert to revnums and intersect with "common". The client should
+        # have made it a subset of "common" already, but let's be safe.
+        known = set(repo.revs(b"%ln & ::%ln", known, common))
+        # TODO: we could send only roots() of this set, and the
+        # list of nodes in common, and the client could work out
+        # what to strip, instead of us explicitly sending every
+        # single node.
+        deadrevs = known
+
+        def genkills():
+            for r in deadrevs:
+                yield _KILLNODESIGNAL
+                yield repo.changelog.node(r)
+            yield _DONESIGNAL
+
+        bundler.newpart(_CHANGESPECPART, data=genkills())
+        newvisit, newfull, newellipsis = exchange._computeellipsis(
+            repo, set(), common, known, newmatch
+        )
+        if newvisit:
+            packer = changegroup.getbundler(
+                version,
+                repo,
+                matcher=newmatch,
+                ellipses=True,
+                shallow=depth is not None,
+                ellipsisroots=newellipsis,
+                fullnodes=newfull,
+            )
+            cgdata = packer.generate(common, newvisit, False, b'narrow_widen')
+
+            part = bundler.newpart(b'changegroup', data=cgdata)
+            part.addparam(b'version', version)
+            if b'treemanifest' in repo.requirements:
+                part.addparam(b'treemanifest', b'1')
+
+    visitnodes, relevant_nodes, ellipsisroots = exchange._computeellipsis(
+        repo, common, heads, set(), newmatch, depth=depth
+    )
+
+    repo.ui.debug(b'Found %d relevant revs\n' % len(relevant_nodes))
+    if visitnodes:
+        packer = changegroup.getbundler(
+            version,
+            repo,
+            matcher=newmatch,
+            ellipses=True,
+            shallow=depth is not None,
+            ellipsisroots=ellipsisroots,
+            fullnodes=relevant_nodes,
+        )
+        cgdata = packer.generate(common, visitnodes, False, b'narrow_widen')
+
+        part = bundler.newpart(b'changegroup', data=cgdata)
+        part.addparam(b'version', version)
+        if b'treemanifest' in repo.requirements:
+            part.addparam(b'treemanifest', b'1')
+
+
 @bundle2.parthandler(_SPECPART, (_SPECPART_INCLUDE, _SPECPART_EXCLUDE))
 def _handlechangespec_2(op, inpart):
     # XXX: This bundle2 handling is buggy and should be removed after hg5.2 is



To: martinvonz, durin42, #hg-reviewers
Cc: mercurial-devel


More information about the Mercurial-devel mailing list