object-file: adapt `stream_object_signature()` to take a stream
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>
Patrick Steinhardt committed
Feb 23, 2026 at 17:00 UTC
10a6762719f612bb5edc554e62239a744bbc4283
4 files changed
+31
-14
object-file.c
+3
-7
@@ -129,18 +129,15 @@ int check_object_signature(struct repository *r, const struct object_id *oid,
129
return !oideq(oid, &real_oid) ? -1 : 0;
130
}
131
132
-int stream_object_signature(struct repository *r, const struct object_id *oid)
132
+int stream_object_signature(struct repository *r,
133
+ struct odb_read_stream *st,
134
+ const struct object_id *oid)
135
{
136
struct object_id real_oid;
135
- struct odb_read_stream *st;
137
struct git_hash_ctx c;
138
char hdr[MAX_HEADER_LEN];
139
int hdrlen;
140
140
- st = odb_read_stream_open(r->objects, oid, NULL);
141
- if (!st)
142
- return -1;
143
-
141
/* Generate the header */
142
hdrlen = format_object_header(hdr, sizeof(hdr), st->type, st->size);
143
@@ -160,7 +157,6 @@ int stream_object_signature(struct repository *r, const struct object_id *oid)
157
git_hash_update(&c, buf, readlen);
158
}
159
git_hash_final_oid(&real_oid, &c);
163
- odb_read_stream_close(st);
160
return !oideq(oid, &real_oid) ? -1 : 0;
161
}
162
object-file.h
+3
-1
@@ -164,7 +164,9 @@ int check_object_signature(struct repository *r, const struct object_id *oid,
164
* Try reading the object named with "oid" using
165
* the streaming interface and rehash it to do the same.
166
*/
167
-int stream_object_signature(struct repository *r, const struct object_id *oid);
167
+int stream_object_signature(struct repository *r,
168
+ struct odb_read_stream *stream,
169
+ const struct object_id *oid);
170
171
enum finalize_object_file_flags {
172
FOF_SKIP_COLLISION_CHECK = 1,
object.c
+16
-3
@@ -6,6 +6,7 @@
6
#include "object.h"
7
#include "replace-object.h"
8
#include "object-file.h"
9
+#include "odb/streaming.h"
10
#include "blob.h"
11
#include "statinfo.h"
12
#include "tree.h"
@@ -330,9 +331,21 @@ struct object *parse_object_with_flags(struct repository *r,
331
332
if ((!obj || obj->type == OBJ_NONE || obj->type == OBJ_BLOB) &&
333
odb_read_object_info(r->objects, oid, NULL) == OBJ_BLOB) {
333
- if (!skip_hash && stream_object_signature(r, repl) < 0) {
334
- error(_("hash mismatch %s"), oid_to_hex(oid));
335
- return NULL;
334
+ if (!skip_hash) {
335
+ struct odb_read_stream *stream = odb_read_stream_open(r->objects, oid, NULL);
336
+
337
+ if (!stream) {
338
+ error(_("unable to open object stream for %s"), oid_to_hex(oid));
339
+ return NULL;
340
+ }
341
+
342
+ if (stream_object_signature(r, stream, repl) < 0) {
343
+ error(_("hash mismatch %s"), oid_to_hex(oid));
344
+ odb_read_stream_close(stream);
345
+ return NULL;
346
+ }
347
+
348
+ odb_read_stream_close(stream);
349
}
350
parse_blob_buffer(lookup_blob(r, oid));
351
return lookup_object(r, oid);
pack-check.c
+9
-3
@@ -9,6 +9,7 @@
9
#include "packfile.h"
10
#include "object-file.h"
11
#include "odb.h"
12
+#include "odb/streaming.h"
13
14
struct idx_entry {
15
off_t offset;
@@ -104,6 +105,7 @@ static int verify_packfile(struct repository *r,
105
QSORT(entries, nr_objects, compare_entries);
106
107
for (i = 0; i < nr_objects; i++) {
108
+ struct odb_read_stream *stream = NULL;
109
void *data;
110
struct object_id oid;
111
enum object_type type;
@@ -152,7 +154,9 @@ static int verify_packfile(struct repository *r,
154
type) < 0)
155
err = error("packed %s from %s is corrupt",
156
oid_to_hex(&oid), p->pack_name);
155
- else if (!data && stream_object_signature(r, &oid) < 0)
157
+ else if (!data &&
158
+ (!(stream = odb_read_stream_open(r->objects, &oid, NULL)) ||
159
+ stream_object_signature(r, stream, &oid) < 0))
160
err = error("packed %s from %s is corrupt",
161
oid_to_hex(&oid), p->pack_name);
162
else if (fn) {
@@ -163,12 +167,14 @@ static int verify_packfile(struct repository *r,
167
}
168
if (((base_count + i) & 1023) == 0)
169
display_progress(progress, base_count + i);
166
- free(data);
170
171
+ if (stream)
172
+ odb_read_stream_close(stream);
173
+ free(data);
174
}
175
+
176
display_progress(progress, base_count + i);
177
free(entries);
171
-
178
return err;
179
}
180