]> git.ipfire.org Git - thirdparty/git.git/commitdiff
object-file: adapt `stream_object_signature()` to take a stream
authorPatrick Steinhardt <ps@pks.im>
Mon, 23 Feb 2026 16:00:07 +0000 (17:00 +0100)
committerJunio C Hamano <gitster@pobox.com>
Mon, 23 Feb 2026 21:19:00 +0000 (13:19 -0800)
The function `stream_object_signature()` is responsible for verifying
whether the given object ID matches the actual hash of the object's
contents. In contrast to `check_object_signature()` it does so in a
streaming fashion so that we don't have to load the full object into
memory.

In a subsequent commit we'll want to adapt one of its callsites to pass
a preconstructed stream. Prepare for this by accepting a stream as input
that the caller needs to assemble.

While at it, improve the error reporting in `parse_object_with_flags()`
to tell apart the two failure modes.

Helped-by: Jeff King <peff@peff.net>
Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
object-file.c
object-file.h
object.c
pack-check.c

index e7e4c3348f9c1bb2bc909d13a41e1eb38a946743..a59b7abaaf637311a7b1de9c4e2c27282010c4de 100644 (file)
@@ -129,18 +129,15 @@ int check_object_signature(struct repository *r, const struct object_id *oid,
        return !oideq(oid, &real_oid) ? -1 : 0;
 }
 
-int stream_object_signature(struct repository *r, const struct object_id *oid)
+int stream_object_signature(struct repository *r,
+                           struct odb_read_stream *st,
+                           const struct object_id *oid)
 {
        struct object_id real_oid;
-       struct odb_read_stream *st;
        struct git_hash_ctx c;
        char hdr[MAX_HEADER_LEN];
        int hdrlen;
 
-       st = odb_read_stream_open(r->objects, oid, NULL);
-       if (!st)
-               return -1;
-
        /* Generate the header */
        hdrlen = format_object_header(hdr, sizeof(hdr), st->type, st->size);
 
@@ -160,7 +157,6 @@ int stream_object_signature(struct repository *r, const struct object_id *oid)
                git_hash_update(&c, buf, readlen);
        }
        git_hash_final_oid(&real_oid, &c);
-       odb_read_stream_close(st);
        return !oideq(oid, &real_oid) ? -1 : 0;
 }
 
index 1229d5f675b44aa002cb49d9cdafe6842405cf2c..6936fd0fefc5fb6505e235e3a9ef1b1789b9d899 100644 (file)
@@ -164,7 +164,9 @@ int check_object_signature(struct repository *r, const struct object_id *oid,
  * Try reading the object named with "oid" using
  * the streaming interface and rehash it to do the same.
  */
-int stream_object_signature(struct repository *r, const struct object_id *oid);
+int stream_object_signature(struct repository *r,
+                           struct odb_read_stream *stream,
+                           const struct object_id *oid);
 
 enum finalize_object_file_flags {
        FOF_SKIP_COLLISION_CHECK = 1,
index 4669b8d65e74abcf92da3f9647df8c717be139b6..9d2c676b16c6e6f85b9c098df4e6dc7e208548a8 100644 (file)
--- a/object.c
+++ b/object.c
@@ -6,6 +6,7 @@
 #include "object.h"
 #include "replace-object.h"
 #include "object-file.h"
+#include "odb/streaming.h"
 #include "blob.h"
 #include "statinfo.h"
 #include "tree.h"
@@ -330,9 +331,21 @@ struct object *parse_object_with_flags(struct repository *r,
 
        if ((!obj || obj->type == OBJ_NONE || obj->type == OBJ_BLOB) &&
            odb_read_object_info(r->objects, oid, NULL) == OBJ_BLOB) {
-               if (!skip_hash && stream_object_signature(r, repl) < 0) {
-                       error(_("hash mismatch %s"), oid_to_hex(oid));
-                       return NULL;
+               if (!skip_hash) {
+                       struct odb_read_stream *stream = odb_read_stream_open(r->objects, oid, NULL);
+
+                       if (!stream) {
+                               error(_("unable to open object stream for %s"), oid_to_hex(oid));
+                               return NULL;
+                       }
+
+                       if (stream_object_signature(r, stream, repl) < 0) {
+                               error(_("hash mismatch %s"), oid_to_hex(oid));
+                               odb_read_stream_close(stream);
+                               return NULL;
+                       }
+
+                       odb_read_stream_close(stream);
                }
                parse_blob_buffer(lookup_blob(r, oid));
                return lookup_object(r, oid);
index 67cb2cf72f2b93c9e652fbc72cf456628f29bc62..46782a29d5191ee6b2a4b5e68cfae14c84cc4063 100644 (file)
@@ -9,6 +9,7 @@
 #include "packfile.h"
 #include "object-file.h"
 #include "odb.h"
+#include "odb/streaming.h"
 
 struct idx_entry {
        off_t                offset;
@@ -104,6 +105,7 @@ static int verify_packfile(struct repository *r,
        QSORT(entries, nr_objects, compare_entries);
 
        for (i = 0; i < nr_objects; i++) {
+               struct odb_read_stream *stream = NULL;
                void *data;
                struct object_id oid;
                enum object_type type;
@@ -152,7 +154,9 @@ static int verify_packfile(struct repository *r,
                                                        type) < 0)
                        err = error("packed %s from %s is corrupt",
                                    oid_to_hex(&oid), p->pack_name);
-               else if (!data && stream_object_signature(r, &oid) < 0)
+               else if (!data &&
+                        (!(stream = odb_read_stream_open(r->objects, &oid, NULL)) ||
+                         stream_object_signature(r, stream, &oid) < 0))
                        err = error("packed %s from %s is corrupt",
                                    oid_to_hex(&oid), p->pack_name);
                else if (fn) {
@@ -163,12 +167,14 @@ static int verify_packfile(struct repository *r,
                }
                if (((base_count + i) & 1023) == 0)
                        display_progress(progress, base_count + i);
-               free(data);
 
+               if (stream)
+                       odb_read_stream_close(stream);
+               free(data);
        }
+
        display_progress(progress, base_count + i);
        free(entries);
-
        return err;
 }