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.
--- a/mercurial/changegroup.py Thu Jan 15 14:39:41 2015 -0800
+++ b/mercurial/changegroup.py Thu Jan 15 15:39:16 2015 -0800
@@ -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()),
@@ -101,9 +102,20 @@
fh = os.fdopen(fd, "wb")
cleanup = filename
- header, compressor = bundletypes[bundletype]
- fh.write(header)
- z = compressor()
+ if bundletype == "HG2Y":
+ import bundle2
+ 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
@@ -111,7 +123,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
@@ -146,6 +158,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
@@ -238,6 +251,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
@@ -257,6 +271,7 @@
class cg1packer(object):
deltaheader = _CHANGEGROUPV1_DELTA_HEADER
+ version = '01'
def __init__(self, repo, bundlecaps=None):
"""Given a source repo, construct a bundler.
@@ -484,7 +499,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):
--- a/mercurial/commands.py Thu Jan 15 14:39:41 2015 -0800
+++ b/mercurial/commands.py Thu Jan 15 15:39:16 2015 -0800
@@ -1181,7 +1181,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'))
@@ -2161,7 +2164,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'))
--- a/tests/test-getbundle.t Thu Jan 15 14:39:41 2015 -0800
+++ b/tests/test-getbundle.t Thu Jan 15 15:39:16 2015 -0800
@@ -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: