Skip to content

Commit d2f97bd

Browse files
committed
midx: read objects from multi-pack-index
Signed-off-by: Derrick Stolee <[email protected]>
1 parent 4cd807e commit d2f97bd

File tree

4 files changed

+100
-2
lines changed

4 files changed

+100
-2
lines changed

midx.c

Lines changed: 90 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
#include "lockfile.h"
55
#include "packfile.h"
66
#include "object-store.h"
7-
#include "packfile.h"
7+
#include "sha1-lookup.h"
88
#include "midx.h"
99

1010
#define MIDX_SIGNATURE 0x4d494458 /* "MIDX" */
@@ -152,6 +152,7 @@ struct multi_pack_index *load_multi_pack_index(const char *object_dir)
152152
m->num_objects = ntohl(m->chunk_oid_fanout[255]);
153153

154154
m->pack_names = xcalloc(m->num_packs, sizeof(*m->pack_names));
155+
m->packs = xcalloc(m->num_packs, sizeof(*m->packs));
155156

156157
cur_pack_name = (const char *)m->chunk_pack_names;
157158
for (i = 0; i < m->num_packs; i++) {
@@ -180,6 +181,94 @@ struct multi_pack_index *load_multi_pack_index(const char *object_dir)
180181
return NULL;
181182
}
182183

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+
183272
int prepare_multi_pack_index_one(struct repository *r, const char *object_dir)
184273
{
185274
struct multi_pack_index *m = r->objects->multi_pack_index;

midx.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
struct multi_pack_index;
77

88
struct multi_pack_index *load_multi_pack_index(const char *object_dir);
9+
int bsearch_midx(const struct object_id *oid, struct multi_pack_index *m, uint32_t *result);
10+
int fill_midx_entry(const struct object_id *oid, struct pack_entry *e, struct multi_pack_index *m);
911
int prepare_multi_pack_index_one(struct repository *r, const char *object_dir);
1012

1113
int write_midx_file(const char *object_dir);

object-store.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ struct multi_pack_index {
106106
const unsigned char *chunk_large_offsets;
107107

108108
const char **pack_names;
109+
struct packed_git **packs;
109110
char object_dir[FLEX_ARRAY];
110111
};
111112

packfile.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1902,11 +1902,17 @@ static int fill_pack_entry(const struct object_id *oid,
19021902
int find_pack_entry(struct repository *r, const struct object_id *oid, struct pack_entry *e)
19031903
{
19041904
struct list_head *pos;
1905+
struct multi_pack_index *m;
19051906

19061907
prepare_packed_git(r);
1907-
if (!r->objects->packed_git)
1908+
if (!r->objects->packed_git && !r->objects->multi_pack_index)
19081909
return 0;
19091910

1911+
for (m = r->objects->multi_pack_index; m; m = m->next) {
1912+
if (fill_midx_entry(oid, e, m))
1913+
return 1;
1914+
}
1915+
19101916
list_for_each(pos, &r->objects->packed_git_mru) {
19111917
struct packed_git *p = list_entry(pos, struct packed_git, mru);
19121918
if (fill_pack_entry(oid, e, p)) {

0 commit comments

Comments
 (0)