83
81
return sha.hexdigest()
85
"""Convert a hex string to a binary sha string."""
87
for i in range(0, len(hex), 2):
88
ret += chr(int(hex[i:i+2], 16))
93
"""Convert a binary sha string to a hex sha string."""
96
ret += "%02x" % ord(i)
86
100
MAX_MMAP_SIZE = 256 * 1024 * 1024
88
102
def simple_mmap(f, offset, size, access=mmap.ACCESS_READ):
314
def read_pack_header(f):
316
assert header[:4] == "PACK"
317
(version,) = struct.unpack_from(">L", header, 4)
318
assert version in (2, 3), "Version was %d" % version
319
(num_objects,) = struct.unpack_from(">L", header, 8)
320
return (version, num_objects)
323
def read_pack_tail(f):
327
def unpack_object(map):
328
bytes = take_msb_bytes(map, 0)
329
type = (bytes[0] >> 4) & 0x07
330
size = bytes[0] & 0x0f
331
for i, byte in enumerate(bytes[1:]):
332
size += (byte & 0x7f) << ((i * 7) + 4)
333
raw_base = len(bytes)
334
if type == 6: # offset delta
335
bytes = take_msb_bytes(map, raw_base)
336
assert not (bytes[-1] & 0x80)
337
delta_base_offset = bytes[0] & 0x7f
338
for byte in bytes[1:]:
339
delta_base_offset += 1
340
delta_base_offset <<= 7
341
delta_base_offset += (byte & 0x7f)
343
uncomp, comp_len = read_zlib(map, raw_base, size)
344
assert size == len(uncomp)
345
return type, (delta_base_offset, uncomp), comp_len+raw_base
346
elif type == 7: # ref delta
347
basename = map[raw_base:raw_base+20]
348
uncomp, comp_len = read_zlib(map, raw_base+20, size)
349
assert size == len(uncomp)
350
return type, (basename, uncomp), comp_len+raw_base+20
352
uncomp, comp_len = read_zlib(map, raw_base, size)
353
assert len(uncomp) == size
354
return type, uncomp, comp_len+raw_base
357
328
class PackData(object):
358
329
"""The data contained in a packfile.
400
371
def _read_header(self):
401
372
f = open(self._filename, 'rb')
403
(version, self._num_objects) = \
405
375
f.seek(self._size-20)
406
(self._stored_checksum,) = read_pack_tail(f)
376
self._stored_checksum = f.read(20)
379
assert header[:4] == "PACK"
380
(version,) = struct.unpack_from(">L", header, 4)
381
assert version in (2, 3), "Version was %d" % version
382
(self._num_objects,) = struct.unpack_from(">L", header, 8)
410
384
def __len__(self):
411
385
"""Returns the number of objects in this pack."""
424
398
f = open(self._filename, 'rb')
425
399
for i in range(len(self)):
426
400
map = simple_mmap(f, offset, self._size-offset)
427
(type, obj, total_size) = unpack_object(map)
401
(type, obj, total_size) = self._unpack_object(map)
428
402
yield offset, type, obj
429
403
offset += total_size
501
475
f = open(self._filename, 'rb')
503
477
map = simple_mmap(f, offset, size-offset)
504
return unpack_object(map)[:2]
478
return self._unpack_object(map)[:2]
482
def _unpack_object(self, map):
483
bytes = take_msb_bytes(map, 0)
484
type = (bytes[0] >> 4) & 0x07
485
size = bytes[0] & 0x0f
486
for i, byte in enumerate(bytes[1:]):
487
size += (byte & 0x7f) << ((i * 7) + 4)
488
raw_base = len(bytes)
489
if type == 6: # offset delta
490
bytes = take_msb_bytes(map, raw_base)
491
assert not (bytes[-1] & 0x80)
492
delta_base_offset = bytes[0] & 0x7f
493
for byte in bytes[1:]:
494
delta_base_offset += 1
495
delta_base_offset <<= 7
496
delta_base_offset += (byte & 0x7f)
498
uncomp, comp_len = read_zlib(map, raw_base, size)
499
assert size == len(uncomp)
500
return type, (delta_base_offset, uncomp), comp_len+raw_base
501
elif type == 7: # ref delta
502
basename = map[raw_base:raw_base+20]
503
uncomp, comp_len = read_zlib(map, raw_base+20, size)
504
assert size == len(uncomp)
505
return type, (basename, uncomp), comp_len+raw_base+20
507
uncomp, comp_len = read_zlib(map, raw_base, size)
508
assert len(uncomp) == size
509
return type, uncomp, comp_len+raw_base
509
512
class SHA1Writer(object):