Skip to content

Commit bc5cbbe

Browse files
committed
Merge branch 'ps/read-object-info-improvements'
The object-info API has been cleaned up. * ps/read-object-info-improvements: packfile: drop repository parameter from `packed_object_info()` packfile: skip unpacking object header for disk size requests packfile: disentangle return value of `packed_object_info()` packfile: always populate pack-specific info when reading object info packfile: extend `is_delta` field to allow for "unknown" state packfile: always declare object info to be OI_PACKED object-file: always set OI_LOOSE when reading object info
2 parents d627023 + 12d3b58 commit bc5cbbe

File tree

9 files changed

+158
-79
lines changed

9 files changed

+158
-79
lines changed

builtin/cat-file.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -487,8 +487,7 @@ static void batch_object_write(const char *obj_name,
487487
data->info.sizep = &data->size;
488488

489489
if (pack)
490-
ret = packed_object_info(the_repository, pack,
491-
offset, &data->info);
490+
ret = packed_object_info(pack, offset, &data->info);
492491
else
493492
ret = odb_read_object_info_extended(the_repository->objects,
494493
&data->oid, &data->info,

builtin/pack-objects.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2417,7 +2417,7 @@ static void drop_reused_delta(struct object_entry *entry)
24172417

24182418
oi.sizep = &size;
24192419
oi.typep = &type;
2420-
if (packed_object_info(the_repository, IN_PACK(entry), entry->in_pack_offset, &oi) < 0) {
2420+
if (packed_object_info(IN_PACK(entry), entry->in_pack_offset, &oi) < 0) {
24212421
/*
24222422
* We failed to get the info from this pack for some reason;
24232423
* fall back to odb_read_object_info, which may find another copy.
@@ -3754,7 +3754,7 @@ static int add_object_entry_from_pack(const struct object_id *oid,
37543754
struct object_info oi = OBJECT_INFO_INIT;
37553755

37563756
oi.typep = &type;
3757-
if (packed_object_info(the_repository, p, ofs, &oi) < 0) {
3757+
if (packed_object_info(p, ofs, &oi) < 0) {
37583758
die(_("could not get type of object %s in pack %s"),
37593759
oid_to_hex(oid), p->pack_name);
37603760
} else if (type == OBJ_COMMIT) {

commit-graph.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1493,7 +1493,7 @@ static int add_packed_commits(const struct object_id *oid,
14931493
display_progress(ctx->progress, ++ctx->progress_done);
14941494

14951495
oi.typep = &type;
1496-
if (packed_object_info(ctx->r, pack, offset, &oi) < 0)
1496+
if (packed_object_info(pack, offset, &oi) < 0)
14971497
die(_("unable to get type of object %s"), oid_to_hex(oid));
14981498

14991499
if (type != OBJ_COMMIT)

object-file.c

Lines changed: 71 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -416,19 +416,16 @@ int odb_source_loose_read_object_info(struct odb_source *source,
416416
const struct object_id *oid,
417417
struct object_info *oi, int flags)
418418
{
419-
int status = 0;
419+
int ret;
420420
int fd;
421421
unsigned long mapsize;
422422
const char *path;
423-
void *map;
424-
git_zstream stream;
423+
void *map = NULL;
424+
git_zstream stream, *stream_to_end = NULL;
425425
char hdr[MAX_HEADER_LEN];
426426
unsigned long size_scratch;
427427
enum object_type type_scratch;
428428

429-
if (oi && oi->delta_base_oid)
430-
oidclr(oi->delta_base_oid, source->odb->repo->hash_algo);
431-
432429
/*
433430
* If we don't care about type or size, then we don't
434431
* need to look inside the object at all. Note that we
@@ -439,71 +436,101 @@ int odb_source_loose_read_object_info(struct odb_source *source,
439436
*/
440437
if (!oi || (!oi->typep && !oi->sizep && !oi->contentp)) {
441438
struct stat st;
442-
if ((!oi || !oi->disk_sizep) && (flags & OBJECT_INFO_QUICK))
443-
return quick_has_loose(source->loose, oid) ? 0 : -1;
444-
if (stat_loose_object(source->loose, oid, &st, &path) < 0)
445-
return -1;
439+
440+
if ((!oi || !oi->disk_sizep) && (flags & OBJECT_INFO_QUICK)) {
441+
ret = quick_has_loose(source->loose, oid) ? 0 : -1;
442+
goto out;
443+
}
444+
445+
if (stat_loose_object(source->loose, oid, &st, &path) < 0) {
446+
ret = -1;
447+
goto out;
448+
}
449+
446450
if (oi && oi->disk_sizep)
447451
*oi->disk_sizep = st.st_size;
448-
return 0;
452+
453+
ret = 0;
454+
goto out;
449455
}
450456

451457
fd = open_loose_object(source->loose, oid, &path);
452458
if (fd < 0) {
453459
if (errno != ENOENT)
454460
error_errno(_("unable to open loose object %s"), oid_to_hex(oid));
455-
return -1;
461+
ret = -1;
462+
goto out;
456463
}
457-
map = map_fd(fd, path, &mapsize);
458-
if (!map)
459-
return -1;
460464

461-
if (!oi->sizep)
462-
oi->sizep = &size_scratch;
463-
if (!oi->typep)
464-
oi->typep = &type_scratch;
465+
map = map_fd(fd, path, &mapsize);
466+
if (!map) {
467+
ret = -1;
468+
goto out;
469+
}
465470

466471
if (oi->disk_sizep)
467472
*oi->disk_sizep = mapsize;
468473

474+
stream_to_end = &stream;
475+
469476
switch (unpack_loose_header(&stream, map, mapsize, hdr, sizeof(hdr))) {
470477
case ULHR_OK:
471-
if (parse_loose_header(hdr, oi) < 0)
472-
status = error(_("unable to parse %s header"), oid_to_hex(oid));
473-
else if (*oi->typep < 0)
478+
if (!oi->sizep)
479+
oi->sizep = &size_scratch;
480+
if (!oi->typep)
481+
oi->typep = &type_scratch;
482+
483+
if (parse_loose_header(hdr, oi) < 0) {
484+
ret = error(_("unable to parse %s header"), oid_to_hex(oid));
485+
goto corrupt;
486+
}
487+
488+
if (*oi->typep < 0)
474489
die(_("invalid object type"));
475490

476-
if (!oi->contentp)
477-
break;
478-
*oi->contentp = unpack_loose_rest(&stream, hdr, *oi->sizep, oid);
479-
if (*oi->contentp)
480-
goto cleanup;
491+
if (oi->contentp) {
492+
*oi->contentp = unpack_loose_rest(&stream, hdr, *oi->sizep, oid);
493+
if (!*oi->contentp) {
494+
ret = -1;
495+
goto corrupt;
496+
}
497+
}
481498

482-
status = -1;
483499
break;
484500
case ULHR_BAD:
485-
status = error(_("unable to unpack %s header"),
486-
oid_to_hex(oid));
487-
break;
501+
ret = error(_("unable to unpack %s header"),
502+
oid_to_hex(oid));
503+
goto corrupt;
488504
case ULHR_TOO_LONG:
489-
status = error(_("header for %s too long, exceeds %d bytes"),
490-
oid_to_hex(oid), MAX_HEADER_LEN);
491-
break;
505+
ret = error(_("header for %s too long, exceeds %d bytes"),
506+
oid_to_hex(oid), MAX_HEADER_LEN);
507+
goto corrupt;
492508
}
493509

494-
if (status && (flags & OBJECT_INFO_DIE_IF_CORRUPT))
510+
ret = 0;
511+
512+
corrupt:
513+
if (ret && (flags & OBJECT_INFO_DIE_IF_CORRUPT))
495514
die(_("loose object %s (stored in %s) is corrupt"),
496515
oid_to_hex(oid), path);
497516

498-
cleanup:
499-
git_inflate_end(&stream);
500-
munmap(map, mapsize);
501-
if (oi->sizep == &size_scratch)
502-
oi->sizep = NULL;
503-
if (oi->typep == &type_scratch)
504-
oi->typep = NULL;
505-
oi->whence = OI_LOOSE;
506-
return status;
517+
out:
518+
if (stream_to_end)
519+
git_inflate_end(stream_to_end);
520+
if (map)
521+
munmap(map, mapsize);
522+
if (oi) {
523+
if (oi->sizep == &size_scratch)
524+
oi->sizep = NULL;
525+
if (oi->typep == &type_scratch)
526+
oi->typep = NULL;
527+
if (oi->delta_base_oid)
528+
oidclr(oi->delta_base_oid, source->odb->repo->hash_algo);
529+
if (!ret)
530+
oi->whence = OI_LOOSE;
531+
}
532+
533+
return ret;
507534
}
508535

509536
static void hash_object_body(const struct git_hash_algo *algo, struct git_hash_ctx *c,

odb.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,6 @@ struct object_info {
323323
OI_CACHED,
324324
OI_LOOSE,
325325
OI_PACKED,
326-
OI_DBCACHED
327326
} whence;
328327
union {
329328
/*
@@ -337,7 +336,12 @@ struct object_info {
337336
struct {
338337
struct packed_git *pack;
339338
off_t offset;
340-
unsigned int is_delta;
339+
enum packed_object_type {
340+
PACKED_OBJECT_TYPE_UNKNOWN,
341+
PACKED_OBJECT_TYPE_FULL,
342+
PACKED_OBJECT_TYPE_OFS_DELTA,
343+
PACKED_OBJECT_TYPE_REF_DELTA,
344+
} type;
341345
} packed;
342346
} u;
343347
};

pack-bitmap.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1876,8 +1876,7 @@ static unsigned long get_size_by_pos(struct bitmap_index *bitmap_git,
18761876
ofs = pack_pos_to_offset(pack, pos);
18771877
}
18781878

1879-
if (packed_object_info(bitmap_repo(bitmap_git), pack, ofs,
1880-
&oi) < 0) {
1879+
if (packed_object_info(pack, ofs, &oi) < 0) {
18811880
struct object_id oid;
18821881
nth_bitmap_object_oid(bitmap_git, &oid,
18831882
pack_pos_to_index(pack, pos));

packfile.c

Lines changed: 37 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1578,24 +1578,25 @@ static void add_delta_base_cache(struct packed_git *p, off_t base_offset,
15781578
hashmap_add(&delta_base_cache, &ent->ent);
15791579
}
15801580

1581-
int packed_object_info(struct repository *r, struct packed_git *p,
1581+
int packed_object_info(struct packed_git *p,
15821582
off_t obj_offset, struct object_info *oi)
15831583
{
15841584
struct pack_window *w_curs = NULL;
15851585
unsigned long size;
15861586
off_t curpos = obj_offset;
1587-
enum object_type type;
1587+
enum object_type type = OBJ_NONE;
1588+
int ret;
15881589

15891590
/*
15901591
* We always get the representation type, but only convert it to
15911592
* a "real" type later if the caller is interested.
15921593
*/
15931594
if (oi->contentp) {
1594-
*oi->contentp = cache_or_unpack_entry(r, p, obj_offset, oi->sizep,
1595+
*oi->contentp = cache_or_unpack_entry(p->repo, p, obj_offset, oi->sizep,
15951596
&type);
15961597
if (!*oi->contentp)
15971598
type = OBJ_BAD;
1598-
} else {
1599+
} else if (oi->sizep || oi->typep || oi->delta_base_oid) {
15991600
type = unpack_object_header(p, &w_curs, &curpos, &size);
16001601
}
16011602

@@ -1605,12 +1606,12 @@ int packed_object_info(struct repository *r, struct packed_git *p,
16051606
off_t base_offset = get_delta_base(p, &w_curs, &tmp_pos,
16061607
type, obj_offset);
16071608
if (!base_offset) {
1608-
type = OBJ_BAD;
1609+
ret = -1;
16091610
goto out;
16101611
}
16111612
*oi->sizep = get_size_from_delta(p, &w_curs, tmp_pos);
16121613
if (*oi->sizep == 0) {
1613-
type = OBJ_BAD;
1614+
ret = -1;
16141615
goto out;
16151616
}
16161617
} else {
@@ -1623,7 +1624,7 @@ int packed_object_info(struct repository *r, struct packed_git *p,
16231624
if (offset_to_pack_pos(p, obj_offset, &pos) < 0) {
16241625
error("could not find object at offset %"PRIuMAX" "
16251626
"in pack %s", (uintmax_t)obj_offset, p->pack_name);
1626-
type = OBJ_BAD;
1627+
ret = -1;
16271628
goto out;
16281629
}
16291630

@@ -1632,12 +1633,12 @@ int packed_object_info(struct repository *r, struct packed_git *p,
16321633

16331634
if (oi->typep) {
16341635
enum object_type ptot;
1635-
ptot = packed_to_object_type(r, p, obj_offset,
1636+
ptot = packed_to_object_type(p->repo, p, obj_offset,
16361637
type, &w_curs, curpos);
16371638
if (oi->typep)
16381639
*oi->typep = ptot;
16391640
if (ptot < 0) {
1640-
type = OBJ_BAD;
1641+
ret = -1;
16411642
goto out;
16421643
}
16431644
}
@@ -1647,19 +1648,37 @@ int packed_object_info(struct repository *r, struct packed_git *p,
16471648
if (get_delta_base_oid(p, &w_curs, curpos,
16481649
oi->delta_base_oid,
16491650
type, obj_offset) < 0) {
1650-
type = OBJ_BAD;
1651+
ret = -1;
16511652
goto out;
16521653
}
16531654
} else
16541655
oidclr(oi->delta_base_oid, p->repo->hash_algo);
16551656
}
16561657

1657-
oi->whence = in_delta_base_cache(p, obj_offset) ? OI_DBCACHED :
1658-
OI_PACKED;
1658+
oi->whence = OI_PACKED;
1659+
oi->u.packed.offset = obj_offset;
1660+
oi->u.packed.pack = p;
1661+
1662+
switch (type) {
1663+
case OBJ_NONE:
1664+
oi->u.packed.type = PACKED_OBJECT_TYPE_UNKNOWN;
1665+
break;
1666+
case OBJ_REF_DELTA:
1667+
oi->u.packed.type = PACKED_OBJECT_TYPE_REF_DELTA;
1668+
break;
1669+
case OBJ_OFS_DELTA:
1670+
oi->u.packed.type = PACKED_OBJECT_TYPE_OFS_DELTA;
1671+
break;
1672+
default:
1673+
oi->u.packed.type = PACKED_OBJECT_TYPE_FULL;
1674+
break;
1675+
}
1676+
1677+
ret = 0;
16591678

16601679
out:
16611680
unuse_pack(&w_curs);
1662-
return type;
1681+
return ret;
16631682
}
16641683

16651684
static void *unpack_compressed_entry(struct packed_git *p,
@@ -2133,7 +2152,7 @@ int packfile_store_read_object_info(struct packfile_store *store,
21332152
unsigned flags UNUSED)
21342153
{
21352154
struct pack_entry e;
2136-
int rtype;
2155+
int ret;
21372156

21382157
if (!find_pack_entry(store, oid, &e))
21392158
return 1;
@@ -2145,19 +2164,12 @@ int packfile_store_read_object_info(struct packfile_store *store,
21452164
if (!oi)
21462165
return 0;
21472166

2148-
rtype = packed_object_info(store->source->odb->repo, e.p, e.offset, oi);
2149-
if (rtype < 0) {
2167+
ret = packed_object_info(e.p, e.offset, oi);
2168+
if (ret < 0) {
21502169
mark_bad_packed_object(e.p, oid);
21512170
return -1;
21522171
}
21532172

2154-
if (oi->whence == OI_PACKED) {
2155-
oi->u.packed.offset = e.offset;
2156-
oi->u.packed.pack = e.p;
2157-
oi->u.packed.is_delta = (rtype == OBJ_REF_DELTA ||
2158-
rtype == OBJ_OFS_DELTA);
2159-
}
2160-
21612173
return 0;
21622174
}
21632175

@@ -2554,7 +2566,8 @@ int packfile_store_read_object_stream(struct odb_read_stream **out,
25542566
oi.sizep = &size;
25552567

25562568
if (packfile_store_read_object_info(store, oid, &oi, 0) ||
2557-
oi.u.packed.is_delta ||
2569+
oi.u.packed.type == PACKED_OBJECT_TYPE_REF_DELTA ||
2570+
oi.u.packed.type == PACKED_OBJECT_TYPE_OFS_DELTA ||
25582571
repo_settings_get_big_file_threshold(store->source->odb->repo) >= size)
25592572
return -1;
25602573

packfile.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -441,8 +441,11 @@ void release_pack_memory(size_t);
441441
/* global flag to enable extra checks when accessing packed objects */
442442
extern int do_check_packed_object_crc;
443443

444-
int packed_object_info(struct repository *r,
445-
struct packed_git *pack,
444+
/*
445+
* Look up the object info for a specific offset in the packfile.
446+
* Returns zero on success, a negative error code otherwise.
447+
*/
448+
int packed_object_info(struct packed_git *pack,
446449
off_t offset, struct object_info *);
447450

448451
void mark_bad_packed_object(struct packed_git *, const struct object_id *);

0 commit comments

Comments
 (0)