Patchwork [4,of,8,V2] changegroup: introduce "raw" versions of some commands

login
register
mail settings
Submitter Pierre-Yves David
Date Oct. 17, 2014, 7:56 p.m.
Message ID <f836daa75636bd6c43f3.1413575788@marginatus.alto.octopoid.net>
Download mbox | patch
Permalink /patch/6389/
State Superseded
Commit 706547a14b8ba80f22eeff9f7615f44baa686aaf
Headers show

Comments

Pierre-Yves David - Oct. 17, 2014, 7:56 p.m.
# HG changeset patch
# User Sune Foldager <cryo@cyanite.org>
# Date 1413549662 -7200
#      Fri Oct 17 14:41:02 2014 +0200
# Node ID f836daa75636bd6c43f3ca4a86de6c40f27822ba
# Parent  c36a8b35f3c846458dcdec956ed4674be1b01923
changegroup: introduce "raw" versions of some commands

The commands getchangegroup, getlocalchangegroup and getsubset now each
have a version ending in -raw. The raw versions return the chunk generator
from the changegroup packer directly, without wrapping it in a chunkbuffer
and unpacker. This avoids extra chunkbuffers in the bundle2 code path.

Also, the raw versions can be extended to support alternative packers
in the future, to be used from bundle2.

Patch

diff --git a/mercurial/changegroup.py b/mercurial/changegroup.py
--- a/mercurial/changegroup.py
+++ b/mercurial/changegroup.py
@@ -441,11 +441,11 @@  def _changegroupinfo(repo, nodes, source
     if repo.ui.debugflag:
         repo.ui.debug("list of changesets:\n")
         for node in nodes:
             repo.ui.debug("%s\n" % hex(node))
 
-def getsubset(repo, outgoing, bundler, source, fastpath=False):
+def getsubsetraw(repo, outgoing, bundler, source, fastpath=False):
     repo = repo.unfiltered()
     commonrevs = outgoing.common
     csets = outgoing.missing
     heads = outgoing.missingheads
     # We go through the fast path if we get told to, or if all (unfiltered
@@ -455,11 +455,14 @@  def getsubset(repo, outgoing, bundler, s
     fastpathlinkrev = fastpath or (
             repo.filtername is None and heads == sorted(repo.heads()))
 
     repo.hook('preoutgoing', throw=True, source=source)
     _changegroupinfo(repo, csets, source)
-    gengroup = bundler.generate(commonrevs, csets, fastpathlinkrev, source)
+    return bundler.generate(commonrevs, csets, fastpathlinkrev, source)
+
+def getsubset(repo, outgoing, bundler, source, fastpath=False):
+    gengroup = getsubsetraw(repo, outgoing, bundler, source, fastpath)
     return cg1unpacker(util.chunkbuffer(gengroup), 'UN')
 
 def changegroupsubset(repo, roots, heads, source):
     """Compute a changegroup consisting of all the nodes that are
     descendants of any of the roots and ancestors of any of the heads.
@@ -483,10 +486,20 @@  def changegroupsubset(repo, roots, heads
         discbases.extend([p for p in cl.parents(n) if p != nullid])
     outgoing = discovery.outgoing(cl, discbases, heads)
     bundler = cg1packer(repo)
     return getsubset(repo, outgoing, bundler, source)
 
+def getlocalchangegroupraw(repo, source, outgoing, bundlecaps=None):
+    """Like getbundle, but taking a discovery.outgoing as an argument.
+
+    This is only implemented for local repos and reuses potentially
+    precomputed sets in outgoing. Returns a raw changegroup generator."""
+    if not outgoing.missing:
+        return None
+    bundler = cg1packer(repo, bundlecaps)
+    return getsubsetraw(repo, outgoing, bundler, source)
+
 def getlocalchangegroup(repo, source, outgoing, bundlecaps=None):
     """Like getbundle, but taking a discovery.outgoing as an argument.
 
     This is only implemented for local repos and reuses potentially
     precomputed sets in outgoing."""
@@ -512,10 +525,22 @@  def _computeoutgoing(repo, heads, common
         common = [nullid]
     if not heads:
         heads = cl.heads()
     return discovery.outgoing(cl, common, heads)
 
+def getchangegroupraw(repo, source, heads=None, common=None, bundlecaps=None):
+    """Like changegroupsubset, but returns the set difference between the
+    ancestors of heads and the ancestors common.
+
+    If heads is None, use the local heads. If common is None, use [nullid].
+
+    The nodes in common might not all be known locally due to the way the
+    current discovery protocol works. Returns a raw changegroup generator.
+    """
+    outgoing = _computeoutgoing(repo, heads, common)
+    return getlocalchangegroupraw(repo, source, outgoing, bundlecaps=bundlecaps)
+
 def getchangegroup(repo, source, heads=None, common=None, bundlecaps=None):
     """Like changegroupsubset, but returns the set difference between the
     ancestors of heads and the ancestors common.
 
     If heads is None, use the local heads. If common is None, use [nullid].
diff --git a/mercurial/exchange.py b/mercurial/exchange.py
--- a/mercurial/exchange.py
+++ b/mercurial/exchange.py
@@ -439,12 +439,13 @@  def _pushb2ctx(pushop, bundler):
     pushop.repo.prepushoutgoinghooks(pushop.repo,
                                      pushop.remote,
                                      pushop.outgoing)
     if not pushop.force:
         bundler.newpart('B2X:CHECK:HEADS', data=iter(pushop.remoteheads))
-    cg = changegroup.getlocalchangegroup(pushop.repo, 'push', pushop.outgoing)
-    cgpart = bundler.newpart('B2X:CHANGEGROUP', data=cg.getchunks())
+    cg = changegroup.getlocalchangegroupraw(pushop.repo, 'push',
+                                            pushop.outgoing)
+    cgpart = bundler.newpart('B2X:CHANGEGROUP', data=cg)
     def handlereply(op):
         """extract addchangroup returns from server reply"""
         cgreplies = op.records.getreplies(cgpart.id)
         assert len(cgreplies['changegroup']) == 1
         pushop.cgresult = cgreplies['changegroup'][0]['return']
@@ -1176,15 +1177,15 @@  def _getbundlechangegrouppart(bundler, r
                               b2caps=None, heads=None, common=None, **kwargs):
     """add a changegroup part to the requested bundle"""
     cg = None
     if kwargs.get('cg', True):
         # build changegroup bundle here.
-        cg = changegroup.getchangegroup(repo, source, heads=heads,
-                                        common=common, bundlecaps=bundlecaps)
+        cg = changegroup.getchangegroupraw(repo, source, heads=heads,
+                                           common=common, bundlecaps=bundlecaps)
 
     if cg:
-        bundler.newpart('b2x:changegroup', data=cg.getchunks())
+        bundler.newpart('b2x:changegroup', data=cg)
 
 @getbundle2partsgenerator('listkeys')
 def _getbundlelistkeysparts(bundler, repo, source, bundlecaps=None,
                             b2caps=None, **kwargs):
     """add parts containing listkeys namespaces to the requested bundle"""