22 - end of stream marker. |
22 - end of stream marker. |
23 |
23 |
24 the Binary format |
24 the Binary format |
25 ============================ |
25 ============================ |
26 |
26 |
27 All numbers are unsigned and big endian. |
27 All numbers are unsigned and big-endian. |
28 |
28 |
29 stream level parameters |
29 stream level parameters |
30 ------------------------ |
30 ------------------------ |
31 |
31 |
32 Binary format is as follow |
32 Binary format is as follow |
38 :params value: arbitrary number of Bytes |
38 :params value: arbitrary number of Bytes |
39 |
39 |
40 A blob of `params size` containing the serialized version of all stream level |
40 A blob of `params size` containing the serialized version of all stream level |
41 parameters. |
41 parameters. |
42 |
42 |
43 The blob contains a space separated list of parameters. parameter with value |
43 The blob contains a space separated list of parameters. Parameters with value |
44 are stored in the form `<name>=<value>`. Both name and value are urlquoted. |
44 are stored in the form `<name>=<value>`. Both name and value are urlquoted. |
45 |
45 |
46 Empty name are obviously forbidden. |
46 Empty name are obviously forbidden. |
47 |
47 |
48 Name MUST start with a letter. If this first letter is lower case, the |
48 Name MUST start with a letter. If this first letter is lower case, the |
49 parameter is advisory and can be safefly ignored. However when the first |
49 parameter is advisory and can be safely ignored. However when the first |
50 letter is capital, the parameter is mandatory and the bundling process MUST |
50 letter is capital, the parameter is mandatory and the bundling process MUST |
51 stop if he is not able to proceed it. |
51 stop if he is not able to proceed it. |
52 |
52 |
53 Stream parameters use a simple textual format for two main reasons: |
53 Stream parameters use a simple textual format for two main reasons: |
54 |
54 |
55 - Stream level parameters should remains simple and we want to discourage any |
55 - Stream level parameters should remain simple and we want to discourage any |
56 crazy usage. |
56 crazy usage. |
57 - Textual data allow easy human inspection of a the bundle2 header in case of |
57 - Textual data allow easy human inspection of a bundle2 header in case of |
58 troubles. |
58 troubles. |
59 |
59 |
60 Any Applicative level options MUST go into a bundle2 part instead. |
60 Any Applicative level options MUST go into a bundle2 part instead. |
61 |
61 |
62 Payload part |
62 Payload part |
83 |
83 |
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 |
88 :typename: alphanumerical part name |
88 :parttype: alphanumerical part name |
89 |
89 |
90 :partid: A 32bits integer (unique in the bundle) that can be used to refer |
90 :partid: A 32bits integer (unique in the bundle) that can be used to refer |
91 to this part. |
91 to this part. |
92 |
92 |
93 :parameters: |
93 :parameters: |
94 |
94 |
95 Part's parameter may have arbitraty content, the binary structure is:: |
95 Part's parameter may have arbitrary content, the binary structure is:: |
96 |
96 |
97 <mandatory-count><advisory-count><param-sizes><param-data> |
97 <mandatory-count><advisory-count><param-sizes><param-data> |
98 |
98 |
99 :mandatory-count: 1 byte, number of mandatory parameters |
99 :mandatory-count: 1 byte, number of mandatory parameters |
100 |
100 |
119 |
119 |
120 `chunksize` is a 32 bits integer, `chunkdata` are plain bytes (as much as |
120 `chunksize` is a 32 bits integer, `chunkdata` are plain bytes (as much as |
121 `chunksize` says)` The payload part is concluded by a zero size chunk. |
121 `chunksize` says)` The payload part is concluded by a zero size chunk. |
122 |
122 |
123 The current implementation always produces either zero or one chunk. |
123 The current implementation always produces either zero or one chunk. |
124 This is an implementation limitation that will ultimatly be lifted. |
124 This is an implementation limitation that will ultimately be lifted. |
125 |
125 |
126 Bundle processing |
126 Bundle processing |
127 ============================ |
127 ============================ |
128 |
128 |
129 Each part is processed in order using a "part handler". Handler are registered |
129 Each part is processed in order using a "part handler". Handler are registered |
191 |
191 |
192 class unbundlerecords(object): |
192 class unbundlerecords(object): |
193 """keep record of what happens during and unbundle |
193 """keep record of what happens during and unbundle |
194 |
194 |
195 New records are added using `records.add('cat', obj)`. Where 'cat' is a |
195 New records are added using `records.add('cat', obj)`. Where 'cat' is a |
196 category of record and obj is an arbitraty object. |
196 category of record and obj is an arbitrary object. |
197 |
197 |
198 `records['cat']` will return all entries of this category 'cat'. |
198 `records['cat']` will return all entries of this category 'cat'. |
199 |
199 |
200 Iterating on the object itself will yield `('category', obj)` tuples |
200 Iterating on the object itself will yield `('category', obj)` tuples |
201 for all entries. |
201 for all entries. |
325 class bundle20(object): |
325 class bundle20(object): |
326 """represent an outgoing bundle2 container |
326 """represent an outgoing bundle2 container |
327 |
327 |
328 Use the `addparam` method to add stream level parameter. and `addpart` to |
328 Use the `addparam` method to add stream level parameter. and `addpart` to |
329 populate it. Then call `getchunks` to retrieve all the binary chunks of |
329 populate it. Then call `getchunks` to retrieve all the binary chunks of |
330 datathat compose the bundle2 container.""" |
330 data that compose the bundle2 container.""" |
331 |
331 |
332 def __init__(self, ui): |
332 def __init__(self, ui): |
333 self.ui = ui |
333 self.ui = ui |
334 self._params = [] |
334 self._params = [] |
335 self._parts = [] |
335 self._parts = [] |
343 self._params.append((name, value)) |
343 self._params.append((name, value)) |
344 |
344 |
345 def addpart(self, part): |
345 def addpart(self, part): |
346 """add a new part to the bundle2 container |
346 """add a new part to the bundle2 container |
347 |
347 |
348 Parts contains the actuall applicative payload.""" |
348 Parts contains the actual applicative payload.""" |
349 assert part.id is None |
349 assert part.id is None |
350 part.id = len(self._parts) # very cheap counter |
350 part.id = len(self._parts) # very cheap counter |
351 self._parts.append(part) |
351 self._parts.append(part) |
352 |
352 |
353 def getchunks(self): |
353 def getchunks(self): |
410 raise util.Abort(_('unknown bundle version %s') % version) |
410 raise util.Abort(_('unknown bundle version %s') % version) |
411 self.ui.debug('start processing of %s stream\n' % header) |
411 self.ui.debug('start processing of %s stream\n' % header) |
412 |
412 |
413 @util.propertycache |
413 @util.propertycache |
414 def params(self): |
414 def params(self): |
415 """dictionnary of stream level parameters""" |
415 """dictionary of stream level parameters""" |
416 self.ui.debug('reading bundle2 stream parameters\n') |
416 self.ui.debug('reading bundle2 stream parameters\n') |
417 params = {} |
417 params = {} |
418 paramssize = self._unpack(_fstreamparamsize)[0] |
418 paramssize = self._unpack(_fstreamparamsize)[0] |
419 if paramssize: |
419 if paramssize: |
420 for p in self._readexact(paramssize).split(' '): |
420 for p in self._readexact(paramssize).split(' '): |