@@ -682,19 +682,26 @@ static int compare_delta_entry(const void *a, const void *b)
682682 objects [delta_b -> obj_no ].type );
683683}
684684
685- /* Parse all objects and return the pack content SHA1 hash */
685+ static void resolve_base (struct object_entry * obj )
686+ {
687+ struct base_data * base_obj = alloc_base_data ();
688+ base_obj -> obj = obj ;
689+ base_obj -> data = NULL ;
690+ find_unresolved_deltas (base_obj );
691+ }
692+
693+ /*
694+ * First pass:
695+ * - find locations of all objects;
696+ * - calculate SHA1 of all non-delta objects;
697+ * - remember base (SHA1 or offset) for all deltas.
698+ */
686699static void parse_pack_objects (unsigned char * sha1 )
687700{
688701 int i ;
689702 struct delta_entry * delta = deltas ;
690703 struct stat st ;
691704
692- /*
693- * First pass:
694- * - find locations of all objects;
695- * - calculate SHA1 of all non-delta objects;
696- * - remember base (SHA1 or offset) for all deltas.
697- */
698705 if (verbose )
699706 progress = start_progress (
700707 from_stdin ? "Receiving objects" : "Indexing objects" ,
@@ -728,6 +735,19 @@ static void parse_pack_objects(unsigned char *sha1)
728735 if (S_ISREG (st .st_mode ) &&
729736 lseek (input_fd , 0 , SEEK_CUR ) - input_len != st .st_size )
730737 die ("pack has junk at the end" );
738+ }
739+
740+ /*
741+ * Second pass:
742+ * - for all non-delta objects, look if it is used as a base for
743+ * deltas;
744+ * - if used as a base, uncompress the object and apply all deltas,
745+ * recursively checking if the resulting object is used as a base
746+ * for some more deltas.
747+ */
748+ static void resolve_deltas (void )
749+ {
750+ int i ;
731751
732752 if (!nr_deltas )
733753 return ;
@@ -736,29 +756,63 @@ static void parse_pack_objects(unsigned char *sha1)
736756 qsort (deltas , nr_deltas , sizeof (struct delta_entry ),
737757 compare_delta_entry );
738758
739- /*
740- * Second pass:
741- * - for all non-delta objects, look if it is used as a base for
742- * deltas;
743- * - if used as a base, uncompress the object and apply all deltas,
744- * recursively checking if the resulting object is used as a base
745- * for some more deltas.
746- */
747759 if (verbose )
748760 progress = start_progress ("Resolving deltas" , nr_deltas );
749761 for (i = 0 ; i < nr_objects ; i ++ ) {
750762 struct object_entry * obj = & objects [i ];
751- struct base_data * base_obj = alloc_base_data ();
752763
753764 if (is_delta_type (obj -> type ))
754765 continue ;
755- base_obj -> obj = obj ;
756- base_obj -> data = NULL ;
757- find_unresolved_deltas (base_obj );
766+ resolve_base (obj );
758767 display_progress (progress , nr_resolved_deltas );
759768 }
760769}
761770
771+ /*
772+ * Third pass:
773+ * - append objects to convert thin pack to full pack if required
774+ * - write the final 20-byte SHA-1
775+ */
776+ static void fix_unresolved_deltas (struct sha1file * f , int nr_unresolved );
777+ static void conclude_pack (int fix_thin_pack , const char * curr_pack , unsigned char * pack_sha1 )
778+ {
779+ if (nr_deltas == nr_resolved_deltas ) {
780+ stop_progress (& progress );
781+ /* Flush remaining pack final 20-byte SHA1. */
782+ flush ();
783+ return ;
784+ }
785+
786+ if (fix_thin_pack ) {
787+ struct sha1file * f ;
788+ unsigned char read_sha1 [20 ], tail_sha1 [20 ];
789+ char msg [48 ];
790+ int nr_unresolved = nr_deltas - nr_resolved_deltas ;
791+ int nr_objects_initial = nr_objects ;
792+ if (nr_unresolved <= 0 )
793+ die ("confusion beyond insanity" );
794+ objects = xrealloc (objects ,
795+ (nr_objects + nr_unresolved + 1 )
796+ * sizeof (* objects ));
797+ f = sha1fd (output_fd , curr_pack );
798+ fix_unresolved_deltas (f , nr_unresolved );
799+ sprintf (msg , "completed with %d local objects" ,
800+ nr_objects - nr_objects_initial );
801+ stop_progress_msg (& progress , msg );
802+ sha1close (f , tail_sha1 , 0 );
803+ hashcpy (read_sha1 , pack_sha1 );
804+ fixup_pack_header_footer (output_fd , pack_sha1 ,
805+ curr_pack , nr_objects ,
806+ read_sha1 , consumed_bytes - 20 );
807+ if (hashcmp (read_sha1 , tail_sha1 ) != 0 )
808+ die ("Unexpected tail checksum for %s "
809+ "(disk corruption?)" , curr_pack );
810+ }
811+ if (nr_deltas != nr_resolved_deltas )
812+ die ("pack has %d unresolved deltas" ,
813+ nr_deltas - nr_resolved_deltas );
814+ }
815+
762816static int write_compressed (struct sha1file * f , void * in , unsigned int size )
763817{
764818 git_zstream stream ;
@@ -1196,40 +1250,8 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix)
11961250 objects = xcalloc (nr_objects + 1 , sizeof (struct object_entry ));
11971251 deltas = xcalloc (nr_objects , sizeof (struct delta_entry ));
11981252 parse_pack_objects (pack_sha1 );
1199- if (nr_deltas == nr_resolved_deltas ) {
1200- stop_progress (& progress );
1201- /* Flush remaining pack final 20-byte SHA1. */
1202- flush ();
1203- } else {
1204- if (fix_thin_pack ) {
1205- struct sha1file * f ;
1206- unsigned char read_sha1 [20 ], tail_sha1 [20 ];
1207- char msg [48 ];
1208- int nr_unresolved = nr_deltas - nr_resolved_deltas ;
1209- int nr_objects_initial = nr_objects ;
1210- if (nr_unresolved <= 0 )
1211- die ("confusion beyond insanity" );
1212- objects = xrealloc (objects ,
1213- (nr_objects + nr_unresolved + 1 )
1214- * sizeof (* objects ));
1215- f = sha1fd (output_fd , curr_pack );
1216- fix_unresolved_deltas (f , nr_unresolved );
1217- sprintf (msg , "completed with %d local objects" ,
1218- nr_objects - nr_objects_initial );
1219- stop_progress_msg (& progress , msg );
1220- sha1close (f , tail_sha1 , 0 );
1221- hashcpy (read_sha1 , pack_sha1 );
1222- fixup_pack_header_footer (output_fd , pack_sha1 ,
1223- curr_pack , nr_objects ,
1224- read_sha1 , consumed_bytes - 20 );
1225- if (hashcmp (read_sha1 , tail_sha1 ) != 0 )
1226- die ("Unexpected tail checksum for %s "
1227- "(disk corruption?)" , curr_pack );
1228- }
1229- if (nr_deltas != nr_resolved_deltas )
1230- die ("pack has %d unresolved deltas" ,
1231- nr_deltas - nr_resolved_deltas );
1232- }
1253+ resolve_deltas ();
1254+ conclude_pack (fix_thin_pack , curr_pack , pack_sha1 );
12331255 free (deltas );
12341256 if (strict )
12351257 check_objects ();
0 commit comments