]> git.ipfire.org Git - thirdparty/git.git/commitdiff
odb: compute compat object ID in `odb_write_object_ext()`
authorPatrick Steinhardt <ps@pks.im>
Fri, 17 Jul 2026 09:32:09 +0000 (11:32 +0200)
committerJunio C Hamano <gitster@pobox.com>
Sun, 19 Jul 2026 02:03:48 +0000 (19:03 -0700)
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 <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
odb.c
odb.h
odb/source-files.c
odb/source-inmemory.c
odb/source-loose.c
odb/source-packed.c
odb/source.h

diff --git a/odb.c b/odb.c
index cf6e7938c01e5682fee33f6b33da24ff7a53db3a..1d6538163b54eac10bfa1bbfa02f0ea50fb8ad6b 100644 (file)
--- 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 94754643d249970ba7224d72ba277783836e5272..066560113ebc780db34a0781dc627c4aa7df6743 100644 (file)
--- 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,
index 413875851135a5372ab758d85532a784f6ae153e..3d9f5eca327948dc31e9fca2d2376f71def889d5 100644 (file)
@@ -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);
index e47bfd8fccabf0d5381a240aabd5d51a586c7be1..e727aba427a17d8dc41214659bfdb1dc461771d9 100644 (file)
@@ -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);
index 3f7d04a56e36ce520e102fe686e1742b212288bd..ca223109cd46e434abae5e6acbe060956a735be8 100644 (file)
@@ -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;
 }
 
index 8d9ce197cc2be611bee71d13918fb92019e76404..af0d533375176fefd8bedf7102bf703b94b2b770 100644 (file)
@@ -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");
index cd63dba91f4e2f394f388804e9f877f1493adca6..b3c1ca3a6604fc2a3e58cad81ea18a8e377c37a4 100644 (file)
@@ -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,