|
4 | 4 | #include "lockfile.h"
|
5 | 5 | #include "packfile.h"
|
6 | 6 | #include "object-store.h"
|
7 |
| -#include "packfile.h" |
| 7 | +#include "sha1-lookup.h" |
8 | 8 | #include "midx.h"
|
9 | 9 |
|
10 | 10 | #define MIDX_SIGNATURE 0x4d494458 /* "MIDX" */
|
@@ -152,6 +152,7 @@ struct multi_pack_index *load_multi_pack_index(const char *object_dir)
|
152 | 152 | m->num_objects = ntohl(m->chunk_oid_fanout[255]);
|
153 | 153 |
|
154 | 154 | m->pack_names = xcalloc(m->num_packs, sizeof(*m->pack_names));
|
| 155 | + m->packs = xcalloc(m->num_packs, sizeof(*m->packs)); |
155 | 156 |
|
156 | 157 | cur_pack_name = (const char *)m->chunk_pack_names;
|
157 | 158 | for (i = 0; i < m->num_packs; i++) {
|
@@ -180,6 +181,94 @@ struct multi_pack_index *load_multi_pack_index(const char *object_dir)
|
180 | 181 | return NULL;
|
181 | 182 | }
|
182 | 183 |
|
| 184 | +static int prepare_midx_pack(struct multi_pack_index *m, uint32_t pack_int_id) |
| 185 | +{ |
| 186 | + struct strbuf pack_name = STRBUF_INIT; |
| 187 | + |
| 188 | + if (pack_int_id >= m->num_packs) |
| 189 | + BUG("bad pack-int-id"); |
| 190 | + |
| 191 | + if (m->packs[pack_int_id]) |
| 192 | + return 0; |
| 193 | + |
| 194 | + strbuf_addf(&pack_name, "%s/pack/%s", m->object_dir, |
| 195 | + m->pack_names[pack_int_id]); |
| 196 | + |
| 197 | + m->packs[pack_int_id] = add_packed_git(pack_name.buf, pack_name.len, 1); |
| 198 | + strbuf_release(&pack_name); |
| 199 | + return !m->packs[pack_int_id]; |
| 200 | +} |
| 201 | + |
| 202 | +int bsearch_midx(const struct object_id *oid, struct multi_pack_index *m, uint32_t *result) |
| 203 | +{ |
| 204 | + return bsearch_hash(oid->hash, m->chunk_oid_fanout, m->chunk_oid_lookup, |
| 205 | + MIDX_HASH_LEN, result); |
| 206 | +} |
| 207 | + |
| 208 | +static off_t nth_midxed_offset(struct multi_pack_index *m, uint32_t pos) |
| 209 | +{ |
| 210 | + const unsigned char *offset_data; |
| 211 | + uint32_t offset32; |
| 212 | + |
| 213 | + offset_data = m->chunk_object_offsets + pos * MIDX_CHUNK_OFFSET_WIDTH; |
| 214 | + offset32 = get_be32(offset_data + sizeof(uint32_t)); |
| 215 | + |
| 216 | + if (m->chunk_large_offsets && offset32 & MIDX_LARGE_OFFSET_NEEDED) { |
| 217 | + if (sizeof(offset32) < sizeof(uint64_t)) |
| 218 | + die(_("multi-pack-index stores a 64-bit offset, but off_t is too small")); |
| 219 | + |
| 220 | + offset32 ^= MIDX_LARGE_OFFSET_NEEDED; |
| 221 | + return get_be64(m->chunk_large_offsets + sizeof(uint64_t) * offset32); |
| 222 | + } |
| 223 | + |
| 224 | + return offset32; |
| 225 | +} |
| 226 | + |
| 227 | +static uint32_t nth_midxed_pack_int_id(struct multi_pack_index *m, uint32_t pos) |
| 228 | +{ |
| 229 | + return get_be32(m->chunk_object_offsets + pos * MIDX_CHUNK_OFFSET_WIDTH); |
| 230 | +} |
| 231 | + |
| 232 | +static int nth_midxed_pack_entry(struct multi_pack_index *m, struct pack_entry *e, uint32_t pos) |
| 233 | +{ |
| 234 | + uint32_t pack_int_id; |
| 235 | + struct packed_git *p; |
| 236 | + |
| 237 | + if (pos >= m->num_objects) |
| 238 | + return 0; |
| 239 | + |
| 240 | + pack_int_id = nth_midxed_pack_int_id(m, pos); |
| 241 | + |
| 242 | + if (prepare_midx_pack(m, pack_int_id)) |
| 243 | + die(_("error preparing packfile from multi-pack-index")); |
| 244 | + p = m->packs[pack_int_id]; |
| 245 | + |
| 246 | + /* |
| 247 | + * We are about to tell the caller where they can locate the |
| 248 | + * requested object. We better make sure the packfile is |
| 249 | + * still here and can be accessed before supplying that |
| 250 | + * answer, as it may have been deleted since the MIDX was |
| 251 | + * loaded! |
| 252 | + */ |
| 253 | + if (!is_pack_valid(p)) |
| 254 | + return 0; |
| 255 | + |
| 256 | + e->offset = nth_midxed_offset(m, pos); |
| 257 | + e->p = p; |
| 258 | + |
| 259 | + return 1; |
| 260 | +} |
| 261 | + |
| 262 | +int fill_midx_entry(const struct object_id *oid, struct pack_entry *e, struct multi_pack_index *m) |
| 263 | +{ |
| 264 | + uint32_t pos; |
| 265 | + |
| 266 | + if (!bsearch_midx(oid, m, &pos)) |
| 267 | + return 0; |
| 268 | + |
| 269 | + return nth_midxed_pack_entry(m, e, pos); |
| 270 | +} |
| 271 | + |
183 | 272 | int prepare_multi_pack_index_one(struct repository *r, const char *object_dir)
|
184 | 273 | {
|
185 | 274 | struct multi_pack_index *m = r->objects->multi_pack_index;
|
|
0 commit comments