##// END OF EJS Templates
bundle2: support bundling of empty part (with a type)...
Pierre-Yves David -
r20856:8a6a86c9 default
parent child Browse files
Show More
@@ -21,9 +21,7 b' The format is architectured as follow'
21 - payload parts (any number)
21 - payload parts (any number)
22 - end of stream marker.
22 - end of stream marker.
23
23
24 The current implementation accept some stream level option but no part.
24 the Binary format
25
26 Details on the Binary format
27 ============================
25 ============================
28
26
29 All numbers are unsigned and big endian.
27 All numbers are unsigned and big endian.
@@ -71,7 +69,28 b' Binary format is as follow'
71 The total number of Bytes used by the part headers. When the header is empty
69 The total number of Bytes used by the part headers. When the header is empty
72 (size = 0) this is interpreted as the end of stream marker.
70 (size = 0) this is interpreted as the end of stream marker.
73
71
74 Currently forced to 0 in the current state of the implementation
72 :header:
73
74 The header defines how to interpret the part. It contains two piece of
75 data: the part type, and the part parameters.
76
77 The part type is used to route an application level handler, that can
78 interpret payload.
79
80 Part parameters are passed to the application level handler. They are
81 meant to convey information that will help the application level object to
82 interpret the part payload.
83
84 The binary format of the header is has follow
85
86 :typesize: (one byte)
87 :typename: alphanumerical part name
88 :option: we do not support option yet this denoted by two 16 bites zero.
89
90 :payload:
91
92 The current payload is a 32bit integer with a value of 0. This is
93 considered an "empty" payload.
75 """
94 """
76
95
77 import util
96 import util
@@ -88,15 +107,15 b' from i18n import _'
88 _magicstring = 'HG20'
107 _magicstring = 'HG20'
89
108
90 _fstreamparamsize = '>H'
109 _fstreamparamsize = '>H'
110 _fpartheadersize = '>H'
111 _fparttypesize = '>B'
91
112
92 class bundle20(object):
113 class bundle20(object):
93 """represent an outgoing bundle2 container
114 """represent an outgoing bundle2 container
94
115
95 Use the `addparam` method to add stream level parameter. Then call
116 Use the `addparam` method to add stream level parameter. and `addpart` to
96 `getchunks` to retrieve all the binary chunks of datathat compose the
117 populate it. Then call `getchunks` to retrieve all the binary chunks of
97 bundle2 container.
118 datathat compose the bundle2 container."""
98
99 This object does not support payload part yet."""
100
119
101 def __init__(self, ui):
120 def __init__(self, ui):
102 self.ui = ui
121 self.ui = ui
@@ -111,6 +130,12 b' class bundle20(object):'
111 raise ValueError('non letter first character: %r' % name)
130 raise ValueError('non letter first character: %r' % name)
112 self._params.append((name, value))
131 self._params.append((name, value))
113
132
133 def addpart(self, part):
134 """add a new part to the bundle2 container
135
136 Parts contains the actuall applicative payload."""
137 self._parts.append(part)
138
114 def getchunks(self):
139 def getchunks(self):
115 self.ui.debug('start emission of %s stream\n' % _magicstring)
140 self.ui.debug('start emission of %s stream\n' % _magicstring)
116 yield _magicstring
141 yield _magicstring
@@ -120,9 +145,11 b' class bundle20(object):'
120 if param:
145 if param:
121 yield param
146 yield param
122
147
123 # no support for parts
148 self.ui.debug('start of parts\n')
124 # to be obviously fixed soon.
149 for part in self._parts:
125 assert not self._parts
150 self.ui.debug('bundle part: "%s"\n' % part.type)
151 for chunk in part.getchunks():
152 yield chunk
126 self.ui.debug('end of bundle\n')
153 self.ui.debug('end of bundle\n')
127 yield '\0\0'
154 yield '\0\0'
128
155
@@ -217,5 +244,26 b' class unbundle20(object):'
217 assert headersize == '\0\0'
244 assert headersize == '\0\0'
218 return None
245 return None
219
246
247 class part(object):
248 """A bundle2 part contains application level payload
249
250 The part `type` is used to route the part to the application level
251 handler.
252 """
253
254 def __init__(self, parttype):
255 self.type = parttype
256
257 def getchunks(self):
258 ### header
259 header = [_pack(_fparttypesize, len(self.type)),
260 self.type,
261 '\0\0', # No option support for now.
262 ]
263 headerchunk = ''.join(header)
264 yield _pack(_fpartheadersize, len(headerchunk))
265 yield headerchunk
266 # force empty part for now
267 yield '\0\0\0\0'
220
268
221
269
@@ -16,7 +16,8 b' Create an extension to test bundle2 API'
16 > command = cmdutil.command(cmdtable)
16 > command = cmdutil.command(cmdtable)
17 >
17 >
18 > @command('bundle2',
18 > @command('bundle2',
19 > [('', 'param', [], 'stream level parameter'),],
19 > [('', 'param', [], 'stream level parameter'),
20 > ('', 'parts', False, 'include some arbitrary parts to the bundle'),],
20 > '[OUTPUTFILE]')
21 > '[OUTPUTFILE]')
21 > def cmdbundle2(ui, repo, path=None, **opts):
22 > def cmdbundle2(ui, repo, path=None, **opts):
22 > """write a bundle2 container on standard ouput"""
23 > """write a bundle2 container on standard ouput"""
@@ -28,6 +29,13 b' Create an extension to test bundle2 API'
28 > except ValueError, exc:
29 > except ValueError, exc:
29 > raise util.Abort('%s' % exc)
30 > raise util.Abort('%s' % exc)
30 >
31 >
32 > if opts['parts']:
33 > part = bundle2.part('test:empty')
34 > bundler.addpart(part)
35 > # add a second one to make sure we handle multiple parts
36 > part = bundle2.part('test:empty')
37 > bundler.addpart(part)
38 >
31 > if path is None:
39 > if path is None:
32 > file = sys.stdout
40 > file = sys.stdout
33 > else:
41 > else:
@@ -178,6 +186,7 b' bundling debug'
178 $ hg bundle2 --debug --param 'e|! 7/=babar%#==tutu' --param simple ../out.hg2
186 $ hg bundle2 --debug --param 'e|! 7/=babar%#==tutu' --param simple ../out.hg2
179 start emission of HG20 stream
187 start emission of HG20 stream
180 bundle parameter: e%7C%21%207/=babar%25%23%3D%3Dtutu simple
188 bundle parameter: e%7C%21%207/=babar%25%23%3D%3Dtutu simple
189 start of parts
181 end of bundle
190 end of bundle
182
191
183 file content is ok
192 file content is ok
@@ -215,3 +224,22 b' bad parameter name'
215 $ hg bundle2 --param 42babar
224 $ hg bundle2 --param 42babar
216 abort: non letter first character: '42babar'
225 abort: non letter first character: '42babar'
217 [255]
226 [255]
227
228
229 Test part
230 =================
231
232 $ hg bundle2 --parts ../parts.hg2 --debug
233 start emission of HG20 stream
234 bundle parameter:
235 start of parts
236 bundle part: "test:empty"
237 bundle part: "test:empty"
238 end of bundle
239
240 $ cat ../parts.hg2
241 HG20\x00\x00\x00\r (esc)
242 test:empty\x00\x00\x00\x00\x00\x00\x00\r (esc)
243 test:empty\x00\x00\x00\x00\x00\x00\x00\x00 (no-eol) (esc)
244
245
General Comments 0
You need to be logged in to leave comments. Login now