12
12
zlib ,
13
13
LazyMixin ,
14
14
unpack_from ,
15
+ bin_to_hex ,
15
16
file_contents_ro_filepath ,
16
17
)
17
18
60
61
from binascii import crc32
61
62
62
63
from itertools import izip
64
+ import tempfile
63
65
import array
64
66
import os
65
67
import sys
@@ -176,9 +178,10 @@ def append(self, binsha, crc, offset):
176
178
"""Append one piece of object information"""
177
179
self ._objs .append ((binsha , crc , offset ))
178
180
179
- def write (self , pack_binsha , write ):
181
+ def write (self , pack_sha , write ):
180
182
"""Write the index file using the given write method
181
- :param pack_binsha: sha over the whole pack that we index"""
183
+ :param pack_sha: binary sha over the whole pack that we index
184
+ :return: sha1 binary sha over all index file contents"""
182
185
# sort for sha1 hash
183
186
self ._objs .sort (key = lambda o : o [0 ])
184
187
@@ -192,11 +195,10 @@ def write(self, pack_binsha, write):
192
195
for t in self ._objs :
193
196
tmplist [ord (t [0 ][0 ])] += 1
194
197
#END prepare fanout
195
-
196
198
for i in xrange (255 ):
197
199
v = tmplist [i ]
198
200
sha_write (pack ('>L' , v ))
199
- tmplist [i + 1 ] = v
201
+ tmplist [i + 1 ] + = v
200
202
#END write each fanout entry
201
203
sha_write (pack ('>L' , tmplist [255 ]))
202
204
@@ -226,9 +228,11 @@ def write(self, pack_binsha, write):
226
228
#END for each offset
227
229
228
230
# trailer
229
- assert (len (pack_binsha ) == 20 )
230
- sha_write (pack_binsha )
231
- write (sha_writer .sha (as_hex = False ))
231
+ assert (len (pack_sha ) == 20 )
232
+ sha_write (pack_sha )
233
+ sha = sha_writer .sha (as_hex = False )
234
+ write (sha )
235
+ return sha
232
236
233
237
234
238
@@ -767,7 +771,9 @@ def is_valid_stream(self, sha, use_crc=False):
767
771
"""
768
772
Verify that the stream at the given sha is valid.
769
773
770
- :param use_crc: if True, the index' crc for the sha is used to determine
774
+ :param use_crc: if True, the index' crc is run over the compressed stream of
775
+ the object, which is much faster than checking the sha1. It is also
776
+ more prone to unnoticed corruption or manipulation.
771
777
:param sha: 20 byte sha1 of the object whose stream to verify
772
778
whether the compressed stream of the object is valid. If it is
773
779
a delta, this only verifies that the delta's data is valid, not the
@@ -890,7 +896,8 @@ def write_pack(cls, object_iter, pack_write, index_write=None,
890
896
this would be the place to put it. Otherwise we have to pre-iterate and store
891
897
all items into a list to get the number, which uses more memory than necessary.
892
898
:param zlib_compression: the zlib compression level to use
893
- :return: binary sha over all the contents of the pack
899
+ :return: tuple(pack_sha, index_binsha) binary sha over all the contents of the pack
900
+ and over all contents of the index. If index_write was None, index_binsha will be None
894
901
:note: The destination of the write functions is up to the user. It could
895
902
be a socket, or a file for instance
896
903
:note: writes only undeltified objects"""
@@ -944,16 +951,41 @@ def write_pack(cls, object_iter, pack_write, index_write=None,
944
951
#END count assertion
945
952
946
953
# write footer
947
- binsha = pack_writer .sha (as_hex = False )
948
- assert len (binsha ) == 20
949
- pack_write (binsha )
950
- ofs += len (binsha ) # just for completeness ;)
954
+ pack_sha = pack_writer .sha (as_hex = False )
955
+ assert len (pack_sha ) == 20
956
+ pack_write (pack_sha )
957
+ ofs += len (pack_sha ) # just for completeness ;)
951
958
959
+ index_sha = None
952
960
if wants_index :
953
- index .write (binsha , index_write )
961
+ index_sha = index .write (pack_sha , index_write )
954
962
#END handle index
955
963
956
- return binsha
964
+ return pack_sha , index_sha
965
+
966
+ @classmethod
967
+ def create (cls , object_iter , base_dir , object_count = None , zlib_compression = zlib .Z_BEST_SPEED ):
968
+ """Create a new on-disk entity comprised of a properly named pack file and a properly named
969
+ and corresponding index file. The pack contains all OStream objects contained in object iter.
970
+ :param base_dir: directory which is to contain the files
971
+ :return: PackEntity instance initialized with the new pack
972
+ :note: for more information on the other parameters see the write_pack method"""
973
+ pack_fd , pack_path = tempfile .mkstemp ('' , 'pack' , base_dir )
974
+ index_fd , index_path = tempfile .mkstemp ('' , 'index' , base_dir )
975
+ pack_write = lambda d : os .write (pack_fd , d )
976
+ index_write = lambda d : os .write (index_fd , d )
977
+
978
+ pack_binsha , index_binsha = cls .write_pack (object_iter , pack_write , index_write , object_count , zlib_compression )
979
+ os .close (pack_fd )
980
+ os .close (index_fd )
981
+
982
+ fmt = "pack-%s.%s"
983
+ new_pack_path = os .path .join (base_dir , fmt % (bin_to_hex (pack_binsha ), 'pack' ))
984
+ new_index_path = os .path .join (base_dir , fmt % (bin_to_hex (pack_binsha ), 'idx' ))
985
+ os .rename (pack_path , new_pack_path )
986
+ os .rename (index_path , new_index_path )
987
+
988
+ return cls (new_pack_path )
957
989
958
990
959
991
#} END interface
0 commit comments