Patchwork [4,of,4,STABLE] bundle2: fix bundle2 pulling all revs on empty pulls

login
register
mail settings
Submitter Pierre-Yves David
Date May 15, 2014, 5:50 a.m.
Message ID <235ed8ca9a16f6231fc5.1400133016@marginatus.alto.octopoid.net>
Download mbox | patch
Permalink /patch/4750/
State Accepted
Commit 4dca1a06e7ee6c7569d9c3f0b5885a4f068e52bc
Headers show

Comments

Pierre-Yves David - May 15, 2014, 5:50 a.m.
# HG changeset patch
# User Durham Goode <durham@fb.com>
# Date 1399508659 25200
#      Wed May 07 17:24:19 2014 -0700
# Branch stable
# Node ID 235ed8ca9a16f6231fc5c3bf1346cc1a25430c8c
# Parent  8660d5af350f5a7cd0a0662782f43c42dee305fb
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.

This is backport of ab5040cd5749.
Matt Mackall - May 27, 2014, 11:04 p.m.
On Wed, 2014-05-14 at 22:50 -0700, pierre-yves.david@ens-lyon.org wrote:
> # HG changeset patch
> # User Durham Goode <durham@fb.com>
> # Date 1399508659 25200
> #      Wed May 07 17:24:19 2014 -0700
> # Branch stable
> # Node ID 235ed8ca9a16f6231fc5c3bf1346cc1a25430c8c
> # Parent  8660d5af350f5a7cd0a0662782f43c42dee305fb
> bundle2: fix bundle2 pulling all revs on empty pulls

These are queued for stable, thanks.

Patch

diff --git a/mercurial/exchange.py b/mercurial/exchange.py
--- a/mercurial/exchange.py
+++ b/mercurial/exchange.py
@@ -571,28 +571,31 @@  def _pullbundle2(pullop):
     kwargs = {'bundlecaps': set(['HG2X'])}
     capsblob = bundle2.encodecaps(pullop.repo.bundle2caps)
     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
     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)
     if kwargs.keys() == ['format']:
         return # nothing to pull
     bundle = pullop.remote.getbundle('pull', **kwargs)
     try:
         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"""
     pass
 
@@ -682,11 +685,11 @@  def getbundle(repo, source, heads=None, 
     have a clearer idea of the API we what to query different data.
 
     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:
         return cg
     # very crude first implementation,
@@ -695,12 +698,13 @@  def getbundle(repo, source, heads=None, 
     for bcaps in bundlecaps:
         if bcaps.startswith('bundle2='):
             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)
+    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
@@ -789,10 +789,16 @@  pull
   adding manifests
   adding file changes
   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
   pushing to other
   searching for changes