Patchwork [4,of,5] bundle2: support bundling simple parameter

login
register
mail settings
Submitter Pierre-Yves David
Date March 19, 2014, 10:02 p.m.
Message ID <e98462ffb743dec94550.1395266525@marginatus.alto.octopoid.net>
Download mbox | patch
Permalink /patch/3999/
State Superseded
Commit db9d3991d2c60ea40660474e0c1f7cd1716780fe
Headers show

Comments

Pierre-Yves David - March 19, 2014, 10:02 p.m.
# HG changeset patch
# User Pierre-Yves David <pierre-yves.david@fb.com>
# Date 1395265923 25200
#      Wed Mar 19 14:52:03 2014 -0700
# Node ID e98462ffb743dec94550942c5d81e943f161a90e
# Parent  0346bf275367d6c03ddfa65ee780df3a902e0441
bundle2: support bundling simple parameter

This changeset add bundling capacity for simple parameters, not value or any
special case are handled.

Patch

diff --git a/mercurial/bundle2.py b/mercurial/bundle2.py
--- a/mercurial/bundle2.py
+++ b/mercurial/bundle2.py
@@ -19,11 +19,11 @@  The format is architectured as follow
  - magic string
  - stream level parameters
  - 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
 ============================
 
 All numbers are unsigned and big endian.
@@ -35,18 +35,22 @@  Binary format is as follow
 
 :params size: (16 bits integer)
 
   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
 ------------------------
 
@@ -59,36 +63,60 @@  Binary format is as follow
 
   Currently forced to 0 in the current state of the implementation
 """
 
 import util
+import struct
+
 import changegroup
 from i18n import _
 
+_pack = struct.pack
+_unpack = struct.unpack
+
 _magicstring = 'HG20'
 
+_fstreamparamsize = '>H'
+
 class bundler(object):
     """represent an outgoing bundle2 container
 
     People will eventually by able to add param and parts to this object and
     generated a stream from it."""
 
     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 unbundler(object):
     """interpret a bundle2 stream
 
     (this will eventually yield parts)"""
 
diff --git a/tests/test-bundle2.t b/tests/test-bundle2.t
--- a/tests/test-bundle2.t
+++ b/tests/test-bundle2.t
@@ -12,14 +12,18 @@  Create an extension to test bundle2 API
   > from mercurial import cmdutil
   > from mercurial import bundle2
   > 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"""
   >     bundler = bundle2.bundler()
+  >     for p in opts['param']:
+  >         bundler.addparam(p)
   >     for chunk in bundler.getchunks():
   >         ui.write(chunk)
   > 
   > @command('unbundle2', [], '')
   > def cmdunbundle2(ui, repo):
@@ -40,16 +44,23 @@  The extension requires a repo (currently
   $ cd main
   $ touch a
   $ 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
   parts count:   0
 
@@ -58,5 +69,26 @@  Test old style bundle are detected and r
   $ hg bundle --all ../bundle.hg
   1 changesets found
   $ 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)