1212					zlib ,
1313					LazyMixin ,
1414					unpack_from ,
15+ 					bin_to_hex ,
1516					file_contents_ro_filepath ,
1617					)
1718
6061from  binascii  import  crc32 
6162
6263from  itertools  import  izip 
64+ import  tempfile 
6365import  array 
6466import  os 
6567import  sys 
@@ -176,9 +178,10 @@ def append(self, binsha, crc, offset):
176178		"""Append one piece of object information""" 
177179		self ._objs .append ((binsha , crc , offset ))
178180
179- 	def  write (self , pack_binsha , write ):
181+ 	def  write (self , pack_sha , write ):
180182		"""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""" 
182185		# sort for sha1 hash 
183186		self ._objs .sort (key = lambda  o : o [0 ])
184187
@@ -192,11 +195,10 @@ def write(self, pack_binsha, write):
192195		for  t  in  self ._objs :
193196			tmplist [ord (t [0 ][0 ])] +=  1 
194197		#END prepare fanout 
195- 		
196198		for  i  in  xrange (255 ):
197199			v  =  tmplist [i ]
198200			sha_write (pack ('>L' , v ))
199- 			tmplist [i + 1 ] =  v 
201+ 			tmplist [i + 1 ] + =  v 
200202		#END write each fanout entry 
201203		sha_write (pack ('>L' , tmplist [255 ]))
202204
@@ -226,9 +228,11 @@ def write(self, pack_binsha, write):
226228		#END for each offset 
227229
228230		# 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 
232236
233237
234238
@@ -767,7 +771,9 @@ def is_valid_stream(self, sha, use_crc=False):
767771		""" 
768772		Verify that the stream at the given sha is valid. 
769773		 
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. 
771777		:param sha: 20 byte sha1 of the object whose stream to verify 
772778			whether the compressed stream of the object is valid. If it is  
773779			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,
890896			this would be the place to put it. Otherwise we have to pre-iterate and store  
891897			all items into a list to get the number, which uses more memory than necessary. 
892898		: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 
894901		:note: The destination of the write functions is up to the user. It could 
895902			be a socket, or a file for instance 
896903		:note: writes only undeltified objects""" 
@@ -944,16 +951,41 @@ def write_pack(cls, object_iter, pack_write, index_write=None,
944951		#END count assertion 
945952
946953		# 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 ;) 
951958
959+ 		index_sha  =  None 
952960		if  wants_index :
953- 			index .write (binsha , index_write )
961+ 			index_sha   =   index .write (pack_sha , index_write )
954962		#END handle index 
955963
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 )
957989
958990
959991	#} END interface 
0 commit comments