odb: compute object hash in `odb_write_object_ext()`

Same as in a preceding commit, compute the object hash in `odb_write_object_ext()` so that we can unify this logic. Besides unification, this change also allows us to lift the object existence check out of the "loose" backend into the generic layer, which will happen in the next commit. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed Jul 17, 2026 at 11:32 UTC 46a586a7199a78d2280ddb22368378693541fff0
9 files changed +25 -43
object-file.c
+8 -27
@@ -316,31 +316,6 @@ int parse_loose_header(const char *hdr, struct object_info *oi)
316 return 0;
317 }
318
319 -static void hash_object_body(const struct git_hash_algo *algo, struct git_hash_ctx *c,
320 - const void *buf, size_t len,
321 - struct object_id *oid,
322 - char *hdr, size_t *hdrlen)
323 -{
324 - git_hash_init(c, algo);
325 - git_hash_update(c, hdr, *hdrlen);
326 - git_hash_update(c, buf, len);
327 - git_hash_final_oid(oid, c);
328 -}
329 -
330 -void write_object_file_prepare(const struct git_hash_algo *algo,
331 - const void *buf, size_t len,
332 - enum object_type type, struct object_id *oid,
333 - char *hdr, size_t *hdrlen)
334 -{
335 - struct git_hash_ctx c;
336 -
337 - /* Generate the header */
338 - *hdrlen = format_object_header(hdr, *hdrlen, type, len);
339 -
340 - /* Hash (function pointers) computation */
341 - hash_object_body(algo, &c, buf, len, oid, hdr, hdrlen);
342 -}
343 -
319 #define CHECK_COLLISION_DEST_VANISHED -2
320
321 static int check_collision(const char *source, const char *dest)
@@ -476,10 +451,16 @@ void hash_object_file(const struct git_hash_algo *algo, const void *buf,
451 size_t len, enum object_type type,
452 struct object_id *oid)
453 {
454 + struct git_hash_ctx c;
455 char hdr[MAX_HEADER_LEN];
480 - size_t hdrlen = sizeof(hdr);
456 + int hdrlen;
457 +
458 + hdrlen = format_object_header(hdr, sizeof(hdr), type, len);
459
482 - write_object_file_prepare(algo, buf, len, type, oid, hdr, &hdrlen);
460 + git_hash_init(&c, algo);
461 + git_hash_update(&c, hdr, hdrlen);
462 + git_hash_update(&c, buf, len);
463 + git_hash_final_oid(oid, &c);
464 }
465
466 struct transaction_packfile {
object-file.h
-4
@@ -134,10 +134,6 @@ int finalize_object_file_flags(struct repository *repo,
134 void hash_object_file(const struct git_hash_algo *algo, const void *buf,
135 size_t len, enum object_type type,
136 struct object_id *oid);
137 -void write_object_file_prepare(const struct git_hash_algo *algo,
138 - const void *buf, size_t len,
139 - enum object_type type, struct object_id *oid,
140 - char *hdr, size_t *hdrlen);
137 int write_loose_object(struct odb_source_loose *loose,
138 const struct object_id *oid, char *hdr,
139 int hdrlen, const void *buf, unsigned long len,
odb.c
+2
@@ -995,6 +995,8 @@ int odb_write_object_ext(struct object_database *odb,
995 const struct git_hash_algo *compat = odb->repo->compat_hash_algo;
996 struct object_id compat_oid, *compat_oid_p = NULL;
997
998 + hash_object_file(odb->repo->hash_algo, buf, len, type, oid);
999 +
1000 if (compat) {
1001 const struct git_hash_algo *algo = odb->repo->hash_algo;
1002
odb/source-files.c
+1 -1
@@ -162,7 +162,7 @@ static int odb_source_files_freshen_object(struct odb_source *source,
162 static int odb_source_files_write_object(struct odb_source *source,
163 const void *buf, size_t len,
164 enum object_type type,
165 - struct object_id *oid,
165 + const struct object_id *oid,
166 const struct object_id *compat_oid,
167 enum odb_write_object_flags flags)
168 {
odb/source-inmemory.c
+3 -3
@@ -230,15 +230,13 @@ static int odb_source_inmemory_count_objects(struct odb_source *source,
230 static int odb_source_inmemory_write_object(struct odb_source *source,
231 const void *buf, size_t len,
232 enum object_type type,
233 - struct object_id *oid,
233 + const struct object_id *oid,
234 const struct object_id *compat_oid UNUSED,
235 enum odb_write_object_flags flags UNUSED)
236 {
237 struct odb_source_inmemory *inmemory = odb_source_inmemory_downcast(source);
238 struct inmemory_object *object;
239
240 - hash_object_file(source->odb->repo->hash_algo, buf, len, type, oid);
241 -
240 if (!inmemory->objects) {
241 CALLOC_ARRAY(inmemory->objects, 1);
242 oidtree_init(inmemory->objects);
@@ -285,6 +283,8 @@ static int odb_source_inmemory_write_object_stream(struct odb_source *source,
283 goto out;
284 }
285
286 + hash_object_file(source->odb->repo->hash_algo, data, total_read, OBJ_BLOB, oid);
287 +
288 ret = odb_source_inmemory_write_object(source, data, len, OBJ_BLOB, oid,
289 NULL, 0);
290 if (ret < 0)
odb/source-loose.c
+7 -5
@@ -584,19 +584,21 @@ static int odb_source_loose_freshen_object(struct odb_source *source,
584
585 static int odb_source_loose_write_object(struct odb_source *source,
586 const void *buf, size_t len,
587 - enum object_type type, struct object_id *oid,
587 + enum object_type type,
588 + const struct object_id *oid,
589 const struct object_id *compat_oid,
590 enum odb_write_object_flags flags)
591 {
592 struct odb_source_loose *loose = odb_source_loose_downcast(source);
592 - const struct git_hash_algo *algo = source->odb->repo->hash_algo;
593 char hdr[MAX_HEADER_LEN];
594 - size_t hdrlen = sizeof(hdr);
594 + int hdrlen;
595 +
596 + hdrlen = format_object_header(hdr, sizeof(hdr), type, len);
597
596 - /* Normally if we have it in the pack then we do not bother writing
598 + /*
599 + * Normally if we have it in the pack then we do not bother writing
600 * it out into .git/objects/??/?{38} file.
601 */
599 - write_object_file_prepare(algo, buf, len, type, oid, hdr, &hdrlen);
602 if (odb_freshen_object(source->odb, oid))
603 return 0;
604 if (write_loose_object(loose, oid, hdr, hdrlen, buf, len, 0, flags))
odb/source-packed.c
+1 -1
@@ -529,7 +529,7 @@ static int odb_source_packed_write_object(struct odb_source *source UNUSED,
529 const void *buf UNUSED,
530 size_t len UNUSED,
531 enum object_type type UNUSED,
532 - struct object_id *oid UNUSED,
532 + const struct object_id *oid UNUSED,
533 const struct object_id *compat_oid UNUSED,
534 unsigned flags UNUSED)
535 {
odb/source.h
+2 -2
@@ -206,7 +206,7 @@ struct odb_source {
206 int (*write_object)(struct odb_source *source,
207 const void *buf, size_t len,
208 enum object_type type,
209 - struct object_id *oid,
209 + const struct object_id *oid,
210 const struct object_id *compat_oid,
211 enum odb_write_object_flags flags);
212
@@ -416,7 +416,7 @@ static inline int odb_source_freshen_object(struct odb_source *source,
416 static inline int odb_source_write_object(struct odb_source *source,
417 const void *buf, unsigned long len,
418 enum object_type type,
419 - struct object_id *oid,
419 + const struct object_id *oid,
420 const struct object_id *compat_oid,
421 enum odb_write_object_flags flags)
422 {
t/unit-tests/u-odb-inmemory.c
+1
@@ -43,6 +43,7 @@ static void cl_assert_write_object(struct odb_source_inmemory *source,
43 struct object_id *oid)
44 {
45 size_t content_len = strlen(content);
46 + hash_object_file(repo.hash_algo, content, content_len, type, oid);
47 cl_must_pass(odb_source_write_object(&source->base, content, content_len,
48 type, oid, NULL, 0));
49 }