Show More
@@ -89,8 +89,13 b' Binary format is as follow' | |||||
89 |
|
89 | |||
90 | :payload: |
|
90 | :payload: | |
91 |
|
91 | |||
92 | The current payload is a 32bit integer with a value of 0. This is |
|
92 | payload is a series of `<chunksize><chunkdata>`. | |
93 | considered an "empty" payload. |
|
93 | ||
|
94 | `chunksize` is a 32 bits integer, `chunkdata` are plain bytes (as much as | |||
|
95 | `chunksize` says)` The payload part is concluded by a zero size chunk. | |||
|
96 | ||||
|
97 | The current implementation always produces either zero or one chunk. | |||
|
98 | This is an implementation limitation that will ultimatly be lifted. | |||
94 | """ |
|
99 | """ | |
95 |
|
100 | |||
96 | import util |
|
101 | import util | |
@@ -109,6 +114,7 b' from i18n import _' | |||||
109 | _fstreamparamsize = '>H' |
|
114 | _fstreamparamsize = '>H' | |
110 | _fpartheadersize = '>H' |
|
115 | _fpartheadersize = '>H' | |
111 | _fparttypesize = '>B' |
|
116 | _fparttypesize = '>B' | |
|
117 | _fpayloadsize = '>I' | |||
112 |
|
118 | |||
113 | class bundle20(object): |
|
119 | class bundle20(object): | |
114 | """represent an outgoing bundle2 container |
|
120 | """represent an outgoing bundle2 container | |
@@ -257,12 +263,18 b' class unbundle20(object):' | |||||
257 | typesize = _unpack(_fparttypesize, fromheader(1))[0] |
|
263 | typesize = _unpack(_fparttypesize, fromheader(1))[0] | |
258 | parttype = fromheader(typesize) |
|
264 | parttype = fromheader(typesize) | |
259 | self.ui.debug('part type: "%s"\n' % parttype) |
|
265 | self.ui.debug('part type: "%s"\n' % parttype) | |
260 | current = part(parttype) |
|
|||
261 | assert fromheader(2) == '\0\0' # no option for now |
|
266 | assert fromheader(2) == '\0\0' # no option for now | |
262 | del self._offset # clean up layer, nobody saw anything. |
|
267 | del self._offset # clean up layer, nobody saw anything. | |
263 | self.ui.debug('part parameters: 0\n') |
|
268 | self.ui.debug('part parameters: 0\n') | |
264 | assert self._readexact(4) == '\0\0\0\0' #empty payload |
|
269 | payload = [] | |
265 | self.ui.debug('payload chunk size: 0\n') |
|
270 | payloadsize = self._unpack(_fpayloadsize)[0] | |
|
271 | self.ui.debug('payload chunk size: %i\n' % payloadsize) | |||
|
272 | while payloadsize: | |||
|
273 | payload.append(self._readexact(payloadsize)) | |||
|
274 | payloadsize = self._unpack(_fpayloadsize)[0] | |||
|
275 | self.ui.debug('payload chunk size: %i\n' % payloadsize) | |||
|
276 | payload = ''.join(payload) | |||
|
277 | current = part(parttype, data=payload) | |||
266 | return current |
|
278 | return current | |
267 |
|
279 | |||
268 |
|
280 | |||
@@ -286,7 +298,12 b' class part(object):' | |||||
286 | headerchunk = ''.join(header) |
|
298 | headerchunk = ''.join(header) | |
287 | yield _pack(_fpartheadersize, len(headerchunk)) |
|
299 | yield _pack(_fpartheadersize, len(headerchunk)) | |
288 | yield headerchunk |
|
300 | yield headerchunk | |
289 | # force empty part for now |
|
301 | # we only support fixed size data now. | |
290 | yield '\0\0\0\0' |
|
302 | # This will be improved in the future. | |
|
303 | if len(self.data): | |||
|
304 | yield _pack(_fpayloadsize, len(self.data)) | |||
|
305 | yield self.data | |||
|
306 | # end of payload | |||
|
307 | yield _pack(_fpayloadsize, 0) | |||
291 |
|
308 | |||
292 |
|
309 |
@@ -15,6 +15,11 b' Create an extension to test bundle2 API' | |||||
15 | > cmdtable = {} |
|
15 | > cmdtable = {} | |
16 | > command = cmdutil.command(cmdtable) |
|
16 | > command = cmdutil.command(cmdtable) | |
17 | > |
|
17 | > | |
|
18 | > ELEPHANTSSONG = """Patali Dirapata, Cromda Cromda Ripalo, Pata Pata, Ko Ko Ko | |||
|
19 | > Bokoro Dipoulito, Rondi Rondi Pepino, Pata Pata, Ko Ko Ko | |||
|
20 | > Emana Karassoli, Loucra Loucra Ponponto, Pata Pata, Ko Ko Ko.""" | |||
|
21 | > assert len(ELEPHANTSSONG) == 178 # future test say 178 bytes, trust it. | |||
|
22 | > | |||
18 | > @command('bundle2', |
|
23 | > @command('bundle2', | |
19 | > [('', 'param', [], 'stream level parameter'), |
|
24 | > [('', 'param', [], 'stream level parameter'), | |
20 | > ('', 'parts', False, 'include some arbitrary parts to the bundle'),], |
|
25 | > ('', 'parts', False, 'include some arbitrary parts to the bundle'),], | |
@@ -35,6 +40,8 b' Create an extension to test bundle2 API' | |||||
35 | > # add a second one to make sure we handle multiple parts |
|
40 | > # add a second one to make sure we handle multiple parts | |
36 | > part = bundle2.part('test:empty') |
|
41 | > part = bundle2.part('test:empty') | |
37 | > bundler.addpart(part) |
|
42 | > bundler.addpart(part) | |
|
43 | > part = bundle2.part('test:song', data=ELEPHANTSSONG) | |||
|
44 | > bundler.addpart(part) | |||
38 | > |
|
45 | > | |
39 | > if path is None: |
|
46 | > if path is None: | |
40 | > file = sys.stdout |
|
47 | > file = sys.stdout | |
@@ -62,6 +69,7 b' Create an extension to test bundle2 API' | |||||
62 | > ui.write('parts count: %i\n' % len(parts)) |
|
69 | > ui.write('parts count: %i\n' % len(parts)) | |
63 | > for p in parts: |
|
70 | > for p in parts: | |
64 | > ui.write(' :%s:\n' % p.type) |
|
71 | > ui.write(' :%s:\n' % p.type) | |
|
72 | > ui.write(' payload: %i bytes\n' % len(p.data)) | |||
65 | > EOF |
|
73 | > EOF | |
66 | $ cat >> $HGRCPATH << EOF |
|
74 | $ cat >> $HGRCPATH << EOF | |
67 | > [extensions] |
|
75 | > [extensions] | |
@@ -238,19 +246,26 b' Test part' | |||||
238 | start of parts |
|
246 | start of parts | |
239 | bundle part: "test:empty" |
|
247 | bundle part: "test:empty" | |
240 | bundle part: "test:empty" |
|
248 | bundle part: "test:empty" | |
|
249 | bundle part: "test:song" | |||
241 | end of bundle |
|
250 | end of bundle | |
242 |
|
251 | |||
243 | $ cat ../parts.hg2 |
|
252 | $ cat ../parts.hg2 | |
244 | HG20\x00\x00\x00\r (esc) |
|
253 | HG20\x00\x00\x00\r (esc) | |
245 | test:empty\x00\x00\x00\x00\x00\x00\x00\r (esc) |
|
254 | test:empty\x00\x00\x00\x00\x00\x00\x00\r (esc) | |
246 | test:empty\x00\x00\x00\x00\x00\x00\x00\x00 (no-eol) (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) | |
|
256 | 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) | |||
247 |
|
258 | |||
248 |
|
259 | |||
249 | $ hg unbundle2 < ../parts.hg2 |
|
260 | $ hg unbundle2 < ../parts.hg2 | |
250 | options count: 0 |
|
261 | options count: 0 | |
251 |
parts count: |
|
262 | parts count: 3 | |
|
263 | :test:empty: | |||
|
264 | payload: 0 bytes | |||
252 | :test:empty: |
|
265 | :test:empty: | |
253 | :test:empty: |
|
266 | payload: 0 bytes | |
|
267 | :test:song: | |||
|
268 | payload: 178 bytes | |||
254 |
|
269 | |||
255 |
$ |
|
270 | $ hg unbundle2 --debug < ../parts.hg2 | |
256 | start processing of HG20 stream |
|
271 | start processing of HG20 stream | |
@@ -265,8 +280,17 b' Test part' | |||||
265 | part type: "test:empty" |
|
280 | part type: "test:empty" | |
266 | part parameters: 0 |
|
281 | part parameters: 0 | |
267 | payload chunk size: 0 |
|
282 | payload chunk size: 0 | |
|
283 | part header size: 12 | |||
|
284 | part type: "test:song" | |||
|
285 | part parameters: 0 | |||
|
286 | payload chunk size: 178 | |||
|
287 | payload chunk size: 0 | |||
268 | part header size: 0 |
|
288 | part header size: 0 | |
269 | end of bundle2 stream |
|
289 | end of bundle2 stream | |
270 |
parts count: |
|
290 | parts count: 3 | |
|
291 | :test:empty: | |||
|
292 | payload: 0 bytes | |||
271 | :test:empty: |
|
293 | :test:empty: | |
272 | :test:empty: |
|
294 | payload: 0 bytes | |
|
295 | :test:song: | |||
|
296 | payload: 178 bytes |
General Comments 0
You need to be logged in to leave comments.
Login now