aboutsummaryrefslogtreecommitdiff
path: root/object-file.c
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2026-01-15 05:47:47 -0800
committerJunio C Hamano <gitster@pobox.com>2026-01-15 05:47:47 -0800
commitc8e1706e8dbe7a511c1fd85d5147a1722b4080f1 (patch)
treedcab6ef9ff4e3e9359454a6b1c04e7dc59d87317 /object-file.c
parent8745eae506f700657882b9e32b2aa00f234a6fb6 (diff)
parent12d3b58b5552750f351ded7166b347446d9543f3 (diff)
downloadgit-c8e1706e8dbe7a511c1fd85d5147a1722b4080f1.tar.xz
Merge branch 'ps/read-object-info-improvements' into ps/odb-for-each-object
* 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
Diffstat (limited to 'object-file.c')
-rw-r--r--object-file.c115
1 files changed, 71 insertions, 44 deletions
diff --git a/object-file.c b/object-file.c
index 6280e42f34..e7e4c3348f 100644
--- a/object-file.c
+++ b/object-file.c
@@ -416,19 +416,16 @@ int odb_source_loose_read_object_info(struct odb_source *source,
const struct object_id *oid,
struct object_info *oi, int flags)
{
- int status = 0;
+ int ret;
int fd;
unsigned long mapsize;
const char *path;
- void *map;
- git_zstream stream;
+ void *map = NULL;
+ git_zstream stream, *stream_to_end = NULL;
char hdr[MAX_HEADER_LEN];
unsigned long size_scratch;
enum object_type type_scratch;
- if (oi && oi->delta_base_oid)
- oidclr(oi->delta_base_oid, source->odb->repo->hash_algo);
-
/*
* If we don't care about type or size, then we don't
* 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,
*/
if (!oi || (!oi->typep && !oi->sizep && !oi->contentp)) {
struct stat st;
- if ((!oi || !oi->disk_sizep) && (flags & OBJECT_INFO_QUICK))
- return quick_has_loose(source->loose, oid) ? 0 : -1;
- if (stat_loose_object(source->loose, oid, &st, &path) < 0)
- return -1;
+
+ if ((!oi || !oi->disk_sizep) && (flags & OBJECT_INFO_QUICK)) {
+ ret = quick_has_loose(source->loose, oid) ? 0 : -1;
+ goto out;
+ }
+
+ if (stat_loose_object(source->loose, oid, &st, &path) < 0) {
+ ret = -1;
+ goto out;
+ }
+
if (oi && oi->disk_sizep)
*oi->disk_sizep = st.st_size;
- return 0;
+
+ ret = 0;
+ goto out;
}
fd = open_loose_object(source->loose, oid, &path);
if (fd < 0) {
if (errno != ENOENT)
error_errno(_("unable to open loose object %s"), oid_to_hex(oid));
- return -1;
+ ret = -1;
+ goto out;
}
- map = map_fd(fd, path, &mapsize);
- if (!map)
- return -1;
- if (!oi->sizep)
- oi->sizep = &size_scratch;
- if (!oi->typep)
- oi->typep = &type_scratch;
+ map = map_fd(fd, path, &mapsize);
+ if (!map) {
+ ret = -1;
+ goto out;
+ }
if (oi->disk_sizep)
*oi->disk_sizep = mapsize;
+ stream_to_end = &stream;
+
switch (unpack_loose_header(&stream, map, mapsize, hdr, sizeof(hdr))) {
case ULHR_OK:
- if (parse_loose_header(hdr, oi) < 0)
- status = error(_("unable to parse %s header"), oid_to_hex(oid));
- else if (*oi->typep < 0)
+ if (!oi->sizep)
+ oi->sizep = &size_scratch;
+ if (!oi->typep)
+ oi->typep = &type_scratch;
+
+ if (parse_loose_header(hdr, oi) < 0) {
+ ret = error(_("unable to parse %s header"), oid_to_hex(oid));
+ goto corrupt;
+ }
+
+ if (*oi->typep < 0)
die(_("invalid object type"));
- if (!oi->contentp)
- break;
- *oi->contentp = unpack_loose_rest(&stream, hdr, *oi->sizep, oid);
- if (*oi->contentp)
- goto cleanup;
+ if (oi->contentp) {
+ *oi->contentp = unpack_loose_rest(&stream, hdr, *oi->sizep, oid);
+ if (!*oi->contentp) {
+ ret = -1;
+ goto corrupt;
+ }
+ }
- status = -1;
break;
case ULHR_BAD:
- status = error(_("unable to unpack %s header"),
- oid_to_hex(oid));
- break;
+ ret = error(_("unable to unpack %s header"),
+ oid_to_hex(oid));
+ goto corrupt;
case ULHR_TOO_LONG:
- status = error(_("header for %s too long, exceeds %d bytes"),
- oid_to_hex(oid), MAX_HEADER_LEN);
- break;
+ ret = error(_("header for %s too long, exceeds %d bytes"),
+ oid_to_hex(oid), MAX_HEADER_LEN);
+ goto corrupt;
}
- if (status && (flags & OBJECT_INFO_DIE_IF_CORRUPT))
+ ret = 0;
+
+corrupt:
+ if (ret && (flags & OBJECT_INFO_DIE_IF_CORRUPT))
die(_("loose object %s (stored in %s) is corrupt"),
oid_to_hex(oid), path);
-cleanup:
- git_inflate_end(&stream);
- munmap(map, mapsize);
- if (oi->sizep == &size_scratch)
- oi->sizep = NULL;
- if (oi->typep == &type_scratch)
- oi->typep = NULL;
- oi->whence = OI_LOOSE;
- return status;
+out:
+ if (stream_to_end)
+ git_inflate_end(stream_to_end);
+ if (map)
+ munmap(map, mapsize);
+ if (oi) {
+ if (oi->sizep == &size_scratch)
+ oi->sizep = NULL;
+ if (oi->typep == &type_scratch)
+ oi->typep = NULL;
+ if (oi->delta_base_oid)
+ oidclr(oi->delta_base_oid, source->odb->repo->hash_algo);
+ if (!ret)
+ oi->whence = OI_LOOSE;
+ }
+
+ return ret;
}
static void hash_object_body(const struct git_hash_algo *algo, struct git_hash_ctx *c,