10
#include "dir.h"
11
#include "packfile.h"
12
#include "delta.h"
13
+#include "ewah/ewok.h"
14
#include "hash-lookup.h"
15
#include "commit.h"
16
#include "object.h"
1078
return -1;
1079
}
1080
1081
+/*
1082
+ * Search duplicate representations for a chain ending in a full object.
1083
+ * Representations of the same OID are interchangeable as delta bases.
1084
+ *
1085
+ * Each path entry is the search frame for one OID. It walks that OID's
1086
+ * contiguous .idx entries and retains the chosen entry's .pack offset
1087
+ * for replay.
1088
+ */
1089
+struct delta_path_entry {
1090
+ off_t selected_offset; /* zero until a candidate is selected */
1091
+ uint32_t next; /* index position of the next candidate */
1092
+ uint32_t remaining; /* total number of candidates remaining */
1093
+};
1094
+
1095
+struct delta_path {
1096
+ struct delta_path_entry *entries;
1097
+ size_t nr, alloc;
1098
+};
1099
+
1100
+static int push_oid_group(struct packed_git *p,
1101
+ const struct object_id *oid,
1102
+ struct bitmap *visited, struct delta_path *path)
1103
+{
1104
+ struct object_id candidate;
1105
+ struct delta_path_entry *entry;
1106
+ uint32_t first_index_pos, group_index_pos, index_pos;
1107
+
1108
+ /*
1109
+ * Determine the range of index positions referring to duplicate
1110
+ * copies of the given object.
1111
+ *
1112
+ * Any position within that range is OK, since we will determine
1113
+ * the exact range below.
1114
+ */
1115
+ if (!bsearch_pack(oid, p, &group_index_pos))
1116
+ return 0;
1117
+ if (bitmap_get(visited, group_index_pos))
1118
+ return 0;
1119
+
1120
+ first_index_pos = group_index_pos;
1121
+ while (first_index_pos > 0) {
1122
+ if (nth_packed_object_id(&candidate, p, first_index_pos - 1) < 0)
1123
+ return -1;
1124
+ if (!oideq(&candidate, oid))
1125
+ break;
1126
+ first_index_pos--;
1127
+ }
1128
+
1129
+ for (index_pos = first_index_pos; index_pos < p->num_objects; index_pos++) {
1130
+ if (nth_packed_object_id(&candidate, p, index_pos) < 0)
1131
+ return -1;
1132
+ if (!oideq(&candidate, oid))
1133
+ break;
1134
+ }
1135
+
1136
+ bitmap_set(visited, group_index_pos);
1137
+
1138
+ ALLOC_GROW(path->entries, path->nr + 1, path->alloc);
1139
+ entry = &path->entries[path->nr++];
1140
+ entry->selected_offset = 0;
1141
+ entry->next = first_index_pos;
1142
+ entry->remaining = index_pos - first_index_pos;
1143
+
1144
+ return 1;
1145
+}
1146
+
1147
+static enum object_type find_delta_path(struct packed_git *p,
1148
+ struct pack_window **w_curs,
1149
+ off_t offset,
1150
+ struct delta_path *path)
1151
+{
1152
+ struct object_id oid;
1153
+ uint32_t pack_pos;
1154
+ struct bitmap *visited;
1155
+ enum object_type result = OBJ_BAD;
1156
+
1157
+ if (offset_to_pack_pos(p, offset, &pack_pos) < 0)
1158
+ return OBJ_BAD;
1159
+ if (nth_packed_object_id(&oid, p, pack_pos_to_index(p, pack_pos)) < 0)
1160
+ return OBJ_BAD;
1161
+
1162
+ visited = bitmap_new();
1163
+ if (push_oid_group(p, &oid, visited, path) != 1)
1164
+ goto done;
1165
+
1166
+ /*
1167
+ * Search depth-first for a chain ending in a full object. Each frame
1168
+ * tries every representation of one OID; a delta pushes its base OID,
1169
+ * while exhausting a frame backtracks to its parent.
1170
+ */
1171
+ while (path->nr) {
1172
+ struct delta_path_entry *entry = &path->entries[path->nr - 1];
1173
+ enum object_type candidate_type;
1174
+ off_t curpos;
1175
+ size_t size;
1176
+
1177
+ /*
1178
+ * This OID has no path to a full object. Let its parent try
1179
+ * another representation; exhausting the root fails the search.
1180
+ */
1181
+ if (!entry->remaining) {
1182
+ path->nr--;
1183
+ continue;
1184
+ }
1185
+
1186
+ entry->selected_offset =
1187
+ nth_packed_object_offset(p, entry->next++);
1188
+ entry->remaining--;
1189
+ curpos = entry->selected_offset;
1190
+ candidate_type = unpack_object_header(p, w_curs, &curpos, &size);
1191
+
1192
+ /*
1193
+ * A full object terminates the chain, and its type is
1194
+ * inherited by every delta above it. A delta continues
1195
+ * at its base; any other type rejects only this
1196
+ * representation.
1197
+ */
1198
+ switch (candidate_type) {
1199
+ case OBJ_COMMIT:
1200
+ case OBJ_TREE:
1201
+ case OBJ_BLOB:
1202
+ case OBJ_TAG:
1203
+ result = candidate_type;
1204
+ goto done;
1205
+ case OBJ_OFS_DELTA:
1206
+ case OBJ_REF_DELTA:
1207
+ break;
1208
+ default:
1209
+ /*
1210
+ * A bad or unknown type rejects only this copy;
1211
+ * another representation of the same OID may
1212
+ * still work.
1213
+ */
1214
+ continue;
1215
+ }
1216
+
1217
+ /*
1218
+ * Descend to this delta's base. A malformed reference
1219
+ * or a missing or already-visited base rejects this
1220
+ * copy. A newly pushed base is examined next; an index
1221
+ * error aborts the search.
1222
+ */
1223
+ if (get_delta_base_oid(p, w_curs, curpos, &oid, candidate_type,
1224
+ entry->selected_offset))
1225
+ continue;
1226
+ if (push_oid_group(p, &oid, visited, path) < 0)
1227
+ goto done;
1228
+ }
1229
+
1230
+done:
1231
+ bitmap_free(visited);
1232
+ return result;
1233
+}
1234
+
1235
static int retry_bad_packed_offset(struct repository *r,
1236
struct packed_git *p,
1237
off_t obj_offset)
1260
{
1261
off_t small_poi_stack[POI_STACK_PREALLOC];
1262
off_t *poi_stack = small_poi_stack;
1263
+ off_t root_offset = obj_offset;
1264
int poi_stack_nr = 0, poi_stack_alloc = POI_STACK_PREALLOC;
1265
1266
while (type == OBJ_OFS_DELTA || type == OBJ_REF_DELTA) {
1267
off_t base_offset;
1268
size_t size;
1269
+
1270
+ if (poi_stack_nr > 0 && poi_stack_nr % 2 == 0 &&
1271
+ obj_offset == poi_stack[poi_stack_nr / 2]) {
1272
+ struct delta_path path = { 0 };
1273
+ /*
1274
+ * Normal lookup returned to the same pack
1275
+ * entry. Restart from the requested object
1276
+ * using alternate representations.
1277
+ */
1278
+ type = find_delta_path(p, w_curs, root_offset, &path);
1279
+ free(path.entries);
1280
+ if (type == OBJ_BAD)
1281
+ goto unwind;
1282
+ break;
1283
+ }
1284
/* Push the object we're going to leave behind */
1285
if (poi_stack_nr >= poi_stack_alloc && poi_stack == small_poi_stack) {
1286
poi_stack_alloc = alloc_nr(poi_stack_nr);
1696
{
1697
struct pack_window *w_curs = NULL;
1698
off_t curpos = obj_offset;
1699
+ off_t root_offset = obj_offset;
1700
void *data = NULL;
1701
size_t size;
1702
enum object_type type;
1703
+ struct delta_path path = { 0 };
1704
struct unpack_entry_stack_ent small_delta_stack[UNPACK_ENTRY_STACK_PREALLOC];
1705
struct unpack_entry_stack_ent *delta_stack = small_delta_stack;
1706
int delta_stack_nr = 0, delta_stack_alloc = UNPACK_ENTRY_STACK_PREALLOC;
1726
break;
1727
}
1728
1729
+ if (!path.nr &&
1730
+ delta_stack_nr > 0 && delta_stack_nr % 2 == 0 &&
1731
+ obj_offset == delta_stack[delta_stack_nr / 2].obj_offset) {
1732
+ /*
1733
+ * Normal lookup returned to the same pack
1734
+ * entry. Find an acyclic path if one exists,
1735
+ * discard this walk, and replay that path.
1736
+ */
1737
+ if (find_delta_path(p, &w_curs, root_offset,
1738
+ &path) == OBJ_BAD)
1739
+ break;
1740
+ delta_stack_nr = 0;
1741
+ curpos = obj_offset = path.entries[0].selected_offset;
1742
+ continue;
1743
+ }
1744
+
1745
if (do_check_packed_object_crc && p->index_version > 1) {
1746
uint32_t pack_pos, index_pos;
1747
off_t len;
1780
break;
1781
}
1782
1783
+ /* Use the base chosen by recovery, not the one from normal lookup. */
1784
+ if (path.nr) {
1785
+ size_t path_pos = (size_t)delta_stack_nr + 1;
1786
+
1787
+ if (path_pos >= path.nr)
1788
+ BUG("alternate delta path ends in a delta");
1789
+ base_offset = path.entries[path_pos].selected_offset;
1790
+ }
1791
+
1792
/* push object, proceed to base */
1793
if (delta_stack_nr >= delta_stack_alloc
1794
&& delta_stack == small_delta_stack) {
1929
1930
out:
1931
unuse_pack(&w_curs);
1932
+ free(path.entries);
1933
1934
if (delta_stack != small_delta_stack)
1935
free(delta_stack);