Show More
@@ -231,10 +231,145 b' def _fm0decodemeta(data):' | |||
|
231 | 231 | d[key] = value |
|
232 | 232 | return d |
|
233 | 233 | |
|
234 | ## Parsing and writing of version "1" | |
|
235 | # | |
|
236 | # The header is followed by the markers. Each marker is made of: | |
|
237 | # | |
|
238 | # - uint32: total size of the marker (including this field) | |
|
239 | # | |
|
240 | # - float64: date in seconds since epoch | |
|
241 | # | |
|
242 | # - int16: timezone offset in minutes | |
|
243 | # | |
|
244 | # - uint16: a bit field. It is reserved for flags used in common | |
|
245 | # obsolete marker operations, to avoid repeated decoding of metadata | |
|
246 | # entries. | |
|
247 | # | |
|
248 | # - uint8: number of successors "N", can be zero. | |
|
249 | # | |
|
250 | # - uint8: number of parents "P", can be zero. | |
|
251 | # | |
|
252 | # 0: parents data stored but no parent, | |
|
253 | # 1: one parent stored, | |
|
254 | # 2: two parents stored, | |
|
255 | # 3: no parent data stored | |
|
256 | # | |
|
257 | # - uint8: number of metadata entries M | |
|
258 | # | |
|
259 | # - 20 or 32 bytes: precursor changeset identifier. | |
|
260 | # | |
|
261 | # - N*(20 or 32) bytes: successors changesets identifiers. | |
|
262 | # | |
|
263 | # - P*(20 or 32) bytes: parents of the precursors changesets. | |
|
264 | # | |
|
265 | # - M*(uint8, uint8): size of all metadata entries (key and value) | |
|
266 | # | |
|
267 | # - remaining bytes: the metadata, each (key, value) pair after the other. | |
|
268 | _fm1version = 1 | |
|
269 | _fm1fixed = '>IdhHBBB20s' | |
|
270 | _fm1nodesha1 = '20s' | |
|
271 | _fm1nodesha256 = '32s' | |
|
272 | _fm1fsize = struct.calcsize(_fm1fixed) | |
|
273 | _fm1parentnone = 3 | |
|
274 | _fm1parentshift = 14 | |
|
275 | _fm1parentmask = (_fm1parentnone << _fm1parentshift) | |
|
276 | _fm1metapair = 'BB' | |
|
277 | _fm1metapairsize = struct.calcsize('BB') | |
|
278 | ||
|
279 | def _fm1readmarkers(data, off=0): | |
|
280 | # Loop on markers | |
|
281 | l = len(data) | |
|
282 | while off + _fm1fsize <= l: | |
|
283 | # read fixed part | |
|
284 | cur = data[off:off + _fm1fsize] | |
|
285 | off += _fm1fsize | |
|
286 | fixeddata = _unpack(_fm1fixed, cur) | |
|
287 | ttsize, seconds, tz, flags, numsuc, numpar, nummeta, prec = fixeddata | |
|
288 | # extract the number of parents information | |
|
289 | if numpar == _fm1parentnone: | |
|
290 | numpar = None | |
|
291 | # build the date tuple (upgrade tz minutes to seconds) | |
|
292 | date = (seconds, tz * 60) | |
|
293 | _fm1node = _fm1nodesha1 | |
|
294 | if flags & usingsha256: | |
|
295 | _fm1node = _fm1nodesha256 | |
|
296 | fnodesize = struct.calcsize(_fm1node) | |
|
297 | # read replacement | |
|
298 | sucs = () | |
|
299 | if numsuc: | |
|
300 | s = (fnodesize * numsuc) | |
|
301 | cur = data[off:off + s] | |
|
302 | sucs = _unpack(_fm1node * numsuc, cur) | |
|
303 | off += s | |
|
304 | # read parents | |
|
305 | if numpar is None: | |
|
306 | parents = None | |
|
307 | elif numpar == 0: | |
|
308 | parents = () | |
|
309 | elif numpar: # neither None nor zero | |
|
310 | s = (fnodesize * numpar) | |
|
311 | cur = data[off:off + s] | |
|
312 | parents = _unpack(_fm1node * numpar, cur) | |
|
313 | off += s | |
|
314 | # read metadata | |
|
315 | metaformat = '>' + (_fm1metapair * nummeta) | |
|
316 | s = _fm1metapairsize * nummeta | |
|
317 | metapairsize = _unpack(metaformat, data[off:off + s]) | |
|
318 | off += s | |
|
319 | metadata = [] | |
|
320 | for idx in xrange(0, len(metapairsize), 2): | |
|
321 | sk = metapairsize[idx] | |
|
322 | sv = metapairsize[idx + 1] | |
|
323 | key = data[off:off + sk] | |
|
324 | value = data[off + sk:off + sk + sv] | |
|
325 | assert len(key) == sk | |
|
326 | assert len(value) == sv | |
|
327 | metadata.append((key, value)) | |
|
328 | off += sk + sv | |
|
329 | metadata = tuple(metadata) | |
|
330 | ||
|
331 | yield (prec, sucs, flags, metadata, date, parents) | |
|
332 | ||
|
333 | def _fm1encodeonemarker(marker): | |
|
334 | pre, sucs, flags, metadata, date, parents = marker | |
|
335 | # determine node size | |
|
336 | _fm1node = _fm1nodesha1 | |
|
337 | if flags & usingsha256: | |
|
338 | _fm1node = _fm1nodesha256 | |
|
339 | numsuc = len(sucs) | |
|
340 | numextranodes = numsuc | |
|
341 | if parents is None: | |
|
342 | numpar = _fm1parentnone | |
|
343 | else: | |
|
344 | numpar = len(parents) | |
|
345 | numextranodes += numpar | |
|
346 | formatnodes = _fm1node * numextranodes | |
|
347 | formatmeta = _fm1metapair * len(metadata) | |
|
348 | format = _fm1fixed + formatnodes + formatmeta | |
|
349 | # tz is stored in minutes so we divide by 60 | |
|
350 | tz = date[1]//60 | |
|
351 | data = [None, date[0], tz, flags, numsuc, numpar, len(metadata), pre] | |
|
352 | data.extend(sucs) | |
|
353 | if parents is not None: | |
|
354 | data.extend(parents) | |
|
355 | totalsize = struct.calcsize(format) | |
|
356 | for key, value in metadata: | |
|
357 | lk = len(key) | |
|
358 | lv = len(value) | |
|
359 | data.append(lk) | |
|
360 | data.append(lv) | |
|
361 | totalsize += lk + lv | |
|
362 | data[0] = totalsize | |
|
363 | data = [_pack(format, *data)] | |
|
364 | for key, value in metadata: | |
|
365 | data.append(key) | |
|
366 | data.append(value) | |
|
367 | return ''.join(data) | |
|
234 | 368 | |
|
235 | 369 | # mapping to read/write various marker formats |
|
236 | 370 | # <version> -> (decoder, encoder) |
|
237 |
formats = {_fm0version: (_fm0readmarkers, _fm0encodeonemarker) |
|
|
371 | formats = {_fm0version: (_fm0readmarkers, _fm0encodeonemarker), | |
|
372 | _fm1version: (_fm1readmarkers, _fm1encodeonemarker)} | |
|
238 | 373 | |
|
239 | 374 | def _readmarkers(data): |
|
240 | 375 | """Read and enumerate markers from raw data""" |
General Comments 0
You need to be logged in to leave comments.
Login now