From: Patrick Steinhardt Date: Fri, 17 Jul 2026 09:32:09 +0000 (+0200) Subject: odb: compute compat object ID in `odb_write_object_ext()` X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=215d305f450ff0691d15daaa6ef72f77e8441b39;p=thirdparty%2Fgit.git odb: compute compat object ID in `odb_write_object_ext()` Repositories can have a compatibility hash configured, which means that such a repository is expected to maintain a mapping between canonical and compatibility object hashes. Maintaining this mapping is the responsibility of the object database sources, where we either store them as part of the loose objects map or in packfile indices v3 (once we gain support for this feature). But besides storing these compatibility hashes, the sources are also responsible for generating the compatibility hash in the first place. This is somewhat unnecessary though, as the compatibility hash should be computed the same no matter which source is being used. The consequence is that we need to duplicate this functionality across the different backends, which does not make a lot of sense. Refactor the code so that we instead compute the compatibility hash in `odb_write_object_ext()` and then pass the computed value to the sources. No callers need adjustment as there are none that write objects via the source interfaces directly. Signed-off-by: Patrick Steinhardt Signed-off-by: Junio C Hamano --- diff --git a/odb.c b/odb.c index cf6e7938c0..1d6538163b 100644 --- a/odb.c +++ b/odb.c @@ -989,11 +989,33 @@ int odb_write_object_ext(struct object_database *odb, const void *buf, unsigned long len, enum object_type type, struct object_id *oid, - struct object_id *compat_oid, + const struct object_id *compat_oid_in, enum odb_write_object_flags flags) { + const struct git_hash_algo *compat = odb->repo->compat_hash_algo; + struct object_id compat_oid, *compat_oid_p = NULL; + + if (compat) { + const struct git_hash_algo *algo = odb->repo->hash_algo; + + if (compat_oid_in) { + oidcpy(&compat_oid, compat_oid_in); + } else if (type == OBJ_BLOB) { + hash_object_file(compat, buf, len, type, &compat_oid); + } else { + struct strbuf converted = STRBUF_INIT; + convert_object_file(odb->repo, &converted, algo, compat, + buf, len, type, 0); + hash_object_file(compat, converted.buf, converted.len, + type, &compat_oid); + strbuf_release(&converted); + } + + compat_oid_p = &compat_oid; + } + return odb_source_write_object(odb->sources, buf, len, type, - oid, compat_oid, flags); + oid, compat_oid_p, flags); } int odb_write_object_stream(struct object_database *odb, diff --git a/odb.h b/odb.h index 94754643d2..066560113e 100644 --- a/odb.h +++ b/odb.h @@ -585,9 +585,11 @@ enum odb_write_object_flags { /* * Write an object into the object database. The object is being written into - * the local alternate of the repository. If provided, the converted object ID - * as well as the compatibility object ID are written to the respective - * pointers. + * the local alternate of the repository. If provided, the object ID of the + * final object is written into `oid`. + * + * If the caller provides a `compat_oid`, then this compatibility object hash + * will be stored instead of computing the compatibility hash ad-hoc. * * Returns 0 on success, a negative error code otherwise. */ @@ -595,7 +597,7 @@ int odb_write_object_ext(struct object_database *odb, const void *buf, unsigned long len, enum object_type type, struct object_id *oid, - struct object_id *compat_oid, + const struct object_id *compat_oid, enum odb_write_object_flags flags); static inline int odb_write_object(struct object_database *odb, diff --git a/odb/source-files.c b/odb/source-files.c index 4138758511..3d9f5eca32 100644 --- a/odb/source-files.c +++ b/odb/source-files.c @@ -163,7 +163,7 @@ 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, - struct object_id *compat_oid, + const struct object_id *compat_oid, enum odb_write_object_flags flags) { struct odb_source_files *files = odb_source_files_downcast(source); diff --git a/odb/source-inmemory.c b/odb/source-inmemory.c index e47bfd8fcc..e727aba427 100644 --- a/odb/source-inmemory.c +++ b/odb/source-inmemory.c @@ -231,7 +231,7 @@ 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, - struct object_id *compat_oid UNUSED, + const struct object_id *compat_oid UNUSED, enum odb_write_object_flags flags UNUSED) { struct odb_source_inmemory *inmemory = odb_source_inmemory_downcast(source); diff --git a/odb/source-loose.c b/odb/source-loose.c index 3f7d04a56e..ca223109cd 100644 --- a/odb/source-loose.c +++ b/odb/source-loose.c @@ -585,32 +585,14 @@ 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, - struct object_id *compat_oid_in, + 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; - const struct git_hash_algo *compat = source->odb->repo->compat_hash_algo; - struct object_id compat_oid; char hdr[MAX_HEADER_LEN]; size_t hdrlen = sizeof(hdr); - /* Generate compat_oid */ - if (compat) { - if (compat_oid_in) - oidcpy(&compat_oid, compat_oid_in); - else if (type == OBJ_BLOB) - hash_object_file(compat, buf, len, type, &compat_oid); - else { - struct strbuf converted = STRBUF_INIT; - convert_object_file(source->odb->repo, &converted, algo, compat, - buf, len, type, 0); - hash_object_file(compat, converted.buf, converted.len, - type, &compat_oid); - strbuf_release(&converted); - } - } - /* Normally if we have it in the pack then we do not bother writing * it out into .git/objects/??/?{38} file. */ @@ -619,8 +601,8 @@ static int odb_source_loose_write_object(struct odb_source *source, return 0; if (write_loose_object(loose, oid, hdr, hdrlen, buf, len, 0, flags)) return -1; - if (compat) - return repo_add_loose_object_map(loose, oid, &compat_oid); + if (compat_oid) + return repo_add_loose_object_map(loose, oid, compat_oid); return 0; } diff --git a/odb/source-packed.c b/odb/source-packed.c index 8d9ce197cc..af0d533375 100644 --- a/odb/source-packed.c +++ b/odb/source-packed.c @@ -530,7 +530,7 @@ static int odb_source_packed_write_object(struct odb_source *source UNUSED, size_t len UNUSED, enum object_type type UNUSED, struct object_id *oid UNUSED, - struct object_id *compat_oid UNUSED, + const struct object_id *compat_oid UNUSED, unsigned flags UNUSED) { return error("packed backend cannot write objects"); diff --git a/odb/source.h b/odb/source.h index cd63dba91f..b3c1ca3a66 100644 --- a/odb/source.h +++ b/odb/source.h @@ -207,7 +207,7 @@ struct odb_source { const void *buf, size_t len, enum object_type type, struct object_id *oid, - struct object_id *compat_oid, + const struct object_id *compat_oid, enum odb_write_object_flags flags); /* @@ -417,7 +417,7 @@ 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, - struct object_id *compat_oid, + const struct object_id *compat_oid, enum odb_write_object_flags flags) { return source->write_object(source, buf, len, type, oid,