Patchwork [2,of,2] changegroup.writebundle: HG2Y support

login
register
mail settings
Submitter Eric Sumner
Date Jan. 16, 2015, 11:10 p.m.
Message ID <3bf0ad8003affef2df0e.1421449823@dev911.prn1.facebook.com>
Download mbox | patch
Permalink /patch/7499/
State Superseded
Headers show

Comments

Eric Sumner - Jan. 16, 2015, 11:10 p.m.
# HG changeset patch
# User Eric Sumner <ericsumner@fb.com>
# Date 1421365156 28800
#      Thu Jan 15 15:39:16 2015 -0800
# Node ID 3bf0ad8003affef2df0eff953334fdff52b6ff61
# Parent  4f8446060b6df2a787baa3df70ed2e208fb49437
changegroup.writebundle: HG2Y support

This diff adds support to writebundle to generate a bundle2 wrapper; upcoming
diffs will add an option to write a v2 changegroup part instead of v1 in these
bundles.

Patch

diff --git a/mercurial/changegroup.py b/mercurial/changegroup.py
--- a/mercurial/changegroup.py
+++ b/mercurial/changegroup.py
@@ -10,7 +10,7 @@ 
 from node import nullrev, nullid, hex, short
 import mdiff, util, dagutil
 import struct, os, bz2, zlib, tempfile
-import discovery, error, phases, branchmap
+import discovery, error, phases, branchmap, bundle2
 
 _CHANGEGROUPV1_DELTA_HEADER = "20s20s20s20s"
 _CHANGEGROUPV2_DELTA_HEADER = "20s20s20s20s20s"
@@ -71,6 +71,7 @@ 
     "": ("", nocompress), # only when using unbundle on ssh and old http servers
                           # since the unification ssh accepts a header but there
                           # is no capability signaling it.
+    "HG2Y": (), # special-cased below
     "HG10UN": ("HG10UN", nocompress),
     "HG10BZ": ("HG10", lambda: bz2.BZ2Compressor()),
     "HG10GZ": ("HG10GZ", lambda: zlib.compressobj()),
@@ -103,9 +104,19 @@ 
             fh = os.fdopen(fd, "wb")
         cleanup = filename
 
-        header, compressor = bundletypes[bundletype]
-        fh.write(header)
-        z = compressor()
+        if bundletype == "HG2Y":
+            bundle = bundle2.bundle20(ui)
+            part = bundle.newpart('b2x:changegroup', data=cg.getchunks())
+            part.addparam('version', cg.version)
+            z = nocompress()
+            chunkiter = bundle.getchunks()
+        else:
+            if cg.version != '01':
+                raise util.Abort(_('Bundle1 only supports v1 changegroups\n'))
+            header, compressor = bundletypes[bundletype]
+            fh.write(header)
+            z = compressor()
+            chunkiter = cg.getchunks()
 
         # parse the changegroup data, otherwise we will block
         # in case of sshrepo because we don't know the end of the stream
@@ -113,7 +124,7 @@ 
         # 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
-        for chunk in cg.getchunks():
+        for chunk in chunkiter:
             fh.write(z.compress(chunk))
         fh.write(z.flush())
         cleanup = None
@@ -148,6 +159,7 @@ 
 class cg1unpacker(object):
     deltaheader = _CHANGEGROUPV1_DELTA_HEADER
     deltaheadersize = struct.calcsize(deltaheader)
+    version = '01'
     def __init__(self, fh, alg):
         self._stream = decompressor(fh, alg)
         self._type = alg
@@ -240,6 +252,7 @@ 
 class cg2unpacker(cg1unpacker):
     deltaheader = _CHANGEGROUPV2_DELTA_HEADER
     deltaheadersize = struct.calcsize(deltaheader)
+    version = '02'
 
     def _deltaheader(self, headertuple, prevnode):
         node, p1, p2, deltabase, cs = headertuple
@@ -259,6 +272,7 @@ 
 
 class cg1packer(object):
     deltaheader = _CHANGEGROUPV1_DELTA_HEADER
+    version = '01'
     def __init__(self, repo, bundlecaps=None):
         """Given a source repo, construct a bundler.
 
@@ -486,7 +500,7 @@ 
         return struct.pack(self.deltaheader, node, p1n, p2n, linknode)
 
 class cg2packer(cg1packer):
-
+    version = '02'
     deltaheader = _CHANGEGROUPV2_DELTA_HEADER
 
     def group(self, nodelist, revlog, lookup, units=None, reorder=None):
diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -1182,7 +1182,10 @@ 
         revs = scmutil.revrange(repo, opts['rev'])
 
     bundletype = opts.get('type', 'bzip2').lower()
-    btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
+    btypes = {'none': 'HG10UN',
+              'bzip2': 'HG10BZ',
+              'gzip': 'HG10GZ',
+              'bundle2': 'HG2Y'}
     bundletype = btypes.get(bundletype)
     if bundletype not in changegroup.bundletypes:
         raise util.Abort(_('unknown bundle type specified with --type'))
@@ -2162,7 +2165,10 @@ 
     bundle = repo.getbundle('debug', **args)
 
     bundletype = opts.get('type', 'bzip2').lower()
-    btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
+    btypes = {'none': 'HG10UN',
+              'bzip2': 'HG10BZ',
+              'gzip': 'HG10GZ',
+              'bundle2': 'HG2Y'}
     bundletype = btypes.get(bundletype)
     if bundletype not in changegroup.bundletypes:
         raise util.Abort(_('unknown bundle type specified with --type'))
diff --git a/tests/test-getbundle.t b/tests/test-getbundle.t
--- a/tests/test-getbundle.t
+++ b/tests/test-getbundle.t
@@ -165,7 +165,30 @@ 
   8365676dbab05860ce0d9110f2af51368b961bbd
   0b2f73f04880d9cb6a5cd8a757f0db0ad01e32c3
 
+= Test bundle2 =
 
+  $ hg debuggetbundle repo bundle -t bundle2
+  $ hg debugbundle bundle
+  Stream params: {}
+  b2x:changegroup -- "{'version': '01'}"
+      7704483d56b2a7b5db54dcee7c62378ac629b348
+      29a4d1f17bd3f0779ca0525bebb1cfb51067c738
+      713346a995c363120712aed1aee7e04afd867638
+      d5f6e1ea452285324836a49d7d3c2a63cfed1d31
+      ff42371d57168345fdf1a3aac66a51f6a45d41d2
+      bac16991d12ff45f9dc43c52da1946dfadb83e80
+      6621d79f61b23ec74cf4b69464343d9e0980ec8b
+      8931463777131cd73923e560b760061f2aa8a4bc
+      f34414c64173e0ecb61b25dc55e116dbbcc89bee
+      928b5f94cdb278bb536eba552de348a4e92ef24d
+      700b7e19db54103633c4bf4a6a6b6d55f4d50c03
+      63476832d8ec6558cf9bbe3cbe0c757e5cf18043
+      13c0170174366b441dc68e8e33757232fa744458
+      5686dbbd9fc46cb806599c878d02fe1cb56b83d3
+      8365676dbab05860ce0d9110f2af51368b961bbd
+      0b2f73f04880d9cb6a5cd8a757f0db0ad01e32c3
+      4801a72e5d88cb515b0c7e40fae34180f3f837f2
+      10c14a2cc935e1d8c31f9e98587dcf27fb08a6da
 = Test via HTTP =
 
 Get everything: