bundle2: support bundling simple parameter
This changeset add bundling capacity for simple parameters, not value or any
special case are handled.
--- a/mercurial/bundle2.py Tue Mar 18 16:35:34 2014 -0700
+++ b/mercurial/bundle2.py Wed Mar 19 14:52:03 2014 -0700
@@ -21,7 +21,7 @@
- payload parts (any number)
- end of stream marker.
-The current implementation is limited to empty bundle.
+The current implementation accept some stream level option but no part.
Details on the Binary format
============================
@@ -37,14 +37,18 @@
The total number of Bytes used by the parameters
- Currently force to 0.
-
:params value: arbitrary number of Bytes
A blob of `params size` containing the serialized version of all stream level
parameters.
- Currently always empty.
+ The blob contains a space separated list of parameters.
+
+ Parameter value are not supported yet.
+
+ Special character in param name are not supported yet.
+
+
Payload part
@@ -61,32 +65,57 @@
"""
import util
+import struct
+
import changegroup
from i18n import _
+_pack = struct.pack
+_unpack = struct.unpack
+
_magicstring = 'HG20'
+_fstreamparamsize = '>H'
+
class bundle20(object):
"""represent an outgoing bundle2 container
- People will eventually be able to add param and parts to this object and
- generated a stream from it."""
+ Use the `addparam` method to add stream level parameter. Then call
+ `getchunks` to retrieve all the binary chunks of datathat compose the
+ bundle2 container.
+
+ This object does not support payload part yet."""
def __init__(self):
self._params = []
self._parts = []
+ def addparam(self, name, value=None):
+ """add a stream level parameter"""
+ self._params.append((name, value))
+
def getchunks(self):
yield _magicstring
- # no support for any param yet
- # to be obviously fixed soon.
- assert not self._params
- yield '\0\0'
+ param = self._paramchunk()
+ yield _pack(_fstreamparamsize, len(param))
+ if param:
+ yield param
+
# no support for parts
# to be obviously fixed soon.
assert not self._parts
yield '\0\0'
+ def _paramchunk(self):
+ """return a encoded version of all stream parameters"""
+ blocks = []
+ for key, value in self._params:
+ # XXX no support for value yet
+ assert value is None
+ # XXX no escaping yet
+ blocks.append(key)
+ return ' '.join(blocks)
+
class unbundle20(object):
"""interpret a bundle2 stream
--- a/tests/test-bundle2.t Tue Mar 18 16:35:34 2014 -0700
+++ b/tests/test-bundle2.t Wed Mar 19 14:52:03 2014 -0700
@@ -14,11 +14,15 @@
> cmdtable = {}
> command = cmdutil.command(cmdtable)
>
- > @command('bundle2', [], '')
- > def cmdbundle2(ui, repo):
+ > @command('bundle2',
+ > [('', 'param', [], 'stream level parameter'),],
+ > '')
+ > def cmdbundle2(ui, repo, **opts):
> """write a bundle2 container on standard ouput"""
- > bundle = bundle2.bundle20()
- > for chunk in bundle.getchunks():
+ > bundler = bundle2.bundle20()
+ > for p in opts['param']:
+ > bundler.addparam(p)
+ > for chunk in bundler.getchunks():
> ui.write(chunk)
>
> @command('unbundle2', [], '')
@@ -42,12 +46,19 @@
$ hg add a
$ hg commit -m 'a'
-Test simple generation of empty bundle
+
+Empty bundle
+=================
+
+- no option
+- no parts
+
+Test bundling
$ hg bundle2
HG20\x00\x00\x00\x00 (no-eol) (esc)
-Test parsing of an empty bundle
+Test unbundling
$ hg bundle2 | hg unbundle2
options count: 0
@@ -60,3 +71,24 @@
$ hg unbundle2 < ../bundle.hg
abort: unknown bundle version 10
[255]
+
+Test parameters
+=================
+
+- some options
+- no parts
+
+advisory parameters, no value
+-------------------------------
+
+Simplest possible parameters form
+
+Test generation
+
+ $ hg bundle2 --param 'caution'
+ HG20\x00\x07caution\x00\x00 (no-eol) (esc)
+
+Test generation multiple option
+
+ $ hg bundle2 --param 'caution' --param 'meal'
+ HG20\x00\x0ccaution meal\x00\x00 (no-eol) (esc)