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. |
|
116 | Use the `addparam` method to add stream level parameter. and `addpart` to | |
96 |
`getchunks` to retrieve all the binary chunks of |
|
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