index-pack: restructure pack processing into three main functions

The second pass in parse_pack_objects() are split into resolve_deltas(). The final phase, fixing thin pack or just seal the pack, is now in conclude_pack() function. Main pack processing is now a sequence of these functions: - parse_pack_objects() reads through the input pack - resolve_deltas() makes sure all deltas can be resolved - conclude_pack() seals the output pack - write_idx_file() writes companion index file - final() moves the pack/index to proper place Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Nguyễn Thái Ngọc Duy committed May 6, 2012 at 19:31 UTC 5272f75587abb4cb396059ecbf1a6130bb2e69d3
1 file changed +75 -53
builtin/index-pack.c
+75 -53
@@ -682,19 +682,26 @@ static int compare_delta_entry(const void *a, const void *b)
682 objects[delta_b->obj_no].type);
683 }
684
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 + */
699 static void parse_pack_objects(unsigned char *sha1)
700 {
701 int i;
702 struct delta_entry *delta = deltas;
703 struct stat st;
704
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 - */
705 if (verbose)
706 progress = start_progress(
707 from_stdin ? "Receiving objects" : "Indexing objects",
@@ -728,6 +735,19 @@ static void parse_pack_objects(unsigned char *sha1)
735 if (S_ISREG(st.st_mode) &&
736 lseek(input_fd, 0, SEEK_CUR) - input_len != st.st_size)
737 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;
751
752 if (!nr_deltas)
753 return;
@@ -736,29 +756,63 @@ static void parse_pack_objects(unsigned char *sha1)
756 qsort(deltas, nr_deltas, sizeof(struct delta_entry),
757 compare_delta_entry);
758
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 - */
759 if (verbose)
760 progress = start_progress("Resolving deltas", nr_deltas);
761 for (i = 0; i < nr_objects; i++) {
762 struct object_entry *obj = &objects[i];
751 - struct base_data *base_obj = alloc_base_data();
763
764 if (is_delta_type(obj->type))
765 continue;
755 - base_obj->obj = obj;
756 - base_obj->data = NULL;
757 - find_unresolved_deltas(base_obj);
766 + resolve_base(obj);
767 display_progress(progress, nr_resolved_deltas);
768 }
769 }
770
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 +
816 static int write_compressed(struct sha1file *f, void *in, unsigned int size)
817 {
818 git_zstream stream;
@@ -1196,40 +1250,8 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix)
1250 objects = xcalloc(nr_objects + 1, sizeof(struct object_entry));
1251 deltas = xcalloc(nr_objects, sizeof(struct delta_entry));
1252 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);
1255 free(deltas);
1256 if (strict)
1257 check_objects();