28
int base_object_no;
29
};
30
31
-union delta_base {
32
- unsigned char sha1[20];
33
- off_t offset;
34
-};
35
-
31
struct base_data {
32
struct base_data *base;
33
struct base_data *child;
47
int pack_fd;
48
};
49
55
-/*
56
- * Even if sizeof(union delta_base) == 24 on 64-bit archs, we really want
57
- * to memcmp() only the first 20 bytes.
58
- */
59
-#define UNION_BASE_SZ 20
60
-
50
#define FLAG_LINK (1u<<20)
51
#define FLAG_CHECKED (1u<<21)
52
64
-struct delta_entry {
65
- union delta_base base;
53
+struct ofs_delta_entry {
54
+ off_t offset;
55
+ int obj_no;
56
+};
57
+
58
+struct ref_delta_entry {
59
+ unsigned char sha1[20];
60
int obj_no;
61
};
62
63
static struct object_entry *objects;
64
static struct object_stat *obj_stat;
71
-static struct delta_entry *deltas;
65
+static struct ofs_delta_entry *ofs_deltas;
66
+static struct ref_delta_entry *ref_deltas;
67
static struct thread_local nothread_data;
68
static int nr_objects;
74
-static int nr_deltas;
69
+static int nr_ofs_deltas;
70
+static int nr_ref_deltas;
71
+static int ref_deltas_alloc;
72
static int nr_resolved_deltas;
73
static int nr_threads;
74
477
}
478
479
static void *unpack_raw_entry(struct object_entry *obj,
483
- union delta_base *delta_base,
480
+ off_t *ofs_offset,
481
+ unsigned char *ref_sha1,
482
unsigned char *sha1)
483
{
484
unsigned char *p;
507
508
switch (obj->type) {
509
case OBJ_REF_DELTA:
512
- hashcpy(delta_base->sha1, fill(20));
510
+ hashcpy(ref_sha1, fill(20));
511
use(20);
512
break;
513
case OBJ_OFS_DELTA:
516
- memset(delta_base, 0, sizeof(*delta_base));
514
p = fill(1);
515
c = *p;
516
use(1);
524
use(1);
525
base_offset = (base_offset << 7) + (c & 127);
526
}
530
- delta_base->offset = obj->idx.offset - base_offset;
531
- if (delta_base->offset <= 0 || delta_base->offset >= obj->idx.offset)
527
+ *ofs_offset = obj->idx.offset - base_offset;
528
+ if (*ofs_offset <= 0 || *ofs_offset >= obj->idx.offset)
529
bad_object(obj->idx.offset, _("delta base offset is out of bound"));
530
break;
531
case OBJ_COMMIT:
609
return unpack_data(obj, NULL, NULL);
610
}
611
615
-static int compare_delta_bases(const union delta_base *base1,
616
- const union delta_base *base2,
617
- enum object_type type1,
618
- enum object_type type2)
612
+static int compare_ofs_delta_bases(off_t offset1, off_t offset2,
613
+ enum object_type type1,
614
+ enum object_type type2)
615
{
616
int cmp = type1 - type2;
617
if (cmp)
618
return cmp;
623
- return memcmp(base1, base2, UNION_BASE_SZ);
619
+ return offset1 - offset2;
620
}
621
626
-static int find_delta(const union delta_base *base, enum object_type type)
622
+static int find_ofs_delta(const off_t offset, enum object_type type)
623
{
628
- int first = 0, last = nr_deltas;
629
-
630
- while (first < last) {
631
- int next = (first + last) / 2;
632
- struct delta_entry *delta = &deltas[next];
633
- int cmp;
634
-
635
- cmp = compare_delta_bases(base, &delta->base,
636
- type, objects[delta->obj_no].type);
637
- if (!cmp)
638
- return next;
639
- if (cmp < 0) {
640
- last = next;
641
- continue;
642
- }
643
- first = next+1;
644
- }
645
- return -first-1;
624
+ int first = 0, last = nr_ofs_deltas;
625
+
626
+ while (first < last) {
627
+ int next = (first + last) / 2;
628
+ struct ofs_delta_entry *delta = &ofs_deltas[next];
629
+ int cmp;
630
+
631
+ cmp = compare_ofs_delta_bases(offset, delta->offset,
632
+ type, objects[delta->obj_no].type);
633
+ if (!cmp)
634
+ return next;
635
+ if (cmp < 0) {
636
+ last = next;
637
+ continue;
638
+ }
639
+ first = next+1;
640
+ }
641
+ return -first-1;
642
}
643
648
-static void find_delta_children(const union delta_base *base,
649
- int *first_index, int *last_index,
650
- enum object_type type)
644
+static void find_ofs_delta_children(off_t offset,
645
+ int *first_index, int *last_index,
646
+ enum object_type type)
647
{
652
- int first = find_delta(base, type);
648
+ int first = find_ofs_delta(offset, type);
649
int last = first;
654
- int end = nr_deltas - 1;
650
+ int end = nr_ofs_deltas - 1;
651
652
if (first < 0) {
653
*first_index = 0;
654
*last_index = -1;
655
return;
656
}
661
- while (first > 0 && !memcmp(&deltas[first - 1].base, base, UNION_BASE_SZ))
657
+ while (first > 0 && ofs_deltas[first - 1].offset == offset)
658
--first;
663
- while (last < end && !memcmp(&deltas[last + 1].base, base, UNION_BASE_SZ))
659
+ while (last < end && ofs_deltas[last + 1].offset == offset)
660
+ ++last;
661
+ *first_index = first;
662
+ *last_index = last;
663
+}
664
+
665
+static int compare_ref_delta_bases(const unsigned char *sha1,
666
+ const unsigned char *sha2,
667
+ enum object_type type1,
668
+ enum object_type type2)
669
+{
670
+ int cmp = type1 - type2;
671
+ if (cmp)
672
+ return cmp;
673
+ return hashcmp(sha1, sha2);
674
+}
675
+
676
+static int find_ref_delta(const unsigned char *sha1, enum object_type type)
677
+{
678
+ int first = 0, last = nr_ref_deltas;
679
+
680
+ while (first < last) {
681
+ int next = (first + last) / 2;
682
+ struct ref_delta_entry *delta = &ref_deltas[next];
683
+ int cmp;
684
+
685
+ cmp = compare_ref_delta_bases(sha1, delta->sha1,
686
+ type, objects[delta->obj_no].type);
687
+ if (!cmp)
688
+ return next;
689
+ if (cmp < 0) {
690
+ last = next;
691
+ continue;
692
+ }
693
+ first = next+1;
694
+ }
695
+ return -first-1;
696
+}
697
+
698
+static void find_ref_delta_children(const unsigned char *sha1,
699
+ int *first_index, int *last_index,
700
+ enum object_type type)
701
+{
702
+ int first = find_ref_delta(sha1, type);
703
+ int last = first;
704
+ int end = nr_ref_deltas - 1;
705
+
706
+ if (first < 0) {
707
+ *first_index = 0;
708
+ *last_index = -1;
709
+ return;
710
+ }
711
+ while (first > 0 && !hashcmp(ref_deltas[first - 1].sha1, sha1))
712
+ --first;
713
+ while (last < end && !hashcmp(ref_deltas[last + 1].sha1, sha1))
714
++last;
715
*first_index = first;
716
*last_index = last;
977
struct base_data *prev_base)
978
{
979
if (base->ref_last == -1 && base->ofs_last == -1) {
930
- union delta_base base_spec;
931
-
932
- hashcpy(base_spec.sha1, base->obj->idx.sha1);
933
- find_delta_children(&base_spec,
934
- &base->ref_first, &base->ref_last, OBJ_REF_DELTA);
980
+ find_ref_delta_children(base->obj->idx.sha1,
981
+ &base->ref_first, &base->ref_last,
982
+ OBJ_REF_DELTA);
983
936
- memset(&base_spec, 0, sizeof(base_spec));
937
- base_spec.offset = base->obj->idx.offset;
938
- find_delta_children(&base_spec,
939
- &base->ofs_first, &base->ofs_last, OBJ_OFS_DELTA);
984
+ find_ofs_delta_children(base->obj->idx.offset,
985
+ &base->ofs_first, &base->ofs_last,
986
+ OBJ_OFS_DELTA);
987
988
if (base->ref_last == -1 && base->ofs_last == -1) {
989
free(base->data);
994
}
995
996
if (base->ref_first <= base->ref_last) {
950
- struct object_entry *child = objects + deltas[base->ref_first].obj_no;
997
+ struct object_entry *child = objects + ref_deltas[base->ref_first].obj_no;
998
struct base_data *result = alloc_base_data();
999
1000
if (!compare_and_swap_type(&child->real_type, OBJ_REF_DELTA,
1010
}
1011
1012
if (base->ofs_first <= base->ofs_last) {
966
- struct object_entry *child = objects + deltas[base->ofs_first].obj_no;
1013
+ struct object_entry *child = objects + ofs_deltas[base->ofs_first].obj_no;
1014
struct base_data *result = alloc_base_data();
1015
1016
assert(child->real_type == OBJ_OFS_DELTA);
1046
}
1047
}
1048
1002
-static int compare_delta_entry(const void *a, const void *b)
1049
+static int compare_ofs_delta_entry(const void *a, const void *b)
1050
+{
1051
+ const struct ofs_delta_entry *delta_a = a;
1052
+ const struct ofs_delta_entry *delta_b = b;
1053
+
1054
+ return delta_a->offset - delta_b->offset;
1055
+}
1056
+
1057
+static int compare_ref_delta_entry(const void *a, const void *b)
1058
{
1004
- const struct delta_entry *delta_a = a;
1005
- const struct delta_entry *delta_b = b;
1059
+ const struct ref_delta_entry *delta_a = a;
1060
+ const struct ref_delta_entry *delta_b = b;
1061
1007
- /* group by type (ref vs ofs) and then by value (sha-1 or offset) */
1008
- return compare_delta_bases(&delta_a->base, &delta_b->base,
1009
- objects[delta_a->obj_no].type,
1010
- objects[delta_b->obj_no].type);
1062
+ return hashcmp(delta_a->sha1, delta_b->sha1);
1063
}
1064
1065
static void resolve_base(struct object_entry *obj)
1105
static void parse_pack_objects(unsigned char *sha1)
1106
{
1107
int i, nr_delays = 0;
1056
- struct delta_entry *delta = deltas;
1108
+ struct ofs_delta_entry *ofs_delta = ofs_deltas;
1109
+ unsigned char ref_delta_sha1[20];
1110
struct stat st;
1111
1112
if (verbose)
1115
nr_objects);
1116
for (i = 0; i < nr_objects; i++) {
1117
struct object_entry *obj = &objects[i];
1065
- void *data = unpack_raw_entry(obj, &delta->base, obj->idx.sha1);
1118
+ void *data = unpack_raw_entry(obj, &ofs_delta->offset,
1119
+ ref_delta_sha1, obj->idx.sha1);
1120
obj->real_type = obj->type;
1067
- if (is_delta_type(obj->type)) {
1068
- nr_deltas++;
1069
- delta->obj_no = i;
1070
- delta++;
1121
+ if (obj->type == OBJ_OFS_DELTA) {
1122
+ nr_ofs_deltas++;
1123
+ ofs_delta->obj_no = i;
1124
+ ofs_delta++;
1125
+ } else if (obj->type == OBJ_REF_DELTA) {
1126
+ ALLOC_GROW(ref_deltas, nr_ref_deltas + 1, ref_deltas_alloc);
1127
+ hashcpy(ref_deltas[nr_ref_deltas].sha1, ref_delta_sha1);
1128
+ ref_deltas[nr_ref_deltas].obj_no = i;
1129
+ nr_ref_deltas++;
1130
} else if (!data) {
1131
/* large blobs, check later */
1132
obj->real_type = OBJ_BAD;
1177
{
1178
int i;
1179
1121
- if (!nr_deltas)
1180
+ if (!nr_ofs_deltas && !nr_ref_deltas)
1181
return;
1182
1183
/* Sort deltas by base SHA1/offset for fast searching */
1125
- qsort(deltas, nr_deltas, sizeof(struct delta_entry),
1126
- compare_delta_entry);
1184
+ qsort(ofs_deltas, nr_ofs_deltas, sizeof(struct ofs_delta_entry),
1185
+ compare_ofs_delta_entry);
1186
+ qsort(ref_deltas, nr_ref_deltas, sizeof(struct ref_delta_entry),
1187
+ compare_ref_delta_entry);
1188
1189
if (verbose)
1129
- progress = start_progress(_("Resolving deltas"), nr_deltas);
1190
+ progress = start_progress(_("Resolving deltas"),
1191
+ nr_ref_deltas + nr_ofs_deltas);
1192
1193
#ifndef NO_PTHREADS
1194
nr_dispatched = 0;
1226
static void fix_unresolved_deltas(struct sha1file *f, int nr_unresolved);
1227
static void conclude_pack(int fix_thin_pack, const char *curr_pack, unsigned char *pack_sha1)
1228
{
1167
- if (nr_deltas == nr_resolved_deltas) {
1229
+ if (nr_ref_deltas + nr_ofs_deltas == nr_resolved_deltas) {
1230
stop_progress(&progress);
1231
/* Flush remaining pack final 20-byte SHA1. */
1232
flush();
1237
struct sha1file *f;
1238
unsigned char read_sha1[20], tail_sha1[20];
1239
struct strbuf msg = STRBUF_INIT;
1178
- int nr_unresolved = nr_deltas - nr_resolved_deltas;
1240
+ int nr_unresolved = nr_ofs_deltas + nr_ref_deltas - nr_resolved_deltas;
1241
int nr_objects_initial = nr_objects;
1242
if (nr_unresolved <= 0)
1243
die(_("confusion beyond insanity"));
1259
die(_("Unexpected tail checksum for %s "
1260
"(disk corruption?)"), curr_pack);
1261
}
1200
- if (nr_deltas != nr_resolved_deltas)
1262
+ if (nr_ofs_deltas + nr_ref_deltas != nr_resolved_deltas)
1263
die(Q_("pack has %d unresolved delta",
1264
"pack has %d unresolved deltas",
1203
- nr_deltas - nr_resolved_deltas),
1204
- nr_deltas - nr_resolved_deltas);
1265
+ nr_ofs_deltas + nr_ref_deltas - nr_resolved_deltas),
1266
+ nr_ofs_deltas + nr_ref_deltas - nr_resolved_deltas);
1267
}
1268
1269
static int write_compressed(struct sha1file *f, void *in, unsigned int size)
1323
1324
static int delta_pos_compare(const void *_a, const void *_b)
1325
{
1264
- struct delta_entry *a = *(struct delta_entry **)_a;
1265
- struct delta_entry *b = *(struct delta_entry **)_b;
1326
+ struct ref_delta_entry *a = *(struct ref_delta_entry **)_a;
1327
+ struct ref_delta_entry *b = *(struct ref_delta_entry **)_b;
1328
return a->obj_no - b->obj_no;
1329
}
1330
1331
static void fix_unresolved_deltas(struct sha1file *f, int nr_unresolved)
1332
{
1271
- struct delta_entry **sorted_by_pos;
1333
+ struct ref_delta_entry **sorted_by_pos;
1334
int i, n = 0;
1335
1336
/*
1344
* resolving deltas in the same order as their position in the pack.
1345
*/
1346
sorted_by_pos = xmalloc(nr_unresolved * sizeof(*sorted_by_pos));
1285
- for (i = 0; i < nr_deltas; i++) {
1286
- if (objects[deltas[i].obj_no].real_type != OBJ_REF_DELTA)
1287
- continue;
1288
- sorted_by_pos[n++] = &deltas[i];
1289
- }
1347
+ for (i = 0; i < nr_ref_deltas; i++)
1348
+ sorted_by_pos[n++] = &ref_deltas[i];
1349
qsort(sorted_by_pos, n, sizeof(*sorted_by_pos), delta_pos_compare);
1350
1351
for (i = 0; i < n; i++) {
1293
- struct delta_entry *d = sorted_by_pos[i];
1352
+ struct ref_delta_entry *d = sorted_by_pos[i];
1353
enum object_type type;
1354
struct base_data *base_obj = alloc_base_data();
1355
1356
if (objects[d->obj_no].real_type != OBJ_REF_DELTA)
1357
continue;
1299
- base_obj->data = read_sha1_file(d->base.sha1, &type, &base_obj->size);
1358
+ base_obj->data = read_sha1_file(d->sha1, &type, &base_obj->size);
1359
if (!base_obj->data)
1360
continue;
1361
1303
- if (check_sha1_signature(d->base.sha1, base_obj->data,
1362
+ if (check_sha1_signature(d->sha1, base_obj->data,
1363
base_obj->size, typename(type)))
1305
- die(_("local object %s is corrupt"), sha1_to_hex(d->base.sha1));
1306
- base_obj->obj = append_obj_to_pack(f, d->base.sha1,
1364
+ die(_("local object %s is corrupt"), sha1_to_hex(d->sha1));
1365
+ base_obj->obj = append_obj_to_pack(f, d->sha1,
1366
base_obj->data, base_obj->size, type);
1367
find_unresolved_deltas(base_obj);
1368
display_progress(progress, nr_resolved_deltas);
1554
1555
static void show_pack_info(int stat_only)
1556
{
1498
- int i, baseobjects = nr_objects - nr_deltas;
1557
+ int i, baseobjects = nr_objects - nr_ref_deltas - nr_ofs_deltas;
1558
unsigned long *chain_histogram = NULL;
1559
1560
if (deepest_delta)
1739
objects = xcalloc(nr_objects + 1, sizeof(struct object_entry));
1740
if (show_stat)
1741
obj_stat = xcalloc(nr_objects + 1, sizeof(struct object_stat));
1683
- deltas = xcalloc(nr_objects, sizeof(struct delta_entry));
1742
+ ofs_deltas = xcalloc(nr_objects, sizeof(struct ofs_delta_entry));
1743
parse_pack_objects(pack_sha1);
1744
resolve_deltas();
1745
conclude_pack(fix_thin_pack, curr_pack, pack_sha1);
1687
- free(deltas);
1746
+ free(ofs_deltas);
1747
+ free(ref_deltas);
1748
if (strict)
1749
foreign_nr = check_objects();
1750