Patchwork [5,of,8] changegroup: move chunk extraction into a getchunks method of unbundle10

login
register
mail settings
Submitter Pierre-Yves David
Date April 11, 2014, 10:06 p.m.
Message ID <6eef726e8e85dd6011fc.1397253962@marginatus.alto.octopoid.net>
Download mbox | patch
Permalink /patch/4288/
State Accepted
Headers show

Comments

Pierre-Yves David - April 11, 2014, 10:06 p.m.
# HG changeset patch
# User Pierre-Yves David <pierre-yves.david@fb.com>
# Date 1397161140 25200
#      Thu Apr 10 13:19:00 2014 -0700
# Node ID 6eef726e8e85dd6011fc61951c6dc7e4984df721
# Parent  f38dec61a78b9f38490bcb1667af0a66c834b59f
changegroup: move chunk extraction into a getchunks method of unbundle10

This code used to be in `writebundle` only. We needs to make it more broadly
available for bundle2. The "changegroup" bundle2 part has to retrieve the
binary content of changegroup stream. We moved the chunks retrieving code into
the `unbundle10` object directly and the `writebundle` code is now using that.

This split is useful for bundle2 purpose, we want to be able to easily

To keep thing simples, we kept compression out of the new methods. If it make
more sense in the future, compression may get included in this function too.

Patch

diff --git a/mercurial/changegroup.py b/mercurial/changegroup.py
--- a/mercurial/changegroup.py
+++ b/mercurial/changegroup.py
@@ -89,27 +89,12 @@  def writebundle(cg, filename, bundletype
         # in case of sshrepo because we don't know the end of the stream
 
         # an empty chunkgroup is the end of the changegroup
         # a changegroup has at least 2 chunkgroups (changelog and manifest).
         # after that, an empty chunkgroup is the end of the changegroup
-        empty = False
-        count = 0
-        while not empty or count <= 2:
-            empty = True
-            count += 1
-            while True:
-                chunk = getchunk(cg)
-                if not chunk:
-                    break
-                empty = False
-                fh.write(z.compress(chunkheader(len(chunk))))
-                pos = 0
-                while pos < len(chunk):
-                    next = pos + 2**20
-                    fh.write(z.compress(chunk[pos:next]))
-                    pos = next
-            fh.write(z.compress(closechunk()))
+        for chunk in cg.getchunks():
+            fh.write(z.compress(chunk))
         fh.write(z.flush())
         cleanup = None
         return filename
     finally:
         if fh is not None:
@@ -200,10 +185,38 @@  class unbundle10(object):
         delta = readexactly(self._stream, l - self.deltaheadersize)
         node, p1, p2, deltabase, cs = self._deltaheader(header, prevnode)
         return {'node': node, 'p1': p1, 'p2': p2, 'cs': cs,
                 'deltabase': deltabase, 'delta': delta}
 
+    def getchunks(self):
+        """returns all the chunks contains in the bundle
+
+        Used when you need to forward the binary stream to a file or another
+        network API. To do so, it parse the changegroup data, otherwise it will
+        block in case of sshrepo because it don't know the end of the stream.
+        """
+        # an empty chunkgroup is the end of the changegroup
+        # a changegroup has at least 2 chunkgroups (changelog and manifest).
+        # after that, an empty chunkgroup is the end of the changegroup
+        empty = False
+        count = 0
+        while not empty or count <= 2:
+            empty = True
+            count += 1
+            while True:
+                chunk = getchunk(self)
+                if not chunk:
+                    break
+                empty = False
+                yield chunkheader(len(chunk))
+                pos = 0
+                while pos < len(chunk):
+                    next = pos + 2**20
+                    yield chunk[pos:next]
+                    pos = next
+            yield closechunk()
+
 class headerlessfixup(object):
     def __init__(self, fh, h):
         self._h = h
         self._fh = fh
     def read(self, n):