changeset 4129:bc4e62a1cb82

pullbundle: slice pull into multiple ranges We subdivide the set of missing revisions into multiple "range" using the "stable range" data structure. This slicing aims at maximizing the capability of the resulting ranges.
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Sun, 23 Sep 2018 23:41:08 +0200
parents 4e5ec9ae682e
children a1f6b8211016
files hgext3rd/pullbundle.py tests/test-pullbundle.t
diffstat 2 files changed, 1885 insertions(+), 40 deletions(-) [+]
line wrap: on
line diff
--- a/hgext3rd/pullbundle.py	Sun Sep 23 23:53:23 2018 +0200
+++ b/hgext3rd/pullbundle.py	Sun Sep 23 23:41:08 2018 +0200
@@ -5,14 +5,22 @@
 # This software may be used and distributed according to the terms of the
 # GNU General Public License version 2 or any later version.
 
+import errno
+import os
+
 from mercurial import (
     changegroup,
+    discovery,
     exchange,
     narrowspec,
+    node as nodemod,
+    util,
 )
 
 from mercurial.i18n import _
 
+# generic wrapping
+
 def uisetup(ui):
     exchange.getbundle2partsmapping['changegroup'] = _getbundlechangegrouppart
 
@@ -59,14 +67,156 @@
 
 def makeallcgpart(newpart, repo, outgoing, version, source,
                   bundlecaps, filematcher, cgversions):
-    makeonecgpart(newpart, repo, outgoing, version, source, bundlecaps,
-                  filematcher, cgversions)
+
+    pullbundle = not filematcher
+    if pullbundle and not util.safehasattr(repo, 'stablerange'):
+        repo.ui.warn('pullbundle: required extension "evolve" are missing, skipping pullbundle\n')
+        pullbundle = False
+    if filematcher:
+        makeonecgpart(newpart, repo, None, outgoing, version, source, bundlecaps,
+                      filematcher, cgversions)
+    else:
+        for sliceid, sliceout in sliceoutgoing(repo, outgoing):
+            makeonecgpart(newpart, repo, sliceid, sliceout, version, source, bundlecaps,
+                          filematcher, cgversions)
+
+# stable range slicing
+
+def sliceoutgoing(repo, outgoing):
+    cl = repo.changelog
+    rev = cl.nodemap.get
+    node = cl.node
+    revsort = repo.stablesort
+
+    missingrevs = set(rev(n) for n in outgoing.missing)
+    allslices = []
+    missingheads = [rev(n) for n in outgoing.missingheads]
+    for head in missingheads:
+        localslices = []
+        localmissing = set(repo.revs('%ld and ::%d', missingrevs, head))
+        while localmissing:
+            slicerevs = []
+            for r in revsort.walkfrom(repo, head):
+                if r not in missingrevs:
+                    break
+                slicerevs.append(r)
+            slicenodes = [node(r) for r in slicerevs]
+            localslices.extend(canonicalslices(repo, slicenodes))
+            missingrevs.difference_update(slicerevs)
+            localmissing.difference_update(slicerevs)
+            if localmissing:
+                head = max(localmissing)
+
+        allslices.extend(localslices)
+    return [(rangeid, outgoingfromnodes(repo, nodes))
+            for rangeid, nodes in allslices]
+
+def canonicalslices(repo, nodes):
+    depth = repo.depthcache.get
+    stablerange = repo.stablerange
+    rangelength = lambda x: stablerange.rangelength(repo, x)
+    headrev = repo.changelog.rev(nodes[0])
+    nbrevs = len(nodes)
+    headdepth = depth(headrev)
+    skipped = headdepth - nbrevs
+    rangeid = (headrev, skipped)
+
+    subranges = canonicalsubranges(repo, stablerange, rangeid)
+    idx = 0
+    slices =[]
+    nodes.reverse()
+    for rangeid in subranges:
+        size = rangelength(rangeid)
+        slices.append((rangeid, nodes[idx:idx + size]))
+        idx += size
+    return slices
+
+def canonicalsubranges(repo, stablerange, rangeid):
+    """slice a size of nodes into most reusable subranges
+
+    We try to slice a range into a set of "largest" and "canonical" stable
+    range.
+
+    It might make sense to move this function as a 'stablerange' method.
+    """
+    headrev, skip = rangeid
+    rangedepth = stablerange.depthrev(repo, rangeid[0])
+    canonicals = []
+
+    # 0. find the first power of 2 higher than this range depth
+    cursor = 1
+    while cursor <= rangedepth:
+        cursor *= 2
+
+    # 1. find first cupt
+    precut = cut = 0
+    while True:
+        if skip <= cut:
+            break
+        if cut + cursor < rangedepth:
+            precut = cut
+            cut += cursor
+        if cursor == 1:
+            break
+        cursor //=2
+
+    # 2. optimise, bottom part
+    if skip != cut:
+        tailranges = []
+        tailsize = cut - skip
+        assert 0 < tailsize, tailsize
+        prerange = (headrev, precut)
+        size = stablerange.rangelength(repo, prerange)
+        sub = stablerange.subranges(repo, prerange)[:-1]
+        while not poweroftwo(tailsize):
+            for prerange in reversed(sub):
+                if tailsize <= 0:
+                    break
+
+                assert stablerange.depthrev(repo, prerange[0]) != prerange[1], prerange
+                tailrev, tailskip = prerange
+                size = stablerange.rangelength(repo, (tailrev, tailskip))
+                if tailsize < size:
+                    tailskip += size - tailsize
+                    size = tailsize
+                tailranges.append((tailrev, tailskip))
+                tailsize -= size
+            else:
+                # size of the last block
+                tailsize = stablerange.rangelength(repo, tailranges[-1])
+                if poweroftwo(tailsize):
+                    continue # exit the loop
+                prerange = tailranges.pop()
+                sub = stablerange.subranges(repo, prerange)
+
+        tailranges.reverse()
+        canonicals.extend(tailranges)
+
+    # 3. take recursive subrange until we get to a power of two size?
+    current = (headrev, cut)
+    while not poweroftwo(stablerange.rangelength(repo, current)):
+        sub = stablerange.subranges(repo, current)
+        canonicals.extend(sub[:-1])
+        current = sub[-1]
+    canonicals.append(current)
+
+    return canonicals
+
+def poweroftwo(num):
+    return num and not num & (num - 1)
+
+def outgoingfromnodes(repo, nodes):
+    return discovery.outgoing(repo,
+                              missingroots=nodes,
+                              missingheads=nodes)
+
+# changegroup part construction
 
 def _changegroupinfo(repo, nodes, source):
     if repo.ui.verbose or source == 'bundle':
         repo.ui.status(_("%d changesets found\n") % len(nodes))
 
-def makeonecgpart(newpart, repo, outgoing, version, source,
+def makeonecgpart(newpart, repo, rangeid, outgoing, version, source,
                   bundlecaps, filematcher, cgversions):
     # same as upstream code
 
--- a/tests/test-pullbundle.t	Sun Sep 23 23:53:23 2018 +0200
+++ b/tests/test-pullbundle.t	Sun Sep 23 23:41:08 2018 +0200
@@ -2,7 +2,11 @@
 
   $ cat << EOF >> $HGRCPATH
   > [extensions]
+  > # evolve is providing the stable range code
+  > evolve=
   > pullbundle=
+  > [experimental]
+  > obshashrange.warm-cache=yes
   > EOF
 
 basic setup
@@ -10,16 +14,31 @@
   $ hg init server
   $ hg -R server debugbuilddag '.+898:branchpoint+352:mergepoint+267<branchpoint+145/mergepoint+467'
   $ hg init client
+  $ hg init client2
+  $ hg init client3
 
 simple initial pull
 -------------------
 
+  $ hg -R server log -G -T '{rev}:{node}\n' -r '0+1234+(::1234 and (merge() or branchpoint()))'
+  o  1234:f864bc82f6a2f2ecb49b83722e0895f9d657b0dd
+  :
+  o  898:1388f909cd2b0685efd4e2ce076d198bce20922c
+  :
+  o  0:1ea73414a91b0920940797d8fc6a11e447f8ea1e
+  
+
   $ hg -R client pull server -r 1234 --debug --config devel.bundle2.debug=yes | grep -v 'add changeset'
   pulling from server
   query 1; heads
-  1235 changesets found
+  1024 changesets found
+  128 changesets found
+  64 changesets found
+  16 changesets found
+  2 changesets found
+  1 changesets found
   listing keys for "bookmarks"
-  bundle2-output-bundle: "HG20", 4 parts total
+  bundle2-output-bundle: "HG20", 9 parts total
   bundle2-output: start emission of HG20 stream
   bundle2-output: bundle parameter: 
   bundle2-output: start of parts
@@ -32,23 +51,660 @@
   bundle2-output: payload chunk size: 32768
   bundle2-output: payload chunk size: 32768
   bundle2-output: payload chunk size: 32768
-  bundle2-output: payload chunk size: 32768
-  bundle2-output: payload chunk size: 28424
+  bundle2-output: payload chunk size: 22368
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 1: "CHANGEGROUP"
+  bundle2-output: header chunk size: 43
+  bundle2-output: payload chunk size: 23564
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 2: "CHANGEGROUP"
+  bundle2-output: header chunk size: 42
+  bundle2-output: payload chunk size: 11788
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 3: "CHANGEGROUP"
+  bundle2-output: header chunk size: 42
+  bundle2-output: payload chunk size: 2956
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 4: "CHANGEGROUP"
+  bundle2-output: header chunk size: 41
+  bundle2-output: payload chunk size: 380
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 5: "CHANGEGROUP"
+  bundle2-output: header chunk size: 41
+  bundle2-output: payload chunk size: 196
   bundle2-output: closing payload chunk
   bundle2-output: bundle part: "listkeys"
   bundle2-output-part: "listkeys" (params: 1 mandatory) empty payload
-  bundle2-output: part 1: "LISTKEYS"
+  bundle2-output: part 6: "LISTKEYS"
   bundle2-output: header chunk size: 35
   bundle2-output: closing payload chunk
   bundle2-output: bundle part: "phase-heads"
   bundle2-output-part: "phase-heads" 24 bytes payload
-  bundle2-output: part 2: "PHASE-HEADS"
+  bundle2-output: part 7: "PHASE-HEADS"
   bundle2-output: header chunk size: 18
   bundle2-output: payload chunk size: 24
   bundle2-output: closing payload chunk
   bundle2-output: bundle part: "cache:rev-branch-cache"
   bundle2-output-part: "cache:rev-branch-cache" (advisory) streamed payload
-  bundle2-output: part 3: "cache:rev-branch-cache"
+  bundle2-output: part 8: "cache:rev-branch-cache"
+  bundle2-output: header chunk size: 29
+  bundle2-output: payload chunk size: 24719
+  bundle2-output: closing payload chunk
+  bundle2-output: end of bundle
+  bundle2-input: start processing of HG20 stream
+  bundle2-input: reading bundle2 stream parameters
+  bundle2-input-bundle: with-transaction
+  bundle2-input: start extraction of bundle2 parts
+  bundle2-input: part header size: 44
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "0"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 32768
+  bundle2-input: payload chunk size: 32768
+  bundle2-input: payload chunk size: 32768
+  bundle2-input: payload chunk size: 32768
+  bundle2-input: payload chunk size: 32768
+  bundle2-input: payload chunk size: 22368
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 1024 changesets with 0 changes to 0 files
+  bundle2-input-part: total payload size 186208
+  bundle2-input: part header size: 43
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "1"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 23564
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 128 changesets with 0 changes to 0 files
+  bundle2-input-part: total payload size 23564
+  bundle2-input: part header size: 42
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "2"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 11788
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 64 changesets with 0 changes to 0 files
+  bundle2-input-part: total payload size 11788
+  bundle2-input: part header size: 42
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "3"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 2956
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 16 changesets with 0 changes to 0 files
+  bundle2-input-part: total payload size 2956
+  bundle2-input: part header size: 41
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "4"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 380
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 2 changesets with 0 changes to 0 files
+  bundle2-input-part: total payload size 380
+  bundle2-input: part header size: 41
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "5"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 196
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 1 changesets with 0 changes to 0 files
+  bundle2-input-part: total payload size 196
+  bundle2-input: part header size: 35
+  bundle2-input: part type: "LISTKEYS"
+  bundle2-input: part id: "6"
+  bundle2-input: part parameters: 1
+  bundle2-input: found a handler for part listkeys
+  bundle2-input-part: "listkeys" (params: 1 mandatory) supported
+  bundle2-input: payload chunk size: 0
+  bundle2-input: part header size: 18
+  bundle2-input: part type: "PHASE-HEADS"
+  bundle2-input: part id: "7"
+  bundle2-input: part parameters: 0
+  bundle2-input: found a handler for part phase-heads
+  bundle2-input-part: "phase-heads" supported
+  bundle2-input: payload chunk size: 24
+  bundle2-input: payload chunk size: 0
+  bundle2-input-part: total payload size 24
+  bundle2-input: part header size: 29
+  bundle2-input: part type: "cache:rev-branch-cache"
+  bundle2-input: part id: "8"
+  bundle2-input: part parameters: 0
+  bundle2-input: found a handler for part cache:rev-branch-cache
+  bundle2-input-part: "cache:rev-branch-cache" (advisory) supported
+  bundle2-input: payload chunk size: 24719
+  bundle2-input: payload chunk size: 0
+  bundle2-input-part: total payload size 24719
+  bundle2-input: part header size: 0
+  bundle2-input: end of bundle2 stream
+  bundle2-input-bundle: 8 parts total
+  checking for updated bookmarks
+  updating the branch cache
+  new changesets 1ea73414a91b:f864bc82f6a2
+  (run 'hg update' to get a working copy)
+
+pull the other missing entries (multiple heads pulled)
+------------------------------------------------------
+
+  $ hg -R server log -G -T '{rev}:{node}\n' -r '1234+head()+(only(head(), 1234) and (merge() or branchpoint()))'
+  o  2130:0f376356904fc8c1c6ceaac27990f2fd79b1f8c1
+  :
+  o    1663:1710092b3ab17a6d2ecad664580991a608537749
+  |\
+  | ~
+  | o  1517:1dded5aafa0f8d548f6357cc2f8882dcc4489fbf
+  |/
+  o  1250:d83212ecaa436c80d6113cf915ba35e2db787e79
+  :
+  o  1234:f864bc82f6a2f2ecb49b83722e0895f9d657b0dd
+  |
+  ~
+  $ hg -R client pull server --debug --config devel.bundle2.debug=yes | grep -v 'add changeset'
+  pulling from server
+  query 1; heads
+  searching for changes
+  all local heads known remotely
+  16 changesets found
+  29 changesets found
+  256 changesets found
+  256 changesets found
+  64 changesets found
+  8 changesets found
+  1 changesets found
+  4 changesets found
+  8 changesets found
+  16 changesets found
+  128 changesets found
+  64 changesets found
+  32 changesets found
+  8 changesets found
+  4 changesets found
+  2 changesets found
+  listing keys for "bookmarks"
+  bundle2-output-bundle: "HG20", 19 parts total
+  bundle2-output: start emission of HG20 stream
+  bundle2-output: bundle parameter: 
+  bundle2-output: start of parts
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 0: "CHANGEGROUP"
+  bundle2-output: header chunk size: 42
+  bundle2-output: payload chunk size: 2956
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 1: "CHANGEGROUP"
+  bundle2-output: header chunk size: 42
+  bundle2-output: payload chunk size: 5348
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 2: "CHANGEGROUP"
+  bundle2-output: header chunk size: 43
+  bundle2-output: payload chunk size: 32768
+  bundle2-output: payload chunk size: 14348
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 3: "CHANGEGROUP"
+  bundle2-output: header chunk size: 43
+  bundle2-output: payload chunk size: 32768
+  bundle2-output: payload chunk size: 14348
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 4: "CHANGEGROUP"
+  bundle2-output: header chunk size: 42
+  bundle2-output: payload chunk size: 11788
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 5: "CHANGEGROUP"
+  bundle2-output: header chunk size: 41
+  bundle2-output: payload chunk size: 1484
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 6: "CHANGEGROUP"
+  bundle2-output: header chunk size: 41
+  bundle2-output: payload chunk size: 196
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 7: "CHANGEGROUP"
+  bundle2-output: header chunk size: 41
+  bundle2-output: payload chunk size: 748
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 8: "CHANGEGROUP"
+  bundle2-output: header chunk size: 41
+  bundle2-output: payload chunk size: 1484
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 9: "CHANGEGROUP"
+  bundle2-output: header chunk size: 42
+  bundle2-output: payload chunk size: 2956
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 10: "CHANGEGROUP"
+  bundle2-output: header chunk size: 43
+  bundle2-output: payload chunk size: 23564
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 11: "CHANGEGROUP"
+  bundle2-output: header chunk size: 42
+  bundle2-output: payload chunk size: 11788
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 12: "CHANGEGROUP"
+  bundle2-output: header chunk size: 42
+  bundle2-output: payload chunk size: 5900
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 13: "CHANGEGROUP"
+  bundle2-output: header chunk size: 41
+  bundle2-output: payload chunk size: 1484
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 14: "CHANGEGROUP"
+  bundle2-output: header chunk size: 41
+  bundle2-output: payload chunk size: 748
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 15: "CHANGEGROUP"
+  bundle2-output: header chunk size: 41
+  bundle2-output: payload chunk size: 380
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "listkeys"
+  bundle2-output-part: "listkeys" (params: 1 mandatory) empty payload
+  bundle2-output: part 16: "LISTKEYS"
+  bundle2-output: header chunk size: 35
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "phase-heads"
+  bundle2-output-part: "phase-heads" 48 bytes payload
+  bundle2-output: part 17: "PHASE-HEADS"
+  bundle2-output: header chunk size: 18
+  bundle2-output: payload chunk size: 48
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "cache:rev-branch-cache"
+  bundle2-output-part: "cache:rev-branch-cache" (advisory) streamed payload
+  bundle2-output: part 18: "cache:rev-branch-cache"
+  bundle2-output: header chunk size: 29
+  bundle2-output: payload chunk size: 17939
+  bundle2-output: closing payload chunk
+  bundle2-output: end of bundle
+  bundle2-input: start processing of HG20 stream
+  bundle2-input: reading bundle2 stream parameters
+  bundle2-input-bundle: with-transaction
+  bundle2-input: start extraction of bundle2 parts
+  bundle2-input: part header size: 42
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "0"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 2956
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 16 changesets with 0 changes to 0 files
+  bundle2-input-part: total payload size 2956
+  bundle2-input: part header size: 42
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "1"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 5348
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 29 changesets with 0 changes to 0 files (+1 heads)
+  bundle2-input-part: total payload size 5348
+  bundle2-input: part header size: 43
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "2"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 32768
+  bundle2-input: payload chunk size: 14348
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 256 changesets with 0 changes to 0 files (-1 heads)
+  bundle2-input-part: total payload size 47116
+  bundle2-input: part header size: 43
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "3"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 32768
+  bundle2-input: payload chunk size: 14348
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 256 changesets with 0 changes to 0 files
+  bundle2-input-part: total payload size 47116
+  bundle2-input: part header size: 42
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "4"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 11788
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 64 changesets with 0 changes to 0 files
+  bundle2-input-part: total payload size 11788
+  bundle2-input: part header size: 41
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "5"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 1484
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 8 changesets with 0 changes to 0 files
+  bundle2-input-part: total payload size 1484
+  bundle2-input: part header size: 41
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "6"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 196
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 1 changesets with 0 changes to 0 files (+1 heads)
+  bundle2-input-part: total payload size 196
+  bundle2-input: part header size: 41
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "7"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 748
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 4 changesets with 0 changes to 0 files
+  bundle2-input-part: total payload size 748
+  bundle2-input: part header size: 41
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "8"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 1484
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 8 changesets with 0 changes to 0 files
+  bundle2-input-part: total payload size 1484
+  bundle2-input: part header size: 42
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "9"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 2956
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 16 changesets with 0 changes to 0 files
+  bundle2-input-part: total payload size 2956
+  bundle2-input: part header size: 43
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "10"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 23564
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 128 changesets with 0 changes to 0 files
+  bundle2-input-part: total payload size 23564
+  bundle2-input: part header size: 42
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "11"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 11788
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 64 changesets with 0 changes to 0 files
+  bundle2-input-part: total payload size 11788
+  bundle2-input: part header size: 42
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "12"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 5900
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 32 changesets with 0 changes to 0 files
+  bundle2-input-part: total payload size 5900
+  bundle2-input: part header size: 41
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "13"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 1484
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 8 changesets with 0 changes to 0 files
+  bundle2-input-part: total payload size 1484
+  bundle2-input: part header size: 41
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "14"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 748
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 4 changesets with 0 changes to 0 files
+  bundle2-input-part: total payload size 748
+  bundle2-input: part header size: 41
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "15"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 380
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 2 changesets with 0 changes to 0 files
+  bundle2-input-part: total payload size 380
+  bundle2-input: part header size: 35
+  bundle2-input: part type: "LISTKEYS"
+  bundle2-input: part id: "16"
+  bundle2-input: part parameters: 1
+  bundle2-input: found a handler for part listkeys
+  bundle2-input-part: "listkeys" (params: 1 mandatory) supported
+  bundle2-input: payload chunk size: 0
+  bundle2-input: part header size: 18
+  bundle2-input: part type: "PHASE-HEADS"
+  bundle2-input: part id: "17"
+  bundle2-input: part parameters: 0
+  bundle2-input: found a handler for part phase-heads
+  bundle2-input-part: "phase-heads" supported
+  bundle2-input: payload chunk size: 48
+  bundle2-input: payload chunk size: 0
+  bundle2-input-part: total payload size 48
+  bundle2-input: part header size: 29
+  bundle2-input: part type: "cache:rev-branch-cache"
+  bundle2-input: part id: "18"
+  bundle2-input: part parameters: 0
+  bundle2-input: found a handler for part cache:rev-branch-cache
+  bundle2-input-part: "cache:rev-branch-cache" (advisory) supported
+  bundle2-input: payload chunk size: 17939
+  bundle2-input: payload chunk size: 0
+  bundle2-input-part: total payload size 17939
+  bundle2-input: part header size: 0
+  bundle2-input: end of bundle2 stream
+  bundle2-input-bundle: 18 parts total
+  checking for updated bookmarks
+  updating the branch cache
+  new changesets 17185c1c22f1:1dded5aafa0f
+  (run 'hg heads' to see heads, 'hg merge' to merge)
+
+Same Pullin with a different client
+-----------------------------------
+  $ hg -R server log -G -T '{rev}:{node}\n' -r '0+1234+(::1234 and (merge() or branchpoint()))'
+  o  1234:f864bc82f6a2f2ecb49b83722e0895f9d657b0dd
+  :
+  o  898:1388f909cd2b0685efd4e2ce076d198bce20922c
+  :
+  o  0:1ea73414a91b0920940797d8fc6a11e447f8ea1e
+  
+
+  $ hg -R client2 pull server -r 1234 --debug --config devel.bundle2.debug=yes --traceback| grep -v 'add changeset'
+  pulling from server
+  query 1; heads
+  1024 changesets found
+  128 changesets found
+  64 changesets found
+  16 changesets found
+  2 changesets found
+  1 changesets found
+  listing keys for "bookmarks"
+  bundle2-output-bundle: "HG20", 9 parts total
+  bundle2-output: start emission of HG20 stream
+  bundle2-output: bundle parameter: 
+  bundle2-output: start of parts
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 0: "CHANGEGROUP"
+  bundle2-output: header chunk size: 44
+  bundle2-output: payload chunk size: 32768
+  bundle2-output: payload chunk size: 32768
+  bundle2-output: payload chunk size: 32768
+  bundle2-output: payload chunk size: 32768
+  bundle2-output: payload chunk size: 32768
+  bundle2-output: payload chunk size: 22368
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 1: "CHANGEGROUP"
+  bundle2-output: header chunk size: 43
+  bundle2-output: payload chunk size: 23564
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 2: "CHANGEGROUP"
+  bundle2-output: header chunk size: 42
+  bundle2-output: payload chunk size: 11788
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 3: "CHANGEGROUP"
+  bundle2-output: header chunk size: 42
+  bundle2-output: payload chunk size: 2956
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 4: "CHANGEGROUP"
+  bundle2-output: header chunk size: 41
+  bundle2-output: payload chunk size: 380
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 5: "CHANGEGROUP"
+  bundle2-output: header chunk size: 41
+  bundle2-output: payload chunk size: 196
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "listkeys"
+  bundle2-output-part: "listkeys" (params: 1 mandatory) empty payload
+  bundle2-output: part 6: "LISTKEYS"
+  bundle2-output: header chunk size: 35
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "phase-heads"
+  bundle2-output-part: "phase-heads" 24 bytes payload
+  bundle2-output: part 7: "PHASE-HEADS"
+  bundle2-output: header chunk size: 18
+  bundle2-output: payload chunk size: 24
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "cache:rev-branch-cache"
+  bundle2-output-part: "cache:rev-branch-cache" (advisory) streamed payload
+  bundle2-output: part 8: "cache:rev-branch-cache"
   bundle2-output: header chunk size: 29
   bundle2-output: payload chunk size: 24719
   bundle2-output: closing payload chunk
@@ -69,23 +725,87 @@
   bundle2-input: payload chunk size: 32768
   bundle2-input: payload chunk size: 32768
   bundle2-input: payload chunk size: 32768
-  bundle2-input: payload chunk size: 32768
-  bundle2-input: payload chunk size: 28424
+  bundle2-input: payload chunk size: 22368
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 1024 changesets with 0 changes to 0 files
+  bundle2-input-part: total payload size 186208
+  bundle2-input: part header size: 43
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "1"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 23564
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 128 changesets with 0 changes to 0 files
+  bundle2-input-part: total payload size 23564
+  bundle2-input: part header size: 42
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "2"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 11788
   bundle2-input: payload chunk size: 0
   adding manifests
   adding file changes
-  added 1235 changesets with 0 changes to 0 files
-  bundle2-input-part: total payload size 225032
+  added 64 changesets with 0 changes to 0 files
+  bundle2-input-part: total payload size 11788
+  bundle2-input: part header size: 42
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "3"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 2956
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 16 changesets with 0 changes to 0 files
+  bundle2-input-part: total payload size 2956
+  bundle2-input: part header size: 41
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "4"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 380
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 2 changesets with 0 changes to 0 files
+  bundle2-input-part: total payload size 380
+  bundle2-input: part header size: 41
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "5"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 196
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 1 changesets with 0 changes to 0 files
+  bundle2-input-part: total payload size 196
   bundle2-input: part header size: 35
   bundle2-input: part type: "LISTKEYS"
-  bundle2-input: part id: "1"
+  bundle2-input: part id: "6"
   bundle2-input: part parameters: 1
   bundle2-input: found a handler for part listkeys
   bundle2-input-part: "listkeys" (params: 1 mandatory) supported
   bundle2-input: payload chunk size: 0
   bundle2-input: part header size: 18
   bundle2-input: part type: "PHASE-HEADS"
-  bundle2-input: part id: "2"
+  bundle2-input: part id: "7"
   bundle2-input: part parameters: 0
   bundle2-input: found a handler for part phase-heads
   bundle2-input-part: "phase-heads" supported
@@ -94,7 +814,7 @@
   bundle2-input-part: total payload size 24
   bundle2-input: part header size: 29
   bundle2-input: part type: "cache:rev-branch-cache"
-  bundle2-input: part id: "3"
+  bundle2-input: part id: "8"
   bundle2-input: part parameters: 0
   bundle2-input: found a handler for part cache:rev-branch-cache
   bundle2-input-part: "cache:rev-branch-cache" (advisory) supported
@@ -103,51 +823,164 @@
   bundle2-input-part: total payload size 24719
   bundle2-input: part header size: 0
   bundle2-input: end of bundle2 stream
-  bundle2-input-bundle: 3 parts total
+  bundle2-input-bundle: 8 parts total
   checking for updated bookmarks
   updating the branch cache
   new changesets 1ea73414a91b:f864bc82f6a2
   (run 'hg update' to get a working copy)
 
-pull the other missing entries (multiple heads pulled)
-------------------------------------------------------
+  $ hg -R server log -G -T '{rev}:{node}\n' -r '1234+head()+(only(head(), 1234) and (merge() or branchpoint()))'
+  o  2130:0f376356904fc8c1c6ceaac27990f2fd79b1f8c1
+  :
+  o    1663:1710092b3ab17a6d2ecad664580991a608537749
+  |\
+  | ~
+  | o  1517:1dded5aafa0f8d548f6357cc2f8882dcc4489fbf
+  |/
+  o  1250:d83212ecaa436c80d6113cf915ba35e2db787e79
+  :
+  o  1234:f864bc82f6a2f2ecb49b83722e0895f9d657b0dd
+  |
+  ~
 
-  $ hg -R client pull server --debug --config devel.bundle2.debug=yes | grep -v 'add changeset'
+  $ hg -R client2 pull server --debug --config devel.bundle2.debug=yes | grep -v 'add changeset'
   pulling from server
   query 1; heads
   searching for changes
   all local heads known remotely
-  896 changesets found
+  16 changesets found
+  29 changesets found
+  256 changesets found
+  256 changesets found
+  64 changesets found
+  8 changesets found
+  1 changesets found
+  4 changesets found
+  8 changesets found
+  16 changesets found
+  128 changesets found
+  64 changesets found
+  32 changesets found
+  8 changesets found
+  4 changesets found
+  2 changesets found
   listing keys for "bookmarks"
-  bundle2-output-bundle: "HG20", 4 parts total
+  bundle2-output-bundle: "HG20", 19 parts total
   bundle2-output: start emission of HG20 stream
   bundle2-output: bundle parameter: 
   bundle2-output: start of parts
   bundle2-output: bundle part: "changegroup"
   bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
   bundle2-output: part 0: "CHANGEGROUP"
+  bundle2-output: header chunk size: 42
+  bundle2-output: payload chunk size: 2956
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 1: "CHANGEGROUP"
+  bundle2-output: header chunk size: 42
+  bundle2-output: payload chunk size: 5348
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 2: "CHANGEGROUP"
+  bundle2-output: header chunk size: 43
+  bundle2-output: payload chunk size: 32768
+  bundle2-output: payload chunk size: 14348
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 3: "CHANGEGROUP"
   bundle2-output: header chunk size: 43
   bundle2-output: payload chunk size: 32768
-  bundle2-output: payload chunk size: 32768
-  bundle2-output: payload chunk size: 32768
-  bundle2-output: payload chunk size: 32768
-  bundle2-output: payload chunk size: 32768
-  bundle2-output: payload chunk size: 1036
+  bundle2-output: payload chunk size: 14348
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 4: "CHANGEGROUP"
+  bundle2-output: header chunk size: 42
+  bundle2-output: payload chunk size: 11788
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 5: "CHANGEGROUP"
+  bundle2-output: header chunk size: 41
+  bundle2-output: payload chunk size: 1484
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 6: "CHANGEGROUP"
+  bundle2-output: header chunk size: 41
+  bundle2-output: payload chunk size: 196
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 7: "CHANGEGROUP"
+  bundle2-output: header chunk size: 41
+  bundle2-output: payload chunk size: 748
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 8: "CHANGEGROUP"
+  bundle2-output: header chunk size: 41
+  bundle2-output: payload chunk size: 1484
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 9: "CHANGEGROUP"
+  bundle2-output: header chunk size: 42
+  bundle2-output: payload chunk size: 2956
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 10: "CHANGEGROUP"
+  bundle2-output: header chunk size: 43
+  bundle2-output: payload chunk size: 23564
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 11: "CHANGEGROUP"
+  bundle2-output: header chunk size: 42
+  bundle2-output: payload chunk size: 11788
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 12: "CHANGEGROUP"
+  bundle2-output: header chunk size: 42
+  bundle2-output: payload chunk size: 5900
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 13: "CHANGEGROUP"
+  bundle2-output: header chunk size: 41
+  bundle2-output: payload chunk size: 1484
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 14: "CHANGEGROUP"
+  bundle2-output: header chunk size: 41
+  bundle2-output: payload chunk size: 748
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 15: "CHANGEGROUP"
+  bundle2-output: header chunk size: 41
+  bundle2-output: payload chunk size: 380
   bundle2-output: closing payload chunk
   bundle2-output: bundle part: "listkeys"
   bundle2-output-part: "listkeys" (params: 1 mandatory) empty payload
-  bundle2-output: part 1: "LISTKEYS"
+  bundle2-output: part 16: "LISTKEYS"
   bundle2-output: header chunk size: 35
   bundle2-output: closing payload chunk
   bundle2-output: bundle part: "phase-heads"
   bundle2-output-part: "phase-heads" 48 bytes payload
-  bundle2-output: part 2: "PHASE-HEADS"
+  bundle2-output: part 17: "PHASE-HEADS"
   bundle2-output: header chunk size: 18
   bundle2-output: payload chunk size: 48
   bundle2-output: closing payload chunk
   bundle2-output: bundle part: "cache:rev-branch-cache"
   bundle2-output-part: "cache:rev-branch-cache" (advisory) streamed payload
-  bundle2-output: part 3: "cache:rev-branch-cache"
+  bundle2-output: part 18: "cache:rev-branch-cache"
   bundle2-output: header chunk size: 29
   bundle2-output: payload chunk size: 17939
   bundle2-output: closing payload chunk
@@ -156,8 +989,324 @@
   bundle2-input: reading bundle2 stream parameters
   bundle2-input-bundle: with-transaction
   bundle2-input: start extraction of bundle2 parts
+  bundle2-input: part header size: 42
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "0"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 2956
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 16 changesets with 0 changes to 0 files
+  bundle2-input-part: total payload size 2956
+  bundle2-input: part header size: 42
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "1"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 5348
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 29 changesets with 0 changes to 0 files (+1 heads)
+  bundle2-input-part: total payload size 5348
   bundle2-input: part header size: 43
   bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "2"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 32768
+  bundle2-input: payload chunk size: 14348
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 256 changesets with 0 changes to 0 files (-1 heads)
+  bundle2-input-part: total payload size 47116
+  bundle2-input: part header size: 43
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "3"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 32768
+  bundle2-input: payload chunk size: 14348
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 256 changesets with 0 changes to 0 files
+  bundle2-input-part: total payload size 47116
+  bundle2-input: part header size: 42
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "4"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 11788
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 64 changesets with 0 changes to 0 files
+  bundle2-input-part: total payload size 11788
+  bundle2-input: part header size: 41
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "5"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 1484
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 8 changesets with 0 changes to 0 files
+  bundle2-input-part: total payload size 1484
+  bundle2-input: part header size: 41
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "6"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 196
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 1 changesets with 0 changes to 0 files (+1 heads)
+  bundle2-input-part: total payload size 196
+  bundle2-input: part header size: 41
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "7"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 748
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 4 changesets with 0 changes to 0 files
+  bundle2-input-part: total payload size 748
+  bundle2-input: part header size: 41
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "8"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 1484
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 8 changesets with 0 changes to 0 files
+  bundle2-input-part: total payload size 1484
+  bundle2-input: part header size: 42
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "9"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 2956
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 16 changesets with 0 changes to 0 files
+  bundle2-input-part: total payload size 2956
+  bundle2-input: part header size: 43
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "10"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 23564
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 128 changesets with 0 changes to 0 files
+  bundle2-input-part: total payload size 23564
+  bundle2-input: part header size: 42
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "11"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 11788
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 64 changesets with 0 changes to 0 files
+  bundle2-input-part: total payload size 11788
+  bundle2-input: part header size: 42
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "12"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 5900
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 32 changesets with 0 changes to 0 files
+  bundle2-input-part: total payload size 5900
+  bundle2-input: part header size: 41
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "13"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 1484
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 8 changesets with 0 changes to 0 files
+  bundle2-input-part: total payload size 1484
+  bundle2-input: part header size: 41
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "14"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 748
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 4 changesets with 0 changes to 0 files
+  bundle2-input-part: total payload size 748
+  bundle2-input: part header size: 41
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "15"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 380
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 2 changesets with 0 changes to 0 files
+  bundle2-input-part: total payload size 380
+  bundle2-input: part header size: 35
+  bundle2-input: part type: "LISTKEYS"
+  bundle2-input: part id: "16"
+  bundle2-input: part parameters: 1
+  bundle2-input: found a handler for part listkeys
+  bundle2-input-part: "listkeys" (params: 1 mandatory) supported
+  bundle2-input: payload chunk size: 0
+  bundle2-input: part header size: 18
+  bundle2-input: part type: "PHASE-HEADS"
+  bundle2-input: part id: "17"
+  bundle2-input: part parameters: 0
+  bundle2-input: found a handler for part phase-heads
+  bundle2-input-part: "phase-heads" supported
+  bundle2-input: payload chunk size: 48
+  bundle2-input: payload chunk size: 0
+  bundle2-input-part: total payload size 48
+  bundle2-input: part header size: 29
+  bundle2-input: part type: "cache:rev-branch-cache"
+  bundle2-input: part id: "18"
+  bundle2-input: part parameters: 0
+  bundle2-input: found a handler for part cache:rev-branch-cache
+  bundle2-input-part: "cache:rev-branch-cache" (advisory) supported
+  bundle2-input: payload chunk size: 17939
+  bundle2-input: payload chunk size: 0
+  bundle2-input-part: total payload size 17939
+  bundle2-input: part header size: 0
+  bundle2-input: end of bundle2 stream
+  bundle2-input-bundle: 18 parts total
+  checking for updated bookmarks
+  updating the branch cache
+  new changesets 17185c1c22f1:1dded5aafa0f
+  (run 'hg heads' to see heads, 'hg merge' to merge)
+
+different pull with a different client
+--------------------------------------
+
+  $ hg -R server log -G -T '{rev}:{node}\n' -r '87232049c8d1+0+1789+(::1789 and (merge() or branchpoint()))'
+  o  2085:87232049c8d1f413105bf813b6bfc21da3e26a4f
+  :
+  o  1789:44e80141ad530a2aa085e9bd9b5311b57eff72ff
+  :
+  o    1663:1710092b3ab17a6d2ecad664580991a608537749
+  |\
+  o :  1250:d83212ecaa436c80d6113cf915ba35e2db787e79
+  :/
+  o  898:1388f909cd2b0685efd4e2ce076d198bce20922c
+  :
+  o  0:1ea73414a91b0920940797d8fc6a11e447f8ea1e
+  
+
+  $ hg -R client3 pull server -r 1789 --debug --config devel.bundle2.debug=yes | grep -v 'add changeset'
+  pulling from server
+  query 1; heads
+  1024 changesets found
+  227 changesets found
+  29 changesets found
+  128 changesets found
+  64 changesets found
+  32 changesets found
+  16 changesets found
+  2 changesets found
+  1 changesets found
+  listing keys for "bookmarks"
+  bundle2-output-bundle: "HG20", 12 parts total
+  bundle2-output: start emission of HG20 stream
+  bundle2-output: bundle parameter: 
+  bundle2-output: start of parts
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 0: "CHANGEGROUP"
+  bundle2-output: header chunk size: 44
+  bundle2-output: payload chunk size: 32768
+  bundle2-output: payload chunk size: 32768
+  bundle2-output: payload chunk size: 32768
+  bundle2-output: payload chunk size: 32768
+  bundle2-output: payload chunk size: 32768
+  bundle2-output: payload chunk size: 22368
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 1: "CHANGEGROUP"
+  bundle2-output: header chunk size: 43
+  bundle2-output: payload chunk size: 32768
+  bundle2-output: payload chunk size: 9012
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 2: "CHANGEGROUP"
+  bundle2-output: header chunk size: 42
+  bundle2-output: payload chunk size: 5348
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 3: "CHANGEGROUP"
+  bundle2-output: header chunk size: 43
+  bundle2-output: payload chunk size: 23564
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 4: "CHANGEGROUP"
+  bundle2-output: header chunk size: 42
+  bundle2-output: payload chunk size: 11788
+  bundle2-input: start processing of HG20 stream
+  bundle2-input: reading bundle2 stream parameters
+  bundle2-input-bundle: with-transaction
+  bundle2-input: start extraction of bundle2 parts
+  bundle2-input: part header size: 44
+  bundle2-input: part type: "CHANGEGROUP"
   bundle2-input: part id: "0"
   bundle2-input: part parameters: 2
   bundle2-input: found a handler for part changegroup
@@ -168,22 +1317,568 @@
   bundle2-input: payload chunk size: 32768
   bundle2-input: payload chunk size: 32768
   bundle2-input: payload chunk size: 32768
-  bundle2-input: payload chunk size: 1036
+  bundle2-input: payload chunk size: 22368
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 1024 changesets with 0 changes to 0 files
+  bundle2-input-part: total payload size 186208
+  bundle2-input: part header size: 43
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "1"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 32768
+  bundle2-input: payload chunk size: 9012
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 227 changesets with 0 changes to 0 files
+  bundle2-input-part: total payload size 41780
+  bundle2-input: part header size: 42
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "2"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 5348
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 29 changesets with 0 changes to 0 files (+1 heads)
+  bundle2-input-part: total payload size 5348
+  bundle2-input: part header size: 43
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "3"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 23564
   bundle2-input: payload chunk size: 0
   adding manifests
   adding file changes
-  added 896 changesets with 0 changes to 0 files (+1 heads)
-  bundle2-input-part: total payload size 164876
+  added 128 changesets with 0 changes to 0 files (-1 heads)
+  bundle2-input-part: total payload size 23564
+  bundle2-input: part header size: 42
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "4"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 11788
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 5: "CHANGEGROUP"
+  bundle2-output: header chunk size: 42
+  bundle2-output: payload chunk size: 5900
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 6: "CHANGEGROUP"
+  bundle2-output: header chunk size: 42
+  bundle2-output: payload chunk size: 2956
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 7: "CHANGEGROUP"
+  bundle2-output: header chunk size: 41
+  bundle2-output: payload chunk size: 380
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 8: "CHANGEGROUP"
+  bundle2-output: header chunk size: 41
+  bundle2-output: payload chunk size: 196
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "listkeys"
+  bundle2-output-part: "listkeys" (params: 1 mandatory) empty payload
+  bundle2-output: part 9: "LISTKEYS"
+  bundle2-output: header chunk size: 35
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "phase-heads"
+  bundle2-output-part: "phase-heads" 24 bytes payload
+  bundle2-output: part 10: "PHASE-HEADS"
+  bundle2-output: header chunk size: 18
+  bundle2-output: payload chunk size: 24
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "cache:rev-branch-cache"
+  bundle2-output-part: "cache:rev-branch-cache" (advisory) streamed payload
+  bundle2-output: part 11: "cache:rev-branch-cache"
+  bundle2-output: header chunk size: 29
+  bundle2-output: payload chunk size: 30479
+  bundle2-output: closing payload chunk
+  bundle2-output: end of bundle
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 64 changesets with 0 changes to 0 files
+  bundle2-input-part: total payload size 11788
+  bundle2-input: part header size: 42
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "5"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 5900
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 32 changesets with 0 changes to 0 files
+  bundle2-input-part: total payload size 5900
+  bundle2-input: part header size: 42
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "6"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 2956
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 16 changesets with 0 changes to 0 files
+  bundle2-input-part: total payload size 2956
+  bundle2-input: part header size: 41
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "7"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 380
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 2 changesets with 0 changes to 0 files
+  bundle2-input-part: total payload size 380
+  bundle2-input: part header size: 41
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "8"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 196
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 1 changesets with 0 changes to 0 files
+  bundle2-input-part: total payload size 196
   bundle2-input: part header size: 35
   bundle2-input: part type: "LISTKEYS"
-  bundle2-input: part id: "1"
+  bundle2-input: part id: "9"
   bundle2-input: part parameters: 1
   bundle2-input: found a handler for part listkeys
   bundle2-input-part: "listkeys" (params: 1 mandatory) supported
   bundle2-input: payload chunk size: 0
   bundle2-input: part header size: 18
   bundle2-input: part type: "PHASE-HEADS"
+  bundle2-input: part id: "10"
+  bundle2-input: part parameters: 0
+  bundle2-input: found a handler for part phase-heads
+  bundle2-input-part: "phase-heads" supported
+  bundle2-input: payload chunk size: 24
+  bundle2-input: payload chunk size: 0
+  bundle2-input-part: total payload size 24
+  bundle2-input: part header size: 29
+  bundle2-input: part type: "cache:rev-branch-cache"
+  bundle2-input: part id: "11"
+  bundle2-input: part parameters: 0
+  bundle2-input: found a handler for part cache:rev-branch-cache
+  bundle2-input-part: "cache:rev-branch-cache" (advisory) supported
+  bundle2-input: payload chunk size: 30479
+  bundle2-input: payload chunk size: 0
+  bundle2-input-part: total payload size 30479
+  bundle2-input: part header size: 0
+  bundle2-input: end of bundle2 stream
+  bundle2-input-bundle: 11 parts total
+  checking for updated bookmarks
+  updating the branch cache
+  new changesets 1ea73414a91b:44e80141ad53
+  (run 'hg update' to get a working copy)
+
+  $ hg -R server log -G -T '{rev}:{node}\n' -r '1789+head()+parents(roots(only(head(), 1789)))+(only(head(), 1789) and (merge() or branchpoint()))'
+  o  2130:0f376356904fc8c1c6ceaac27990f2fd79b1f8c1
+  :
+  o  1789:44e80141ad530a2aa085e9bd9b5311b57eff72ff
+  :
+  : o  1517:1dded5aafa0f8d548f6357cc2f8882dcc4489fbf
+  :/
+  o  1250:d83212ecaa436c80d6113cf915ba35e2db787e79
+  |
+  ~
+
+  $ hg -R client3 pull server --debug --config devel.bundle2.debug=yes | grep -v 'add changeset'
+  pulling from server
+  query 1; heads
+  searching for changes
+  all local heads known remotely
+  1 changesets found
+  4 changesets found
+  8 changesets found
+  256 changesets found
+  64 changesets found
+  8 changesets found
+  1 changesets found
+  4 changesets found
+  8 changesets found
+  16 changesets found
+  128 changesets found
+  64 changesets found
+  32 changesets found
+  8 changesets found
+  4 changesets found
+  2 changesets found
+  listing keys for "bookmarks"
+  bundle2-output-bundle: "HG20", 19 parts total
+  bundle2-output: start emission of HG20 stream
+  bundle2-output: bundle parameter: 
+  bundle2-output: start of parts
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 0: "CHANGEGROUP"
+  bundle2-output: header chunk size: 41
+  bundle2-output: payload chunk size: 196
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 1: "CHANGEGROUP"
+  bundle2-output: header chunk size: 41
+  bundle2-output: payload chunk size: 748
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 2: "CHANGEGROUP"
+  bundle2-output: header chunk size: 41
+  bundle2-output: payload chunk size: 1484
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 3: "CHANGEGROUP"
+  bundle2-output: header chunk size: 43
+  bundle2-output: payload chunk size: 32768
+  bundle2-output: payload chunk size: 14348
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 4: "CHANGEGROUP"
+  bundle2-output: header chunk size: 42
+  bundle2-output: payload chunk size: 11788
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 5: "CHANGEGROUP"
+  bundle2-output: header chunk size: 41
+  bundle2-output: payload chunk size: 1484
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 6: "CHANGEGROUP"
+  bundle2-output: header chunk size: 41
+  bundle2-output: payload chunk size: 196
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 7: "CHANGEGROUP"
+  bundle2-output: header chunk size: 41
+  bundle2-output: payload chunk size: 748
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 8: "CHANGEGROUP"
+  bundle2-output: header chunk size: 41
+  bundle2-output: payload chunk size: 1484
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 9: "CHANGEGROUP"
+  bundle2-output: header chunk size: 42
+  bundle2-output: payload chunk size: 2956
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 10: "CHANGEGROUP"
+  bundle2-output: header chunk size: 43
+  bundle2-output: payload chunk size: 23564
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 11: "CHANGEGROUP"
+  bundle2-output: header chunk size: 42
+  bundle2-output: payload chunk size: 11788
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 12: "CHANGEGROUP"
+  bundle2-output: header chunk size: 42
+  bundle2-output: payload chunk size: 5900
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 13: "CHANGEGROUP"
+  bundle2-output: header chunk size: 41
+  bundle2-output: payload chunk size: 1484
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 14: "CHANGEGROUP"
+  bundle2-output: header chunk size: 41
+  bundle2-output: payload chunk size: 748
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "changegroup"
+  bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
+  bundle2-output: part 15: "CHANGEGROUP"
+  bundle2-output: header chunk size: 41
+  bundle2-output: payload chunk size: 380
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "listkeys"
+  bundle2-output-part: "listkeys" (params: 1 mandatory) empty payload
+  bundle2-output: part 16: "LISTKEYS"
+  bundle2-output: header chunk size: 35
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "phase-heads"
+  bundle2-output-part: "phase-heads" 48 bytes payload
+  bundle2-output: part 17: "PHASE-HEADS"
+  bundle2-output: header chunk size: 18
+  bundle2-output: payload chunk size: 48
+  bundle2-output: closing payload chunk
+  bundle2-output: bundle part: "cache:rev-branch-cache"
+  bundle2-output-part: "cache:rev-branch-cache" (advisory) streamed payload
+  bundle2-output: part 18: "cache:rev-branch-cache"
+  bundle2-output: header chunk size: 29
+  bundle2-output: payload chunk size: 12179
+  bundle2-output: closing payload chunk
+  bundle2-output: end of bundle
+  bundle2-input: start processing of HG20 stream
+  bundle2-input: reading bundle2 stream parameters
+  bundle2-input-bundle: with-transaction
+  bundle2-input: start extraction of bundle2 parts
+  bundle2-input: part header size: 41
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "0"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 196
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 1 changesets with 0 changes to 0 files
+  bundle2-input-part: total payload size 196
+  bundle2-input: part header size: 41
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "1"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 748
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 4 changesets with 0 changes to 0 files
+  bundle2-input-part: total payload size 748
+  bundle2-input: part header size: 41
+  bundle2-input: part type: "CHANGEGROUP"
   bundle2-input: part id: "2"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 1484
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 8 changesets with 0 changes to 0 files
+  bundle2-input-part: total payload size 1484
+  bundle2-input: part header size: 43
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "3"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 32768
+  bundle2-input: payload chunk size: 14348
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 256 changesets with 0 changes to 0 files
+  bundle2-input-part: total payload size 47116
+  bundle2-input: part header size: 42
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "4"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 11788
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 64 changesets with 0 changes to 0 files
+  bundle2-input-part: total payload size 11788
+  bundle2-input: part header size: 41
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "5"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 1484
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 8 changesets with 0 changes to 0 files
+  bundle2-input-part: total payload size 1484
+  bundle2-input: part header size: 41
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "6"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 196
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 1 changesets with 0 changes to 0 files (+1 heads)
+  bundle2-input-part: total payload size 196
+  bundle2-input: part header size: 41
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "7"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 748
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 4 changesets with 0 changes to 0 files
+  bundle2-input-part: total payload size 748
+  bundle2-input: part header size: 41
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "8"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 1484
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 8 changesets with 0 changes to 0 files
+  bundle2-input-part: total payload size 1484
+  bundle2-input: part header size: 42
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "9"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 2956
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 16 changesets with 0 changes to 0 files
+  bundle2-input-part: total payload size 2956
+  bundle2-input: part header size: 43
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "10"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 23564
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 128 changesets with 0 changes to 0 files
+  bundle2-input-part: total payload size 23564
+  bundle2-input: part header size: 42
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "11"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 11788
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 64 changesets with 0 changes to 0 files
+  bundle2-input-part: total payload size 11788
+  bundle2-input: part header size: 42
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "12"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 5900
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 32 changesets with 0 changes to 0 files
+  bundle2-input-part: total payload size 5900
+  bundle2-input: part header size: 41
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "13"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 1484
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 8 changesets with 0 changes to 0 files
+  bundle2-input-part: total payload size 1484
+  bundle2-input: part header size: 41
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "14"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 748
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 4 changesets with 0 changes to 0 files
+  bundle2-input-part: total payload size 748
+  bundle2-input: part header size: 41
+  bundle2-input: part type: "CHANGEGROUP"
+  bundle2-input: part id: "15"
+  bundle2-input: part parameters: 2
+  bundle2-input: found a handler for part changegroup
+  bundle2-input-part: "changegroup" (params: 1 mandatory 1 advisory) supported
+  adding changesets
+  bundle2-input: payload chunk size: 380
+  bundle2-input: payload chunk size: 0
+  adding manifests
+  adding file changes
+  added 2 changesets with 0 changes to 0 files
+  bundle2-input-part: total payload size 380
+  bundle2-input: part header size: 35
+  bundle2-input: part type: "LISTKEYS"
+  bundle2-input: part id: "16"
+  bundle2-input: part parameters: 1
+  bundle2-input: found a handler for part listkeys
+  bundle2-input-part: "listkeys" (params: 1 mandatory) supported
+  bundle2-input: payload chunk size: 0
+  bundle2-input: part header size: 18
+  bundle2-input: part type: "PHASE-HEADS"
+  bundle2-input: part id: "17"
   bundle2-input: part parameters: 0
   bundle2-input: found a handler for part phase-heads
   bundle2-input-part: "phase-heads" supported
@@ -192,17 +1887,17 @@
   bundle2-input-part: total payload size 48
   bundle2-input: part header size: 29
   bundle2-input: part type: "cache:rev-branch-cache"
-  bundle2-input: part id: "3"
+  bundle2-input: part id: "18"
   bundle2-input: part parameters: 0
   bundle2-input: found a handler for part cache:rev-branch-cache
   bundle2-input-part: "cache:rev-branch-cache" (advisory) supported
-  bundle2-input: payload chunk size: 17939
+  bundle2-input: payload chunk size: 12179
   bundle2-input: payload chunk size: 0
-  bundle2-input-part: total payload size 17939
+  bundle2-input-part: total payload size 12179
   bundle2-input: part header size: 0
   bundle2-input: end of bundle2 stream
-  bundle2-input-bundle: 3 parts total
+  bundle2-input-bundle: 18 parts total
   checking for updated bookmarks
   updating the branch cache
-  new changesets 17185c1c22f1:0f376356904f
+  new changesets c232505f58fd:1dded5aafa0f
   (run 'hg heads' to see heads, 'hg merge' to merge)