From 46a586a7199a78d2280ddb22368378693541fff0 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 17 Jul 2026 11:32:11 +0200 Subject: [PATCH] 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 Signed-off-by: Junio C Hamano --- object-file.c | 35 ++++++++--------------------------- object-file.h | 4 ---- odb.c | 2 ++ odb/source-files.c | 2 +- odb/source-inmemory.c | 6 +++--- odb/source-loose.c | 12 +++++++----- odb/source-packed.c | 2 +- odb/source.h | 4 ++-- t/unit-tests/u-odb-inmemory.c | 1 + 9 files changed, 25 insertions(+), 43 deletions(-) diff --git a/object-file.c b/object-file.c index 5283292f1e..9ca14f484d 100644 --- a/object-file.c +++ b/object-file.c @@ -316,31 +316,6 @@ int parse_loose_header(const char *hdr, struct object_info *oi) return 0; } -static void hash_object_body(const struct git_hash_algo *algo, struct git_hash_ctx *c, - const void *buf, size_t len, - struct object_id *oid, - char *hdr, size_t *hdrlen) -{ - git_hash_init(c, algo); - git_hash_update(c, hdr, *hdrlen); - git_hash_update(c, buf, len); - git_hash_final_oid(oid, c); -} - -void write_object_file_prepare(const struct git_hash_algo *algo, - const void *buf, size_t len, - enum object_type type, struct object_id *oid, - char *hdr, size_t *hdrlen) -{ - struct git_hash_ctx c; - - /* Generate the header */ - *hdrlen = format_object_header(hdr, *hdrlen, type, len); - - /* Hash (function pointers) computation */ - hash_object_body(algo, &c, buf, len, oid, hdr, hdrlen); -} - #define CHECK_COLLISION_DEST_VANISHED -2 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, size_t len, enum object_type type, struct object_id *oid) { + struct git_hash_ctx c; char hdr[MAX_HEADER_LEN]; - size_t hdrlen = sizeof(hdr); + int hdrlen; - write_object_file_prepare(algo, buf, len, type, oid, hdr, &hdrlen); + hdrlen = format_object_header(hdr, sizeof(hdr), type, len); + + git_hash_init(&c, algo); + git_hash_update(&c, hdr, hdrlen); + git_hash_update(&c, buf, len); + git_hash_final_oid(oid, &c); } struct transaction_packfile { diff --git a/object-file.h b/object-file.h index d04ffa6493..08aafcda0d 100644 --- a/object-file.h +++ b/object-file.h @@ -134,10 +134,6 @@ int finalize_object_file_flags(struct repository *repo, void hash_object_file(const struct git_hash_algo *algo, const void *buf, size_t len, enum object_type type, struct object_id *oid); -void write_object_file_prepare(const struct git_hash_algo *algo, - const void *buf, size_t len, - enum object_type type, struct object_id *oid, - char *hdr, size_t *hdrlen); int write_loose_object(struct odb_source_loose *loose, const struct object_id *oid, char *hdr, int hdrlen, const void *buf, unsigned long len, diff --git a/odb.c b/odb.c index 1d6538163b..4adbdf8a64 100644 --- a/odb.c +++ b/odb.c @@ -995,6 +995,8 @@ int odb_write_object_ext(struct object_database *odb, const struct git_hash_algo *compat = odb->repo->compat_hash_algo; struct object_id compat_oid, *compat_oid_p = NULL; + hash_object_file(odb->repo->hash_algo, buf, len, type, oid); + if (compat) { const struct git_hash_algo *algo = odb->repo->hash_algo; diff --git a/odb/source-files.c b/odb/source-files.c index 3d9f5eca32..06dfc8dd78 100644 --- a/odb/source-files.c +++ b/odb/source-files.c @@ -162,7 +162,7 @@ static int odb_source_files_freshen_object(struct odb_source *source, static int odb_source_files_write_object(struct odb_source *source, const void *buf, size_t len, enum object_type type, - struct object_id *oid, + const struct object_id *oid, const struct object_id *compat_oid, enum odb_write_object_flags flags) { diff --git a/odb/source-inmemory.c b/odb/source-inmemory.c index e727aba427..963d520317 100644 --- a/odb/source-inmemory.c +++ b/odb/source-inmemory.c @@ -230,15 +230,13 @@ static int odb_source_inmemory_count_objects(struct odb_source *source, static int odb_source_inmemory_write_object(struct odb_source *source, const void *buf, size_t len, enum object_type type, - struct object_id *oid, + const struct object_id *oid, const struct object_id *compat_oid UNUSED, enum odb_write_object_flags flags UNUSED) { struct odb_source_inmemory *inmemory = odb_source_inmemory_downcast(source); struct inmemory_object *object; - hash_object_file(source->odb->repo->hash_algo, buf, len, type, oid); - if (!inmemory->objects) { CALLOC_ARRAY(inmemory->objects, 1); oidtree_init(inmemory->objects); @@ -285,6 +283,8 @@ static int odb_source_inmemory_write_object_stream(struct odb_source *source, goto out; } + hash_object_file(source->odb->repo->hash_algo, data, total_read, OBJ_BLOB, oid); + ret = odb_source_inmemory_write_object(source, data, len, OBJ_BLOB, oid, NULL, 0); if (ret < 0) diff --git a/odb/source-loose.c b/odb/source-loose.c index ca223109cd..d4715da6d1 100644 --- a/odb/source-loose.c +++ b/odb/source-loose.c @@ -584,19 +584,21 @@ static int odb_source_loose_freshen_object(struct odb_source *source, static int odb_source_loose_write_object(struct odb_source *source, const void *buf, size_t len, - enum object_type type, struct object_id *oid, + enum object_type type, + const struct object_id *oid, const struct object_id *compat_oid, enum odb_write_object_flags flags) { struct odb_source_loose *loose = odb_source_loose_downcast(source); - const struct git_hash_algo *algo = source->odb->repo->hash_algo; char hdr[MAX_HEADER_LEN]; - size_t hdrlen = sizeof(hdr); + int hdrlen; - /* Normally if we have it in the pack then we do not bother writing + hdrlen = format_object_header(hdr, sizeof(hdr), type, len); + + /* + * Normally if we have it in the pack then we do not bother writing * it out into .git/objects/??/?{38} file. */ - write_object_file_prepare(algo, buf, len, type, oid, hdr, &hdrlen); if (odb_freshen_object(source->odb, oid)) return 0; if (write_loose_object(loose, oid, hdr, hdrlen, buf, len, 0, flags)) diff --git a/odb/source-packed.c b/odb/source-packed.c index af0d533375..f7f1706447 100644 --- a/odb/source-packed.c +++ b/odb/source-packed.c @@ -529,7 +529,7 @@ static int odb_source_packed_write_object(struct odb_source *source UNUSED, const void *buf UNUSED, size_t len UNUSED, enum object_type type UNUSED, - struct object_id *oid UNUSED, + const struct object_id *oid UNUSED, const struct object_id *compat_oid UNUSED, unsigned flags UNUSED) { diff --git a/odb/source.h b/odb/source.h index b3c1ca3a66..c4e94c9d0d 100644 --- a/odb/source.h +++ b/odb/source.h @@ -206,7 +206,7 @@ struct odb_source { int (*write_object)(struct odb_source *source, const void *buf, size_t len, enum object_type type, - struct object_id *oid, + const struct object_id *oid, const struct object_id *compat_oid, enum odb_write_object_flags flags); @@ -416,7 +416,7 @@ static inline int odb_source_freshen_object(struct odb_source *source, static inline int odb_source_write_object(struct odb_source *source, const void *buf, unsigned long len, enum object_type type, - struct object_id *oid, + const struct object_id *oid, const struct object_id *compat_oid, enum odb_write_object_flags flags) { diff --git a/t/unit-tests/u-odb-inmemory.c b/t/unit-tests/u-odb-inmemory.c index 2dbc3ab1df..28a69fc244 100644 --- a/t/unit-tests/u-odb-inmemory.c +++ b/t/unit-tests/u-odb-inmemory.c @@ -43,6 +43,7 @@ static void cl_assert_write_object(struct odb_source_inmemory *source, struct object_id *oid) { size_t content_len = strlen(content); + hash_object_file(repo.hash_algo, content, content_len, type, oid); cl_must_pass(odb_source_write_object(&source->base, content, content_len, type, oid, NULL, 0)); }