[PATCH 3 of 3] bundle2: fix bundle2 pulling all revs on empty pulls

Durham Goode durham at fb.com
Wed May 7 20:44:18 CDT 2014


# HG changeset patch
# User Durham Goode <durham at fb.com>
# Date 1399508659 25200
#      Wed May 07 17:24:19 2014 -0700
# Node ID b6bab8abfb834eddf6387b4db42be26d472bc943
# Parent  d2f14d289ef0b11f96262f0b226c6c360fa8467e
bundle2: fix bundle2 pulling all revs on empty pulls

When bundle2 was enabled, if hg pull had no commits to pull, it would print
'no changes found' and then download the entire repository from the server. This
was caused by heads and common being set to None, which gets treated as
heads=cl.heads() and common=[nullid], which means download the entire repo.

Pulling bundles without a changegroup is a valid use case (like if we're just
updating bookmarks), so this modifes the bundle code to allow not adding
changegroups.

diff --git a/mercurial/exchange.py b/mercurial/exchange.py
--- a/mercurial/exchange.py
+++ b/mercurial/exchange.py
@@ -573,12 +573,13 @@
     kwargs['bundlecaps'].add('bundle2=' + urllib.quote(capsblob))
     # pulling changegroup
     pullop.todosteps.remove('changegroup')
+
+    kwargs['common'] = pullop.common
+    kwargs['heads'] = pullop.heads or pullop.rheads
     if not pullop.fetch:
-            pullop.repo.ui.status(_("no changes found\n"))
-            pullop.cgresult = 0
+        pullop.repo.ui.status(_("no changes found\n"))
+        pullop.cgresult = 0
     else:
-        kwargs['common'] = pullop.common
-        kwargs['heads'] = pullop.heads or pullop.rheads
         if pullop.heads is None and list(pullop.common) == [nullid]:
             pullop.repo.ui.status(_("requesting all changes\n"))
     _pullbundle2extraprepare(pullop, kwargs)
@@ -589,8 +590,10 @@
         op = bundle2.processbundle(pullop.repo, bundle, pullop.gettransaction)
     except bundle2.UnknownPartError, exc:
         raise util.Abort('missing support for %s' % exc)
-    assert len(op.records['changegroup']) == 1
-    pullop.cgresult = op.records['changegroup'][0]['return']
+
+    if pullop.fetch:
+        assert len(op.records['changegroup']) == 1
+        pullop.cgresult = op.records['changegroup'][0]['return']
 
 def _pullbundle2extraprepare(pullop, kwargs):
     """hook function so that extensions can extend the getbundle call"""
@@ -684,7 +687,7 @@
     The implementation is at a very early stage and will get massive rework
     when the API of bundle is refined.
     """
-    # build bundle here.
+    # build changegroup bundle here.
     cg = changegroup.getbundle(repo, source, heads=heads,
                                common=common, bundlecaps=bundlecaps)
     if bundlecaps is None or 'HG2X' not in bundlecaps:
@@ -697,10 +700,11 @@
             blob = urllib.unquote(bcaps[len('bundle2='):])
             b2caps.update(bundle2.decodecaps(blob))
     bundler = bundle2.bundle20(repo.ui, b2caps)
-    part = bundle2.bundlepart('b2x:changegroup', data=cg.getchunks())
-    bundler.addpart(part)
-    _getbundleextrapart(bundler, repo, source, heads=None, common=None,
-                        bundlecaps=None, **kwargs)
+    if cg:
+        part = bundle2.bundlepart('b2x:changegroup', data=cg.getchunks())
+        bundler.addpart(part)
+    _getbundleextrapart(bundler, repo, source, heads=heads, common=common,
+                        bundlecaps=bundlecaps, **kwargs)
     return util.chunkbuffer(bundler.getchunks())
 
 def _getbundleextrapart(bundler, repo, source, heads=None, common=None,
diff --git a/tests/test-bundle2.t b/tests/test-bundle2.t
--- a/tests/test-bundle2.t
+++ b/tests/test-bundle2.t
@@ -791,6 +791,12 @@
   added 1 changesets with 1 changes to 1 files (+1 heads)
   (run 'hg heads' to see heads, 'hg merge' to merge)
 
+pull empty
+
+  $ hg -R other pull -r 24b6387c8c8c
+  pulling from $TESTTMP/main (glob)
+  no changes found
+
 push
 
   $ hg -R main push other --rev eea13746799a


More information about the Mercurial-devel mailing list