[PATCH 1 of 3 v2] bundle2: store list of bundled nodes and heads in bundle20 instance

Gregory Szorc gregory.szorc at gmail.com
Mon Jun 1 22:56:13 CDT 2015

# HG changeset patch
# User Gregory Szorc <gregory.szorc at gmail.com>
# Date 1432593644 25200
#      Mon May 25 15:40:44 2015 -0700
# Node ID 2c67a5830d8dfcb3c76d9a171abe18c19caf05db
# Parent  eb52de500d2a308761b65bc9efaf85272c27eca5
bundle2: store list of bundled nodes and heads in bundle20 instance

bundle2 provides the ability to store and transfer extra metadata
through parts. Part generators may wish to transfer per-changeset
data. Because this may be a common operation, part generators will
want a way to quickly access the list of changesets contained in the
bundle. This patch implements such a feature.

We add "bundlednodes" and "bundledheads" attributes to the
bundle20 class which hold the list of changesets and heads,
respectively, in the bundle.

Part generators are passed "missing" and "heads" arguments today.
It may be tempting for part generators to key off of these to
compute the set of missing nodes or heads. However, doing so may
not always be correct! With remote changegroups, the client may be
instructed to apply a remote bundle2 that already contains the
metadata a part handler may add. In this scenario, if the part
handler keyed off the "missing" and "heads" arguments passed to
it, it may redundantly transfer data that was included in the remote
bundle2. By having the changegroup part generator explicitly record
the changesets and heads in the bundle, we prevent this potential
redundant transfer of data.

diff --git a/mercurial/bundle2.py b/mercurial/bundle2.py
--- a/mercurial/bundle2.py
+++ b/mercurial/bundle2.py
@@ -469,8 +469,12 @@ class bundle20(object):
         self.ui = ui
         self._params = []
         self._parts = []
         self.capabilities = dict(capabilities)
+        # List of changesets in changegroup parts in this bundle.
+        self.bundlednodes = []
+        # List of head nodes in changegroup parts in this bundle.
+        self.bundledheads = []
     def nbparts(self):
         """total number of parts added to the bundler"""
diff --git a/mercurial/exchange.py b/mercurial/exchange.py
--- a/mercurial/exchange.py
+++ b/mercurial/exchange.py
@@ -499,8 +499,10 @@ def _pushb2ctx(pushop, bundler):
         version = max(cgversions)
         cg = changegroup.getlocalchangegroupraw(pushop.repo, 'push',
+    bundler.bundlednodes.extend(pushop.outgoing.missing)
+    bundler.bundledheads.extend(pushop.outgoing.missingheads)
     cgpart = bundler.newpart('changegroup', data=cg)
     if version is not None:
         cgpart.addparam('version', version)
     def handlereply(op):
@@ -1260,8 +1262,11 @@ def _getbundlechangegrouppart(bundler, r
     if cg:
         part = bundler.newpart('changegroup', data=cg)
         if version is not None:
             part.addparam('version', version)
+        outgoing = changegroup._computeoutgoing(repo, heads, common)
+        bundler.bundlednodes.extend(outgoing.missing)
+        bundler.bundledheads.extend(outgoing.missingheads)
 def _getbundlelistkeysparts(bundler, repo, source, bundlecaps=None,
                             b2caps=None, **kwargs):

More information about the Mercurial-devel mailing list