##// END OF EJS Templates
bundle2: part params
Pierre-Yves David -
r20877:9e9e3a4e default
parent child Browse files
Show More
@@ -84,8 +84,31 b' Binary format is as follow'
84 The binary format of the header is has follow
84 The binary format of the header is has follow
85
85
86 :typesize: (one byte)
86 :typesize: (one byte)
87
87 :typename: alphanumerical part name
88 :typename: alphanumerical part name
88 :option: we do not support option yet this denoted by two 16 bites zero.
89
90 :parameters:
91
92 Part's parameter may have arbitraty content, the binary structure is::
93
94 <mandatory-count><advisory-count><param-sizes><param-data>
95
96 :mandatory-count: 1 byte, number of mandatory parameters
97
98 :advisory-count: 1 byte, number of advisory parameters
99
100 :param-sizes:
101
102 N couple of bytes, where N is the total number of parameters. Each
103 couple contains (<size-of-key>, <size-of-value) for one parameter.
104
105 :param-data:
106
107 A blob of bytes from which each parameter key and value can be
108 retrieved using the list of size couples stored in the previous
109 field.
110
111 Mandatory parameters comes first, then the advisory ones.
89
112
90 :payload:
113 :payload:
91
114
@@ -115,6 +138,15 b' from i18n import _'
115 _fpartheadersize = '>H'
138 _fpartheadersize = '>H'
116 _fparttypesize = '>B'
139 _fparttypesize = '>B'
117 _fpayloadsize = '>I'
140 _fpayloadsize = '>I'
141 _fpartparamcount = '>BB'
142
143 def _makefpartparamsizes(nbparams):
144 """return a struct format to read part parameter sizes
145
146 The number parameters is variable so we need to build that format
147 dynamically.
148 """
149 return '>'+('BB'*nbparams)
118
150
119 class bundle20(object):
151 class bundle20(object):
120 """represent an outgoing bundle2 container
152 """represent an outgoing bundle2 container
@@ -263,9 +295,27 b' class unbundle20(object):'
263 typesize = _unpack(_fparttypesize, fromheader(1))[0]
295 typesize = _unpack(_fparttypesize, fromheader(1))[0]
264 parttype = fromheader(typesize)
296 parttype = fromheader(typesize)
265 self.ui.debug('part type: "%s"\n' % parttype)
297 self.ui.debug('part type: "%s"\n' % parttype)
266 assert fromheader(2) == '\0\0' # no option for now
298 ## reading parameters
299 # param count
300 mancount, advcount = _unpack(_fpartparamcount, fromheader(2))
301 self.ui.debug('part parameters: %i\n' % (mancount + advcount))
302 # param size
303 paramsizes = _unpack(_makefpartparamsizes(mancount + advcount),
304 fromheader(2*(mancount + advcount)))
305 # make it a list of couple again
306 paramsizes = zip(paramsizes[::2], paramsizes[1::2])
307 # split mandatory from advisory
308 mansizes = paramsizes[:mancount]
309 advsizes = paramsizes[mancount:]
310 # retrive param value
311 manparams = []
312 for key, value in mansizes:
313 manparams.append((fromheader(key), fromheader(value)))
314 advparams = []
315 for key, value in advsizes:
316 advparams.append((fromheader(key), fromheader(value)))
267 del self._offset # clean up layer, nobody saw anything.
317 del self._offset # clean up layer, nobody saw anything.
268 self.ui.debug('part parameters: 0\n')
318 ## part payload
269 payload = []
319 payload = []
270 payloadsize = self._unpack(_fpayloadsize)[0]
320 payloadsize = self._unpack(_fpayloadsize)[0]
271 self.ui.debug('payload chunk size: %i\n' % payloadsize)
321 self.ui.debug('payload chunk size: %i\n' % payloadsize)
@@ -274,7 +324,7 b' class unbundle20(object):'
274 payloadsize = self._unpack(_fpayloadsize)[0]
324 payloadsize = self._unpack(_fpayloadsize)[0]
275 self.ui.debug('payload chunk size: %i\n' % payloadsize)
325 self.ui.debug('payload chunk size: %i\n' % payloadsize)
276 payload = ''.join(payload)
326 payload = ''.join(payload)
277 current = part(parttype, data=payload)
327 current = part(parttype, manparams, advparams, data=payload)
278 return current
328 return current
279
329
280
330
@@ -285,19 +335,46 b' class part(object):'
285 handler.
335 handler.
286 """
336 """
287
337
288 def __init__(self, parttype, data=''):
338 def __init__(self, parttype, mandatoryparams=(), advisoryparams=(),
339 data=''):
289 self.type = parttype
340 self.type = parttype
290 self.data = data
341 self.data = data
342 self.mandatoryparams = mandatoryparams
343 self.advisoryparams = advisoryparams
291
344
292 def getchunks(self):
345 def getchunks(self):
293 ### header
346 #### header
347 ## parttype
294 header = [_pack(_fparttypesize, len(self.type)),
348 header = [_pack(_fparttypesize, len(self.type)),
295 self.type,
349 self.type,
296 '\0\0', # No option support for now.
297 ]
350 ]
351 ## parameters
352 # count
353 manpar = self.mandatoryparams
354 advpar = self.advisoryparams
355 header.append(_pack(_fpartparamcount, len(manpar), len(advpar)))
356 # size
357 parsizes = []
358 for key, value in manpar:
359 parsizes.append(len(key))
360 parsizes.append(len(value))
361 for key, value in advpar:
362 parsizes.append(len(key))
363 parsizes.append(len(value))
364 paramsizes = _pack(_makefpartparamsizes(len(parsizes) / 2), *parsizes)
365 header.append(paramsizes)
366 # key, value
367 for key, value in manpar:
368 header.append(key)
369 header.append(value)
370 for key, value in advpar:
371 header.append(key)
372 header.append(value)
373 ## finalize header
298 headerchunk = ''.join(header)
374 headerchunk = ''.join(header)
299 yield _pack(_fpartheadersize, len(headerchunk))
375 yield _pack(_fpartheadersize, len(headerchunk))
300 yield headerchunk
376 yield headerchunk
377 ## payload
301 # we only support fixed size data now.
378 # we only support fixed size data now.
302 # This will be improved in the future.
379 # This will be improved in the future.
303 if len(self.data):
380 if len(self.data):
@@ -306,4 +383,3 b' class part(object):'
306 # end of payload
383 # end of payload
307 yield _pack(_fpayloadsize, 0)
384 yield _pack(_fpayloadsize, 0)
308
385
309
@@ -42,6 +42,11 b' Create an extension to test bundle2 API'
42 > bundler.addpart(part)
42 > bundler.addpart(part)
43 > part = bundle2.part('test:song', data=ELEPHANTSSONG)
43 > part = bundle2.part('test:song', data=ELEPHANTSSONG)
44 > bundler.addpart(part)
44 > bundler.addpart(part)
45 > part = bundle2.part('test:math',
46 > [('pi', '3.14'), ('e', '2.72')],
47 > [('cooking', 'raw')],
48 > '42')
49 > bundler.addpart(part)
45 >
50 >
46 > if path is None:
51 > if path is None:
47 > file = sys.stdout
52 > file = sys.stdout
@@ -69,6 +74,8 b' Create an extension to test bundle2 API'
69 > ui.write('parts count: %i\n' % len(parts))
74 > ui.write('parts count: %i\n' % len(parts))
70 > for p in parts:
75 > for p in parts:
71 > ui.write(' :%s:\n' % p.type)
76 > ui.write(' :%s:\n' % p.type)
77 > ui.write(' mandatory: %i\n' % len(p.mandatoryparams))
78 > ui.write(' advisory: %i\n' % len(p.advisoryparams))
72 > ui.write(' payload: %i bytes\n' % len(p.data))
79 > ui.write(' payload: %i bytes\n' % len(p.data))
73 > EOF
80 > EOF
74 $ cat >> $HGRCPATH << EOF
81 $ cat >> $HGRCPATH << EOF
@@ -247,6 +254,7 b' Test part'
247 bundle part: "test:empty"
254 bundle part: "test:empty"
248 bundle part: "test:empty"
255 bundle part: "test:empty"
249 bundle part: "test:song"
256 bundle part: "test:song"
257 bundle part: "test:math"
250 end of bundle
258 end of bundle
251
259
252 $ cat ../parts.hg2
260 $ cat ../parts.hg2
@@ -254,18 +262,28 b' Test part'
254 test:empty\x00\x00\x00\x00\x00\x00\x00\r (esc)
262 test:empty\x00\x00\x00\x00\x00\x00\x00\r (esc)
255 test:empty\x00\x00\x00\x00\x00\x00\x00\x0c test:song\x00\x00\x00\x00\x00\xb2Patali Dirapata, Cromda Cromda Ripalo, Pata Pata, Ko Ko Ko (esc)
263 test:empty\x00\x00\x00\x00\x00\x00\x00\x0c test:song\x00\x00\x00\x00\x00\xb2Patali Dirapata, Cromda Cromda Ripalo, Pata Pata, Ko Ko Ko (esc)
256 Bokoro Dipoulito, Rondi Rondi Pepino, Pata Pata, Ko Ko Ko
264 Bokoro Dipoulito, Rondi Rondi Pepino, Pata Pata, Ko Ko Ko
257 Emana Karassoli, Loucra Loucra Ponponto, Pata Pata, Ko Ko Ko.\x00\x00\x00\x00\x00\x00 (no-eol) (esc)
265 Emana Karassoli, Loucra Loucra Ponponto, Pata Pata, Ko Ko Ko.\x00\x00\x00\x00\x00' test:math\x02\x01\x02\x04\x01\x04\x07\x03pi3.14e2.72cookingraw\x00\x00\x00\x0242\x00\x00\x00\x00\x00\x00 (no-eol) (esc)
258
266
259
267
260 $ hg unbundle2 < ../parts.hg2
268 $ hg unbundle2 < ../parts.hg2
261 options count: 0
269 options count: 0
262 parts count: 3
270 parts count: 4
263 :test:empty:
271 :test:empty:
272 mandatory: 0
273 advisory: 0
264 payload: 0 bytes
274 payload: 0 bytes
265 :test:empty:
275 :test:empty:
276 mandatory: 0
277 advisory: 0
266 payload: 0 bytes
278 payload: 0 bytes
267 :test:song:
279 :test:song:
280 mandatory: 0
281 advisory: 0
268 payload: 178 bytes
282 payload: 178 bytes
283 :test:math:
284 mandatory: 2
285 advisory: 1
286 payload: 2 bytes
269
287
270 $ hg unbundle2 --debug < ../parts.hg2
288 $ hg unbundle2 --debug < ../parts.hg2
271 start processing of HG20 stream
289 start processing of HG20 stream
@@ -285,12 +303,27 b' Test part'
285 part parameters: 0
303 part parameters: 0
286 payload chunk size: 178
304 payload chunk size: 178
287 payload chunk size: 0
305 payload chunk size: 0
306 part header size: 39
307 part type: "test:math"
308 part parameters: 3
309 payload chunk size: 2
310 payload chunk size: 0
288 part header size: 0
311 part header size: 0
289 end of bundle2 stream
312 end of bundle2 stream
290 parts count: 3
313 parts count: 4
291 :test:empty:
314 :test:empty:
315 mandatory: 0
316 advisory: 0
292 payload: 0 bytes
317 payload: 0 bytes
293 :test:empty:
318 :test:empty:
319 mandatory: 0
320 advisory: 0
294 payload: 0 bytes
321 payload: 0 bytes
295 :test:song:
322 :test:song:
323 mandatory: 0
324 advisory: 0
296 payload: 178 bytes
325 payload: 178 bytes
326 :test:math:
327 mandatory: 2
328 advisory: 1
329 payload: 2 bytes
General Comments 0
You need to be logged in to leave comments. Login now