odb/source-loose: wire up `write_object()` callback

Move `odb_source_loose_write_object()` from "object-file.c" into "odb/source-loose.c" and wire it up as the `write_object()` callback of the loose source. As in preceding commits, this requires us to expose a couple of generic functions from "object-file.c" as they are used in both subsystems now. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed Jun 1, 2026 at 10:20 UTC 04a6e84cbdbebadd01d939168f1c69680c174fce
4 files changed +63 -58
object-file.c
+8 -50
@@ -326,10 +326,10 @@ static void hash_object_body(const struct git_hash_algo *algo, struct git_hash_c
326 git_hash_final_oid(oid, c);
327 }
328
329 -static void write_object_file_prepare(const struct git_hash_algo *algo,
330 - const void *buf, unsigned long len,
331 - enum object_type type, struct object_id *oid,
332 - char *hdr, int *hdrlen)
329 +void write_object_file_prepare(const struct git_hash_algo *algo,
330 + const void *buf, unsigned long len,
331 + enum object_type type, struct object_id *oid,
332 + char *hdr, int *hdrlen)
333 {
334 struct git_hash_ctx c;
335
@@ -746,10 +746,10 @@ static int end_loose_object_common(struct odb_source *source,
746 return Z_OK;
747 }
748
749 -static int write_loose_object(struct odb_source *source,
750 - const struct object_id *oid, char *hdr,
751 - int hdrlen, const void *buf, unsigned long len,
752 - time_t mtime, unsigned flags)
749 +int write_loose_object(struct odb_source *source,
750 + const struct object_id *oid, char *hdr,
751 + int hdrlen, const void *buf, unsigned long len,
752 + time_t mtime, unsigned flags)
753 {
754 int fd, ret;
755 unsigned char compressed[4096];
@@ -926,48 +926,6 @@ cleanup:
926 return err;
927 }
928
929 -int odb_source_loose_write_object(struct odb_source *source,
930 - const void *buf, unsigned long len,
931 - enum object_type type, struct object_id *oid,
932 - struct object_id *compat_oid_in,
933 - enum odb_write_object_flags flags)
934 -{
935 - struct odb_source_files *files = odb_source_files_downcast(source);
936 - const struct git_hash_algo *algo = source->odb->repo->hash_algo;
937 - const struct git_hash_algo *compat = source->odb->repo->compat_hash_algo;
938 - struct object_id compat_oid;
939 - char hdr[MAX_HEADER_LEN];
940 - int hdrlen = sizeof(hdr);
941 -
942 - /* Generate compat_oid */
943 - if (compat) {
944 - if (compat_oid_in)
945 - oidcpy(&compat_oid, compat_oid_in);
946 - else if (type == OBJ_BLOB)
947 - hash_object_file(compat, buf, len, type, &compat_oid);
948 - else {
949 - struct strbuf converted = STRBUF_INIT;
950 - convert_object_file(source->odb->repo, &converted, algo, compat,
951 - buf, len, type, 0);
952 - hash_object_file(compat, converted.buf, converted.len,
953 - type, &compat_oid);
954 - strbuf_release(&converted);
955 - }
956 - }
957 -
958 - /* Normally if we have it in the pack then we do not bother writing
959 - * it out into .git/objects/??/?{38} file.
960 - */
961 - write_object_file_prepare(algo, buf, len, type, oid, hdr, &hdrlen);
962 - if (odb_freshen_object(source->odb, oid))
963 - return 0;
964 - if (write_loose_object(source, oid, hdr, hdrlen, buf, len, 0, flags))
965 - return -1;
966 - if (compat)
967 - return repo_add_loose_object_map(files->loose, oid, &compat_oid);
968 - return 0;
969 -}
970 -
929 int force_object_loose(struct odb_source *source,
930 const struct object_id *oid, time_t mtime)
931 {
object-file.h
+8 -6
@@ -23,12 +23,6 @@ int index_path(struct index_state *istate, struct object_id *oid, const char *pa
23 struct object_info;
24 struct odb_source;
25
26 -int odb_source_loose_write_object(struct odb_source *source,
27 - const void *buf, unsigned long len,
28 - enum object_type type, struct object_id *oid,
29 - struct object_id *compat_oid_in,
30 - enum odb_write_object_flags flags);
31 -
26 int odb_source_loose_write_stream(struct odb_source *source,
27 struct odb_write_stream *stream, size_t len,
28 struct object_id *oid);
@@ -129,6 +123,14 @@ int finalize_object_file_flags(struct repository *repo,
123 void hash_object_file(const struct git_hash_algo *algo, const void *buf,
124 unsigned long len, enum object_type type,
125 struct object_id *oid);
126 +void write_object_file_prepare(const struct git_hash_algo *algo,
127 + const void *buf, unsigned long len,
128 + enum object_type type, struct object_id *oid,
129 + char *hdr, int *hdrlen);
130 +int write_loose_object(struct odb_source *source,
131 + const struct object_id *oid, char *hdr,
132 + int hdrlen, const void *buf, unsigned long len,
133 + time_t mtime, unsigned flags);
134
135 /* Helper to check and "touch" a file */
136 int check_and_freshen_file(const char *fn, int freshen);
odb/source-files.c
+3 -2
@@ -164,8 +164,9 @@ static int odb_source_files_write_object(struct odb_source *source,
164 struct object_id *compat_oid,
165 enum odb_write_object_flags flags)
166 {
167 - return odb_source_loose_write_object(source, buf, len, type,
168 - oid, compat_oid, flags);
167 + struct odb_source_files *files = odb_source_files_downcast(source);
168 + return odb_source_write_object(&files->loose->base, buf, len, type,
169 + oid, compat_oid, flags);
170 }
171
172 static int odb_source_files_write_object_stream(struct odb_source *source,
odb/source-loose.c
+44
@@ -5,6 +5,7 @@
5 #include "hex.h"
6 #include "loose.h"
7 #include "object-file.h"
8 +#include "object-file-convert.h"
9 #include "odb.h"
10 #include "odb/source-files.h"
11 #include "odb/source-loose.h"
@@ -588,6 +589,48 @@ static int odb_source_loose_freshen_object(struct odb_source *source,
589 return !!check_and_freshen_file(path.buf, 1);
590 }
591
592 +static int odb_source_loose_write_object(struct odb_source *source,
593 + const void *buf, unsigned long len,
594 + enum object_type type, struct object_id *oid,
595 + struct object_id *compat_oid_in,
596 + enum odb_write_object_flags flags)
597 +{
598 + struct odb_source_loose *loose = odb_source_loose_downcast(source);
599 + const struct git_hash_algo *algo = source->odb->repo->hash_algo;
600 + const struct git_hash_algo *compat = source->odb->repo->compat_hash_algo;
601 + struct object_id compat_oid;
602 + char hdr[MAX_HEADER_LEN];
603 + int hdrlen = sizeof(hdr);
604 +
605 + /* Generate compat_oid */
606 + if (compat) {
607 + if (compat_oid_in)
608 + oidcpy(&compat_oid, compat_oid_in);
609 + else if (type == OBJ_BLOB)
610 + hash_object_file(compat, buf, len, type, &compat_oid);
611 + else {
612 + struct strbuf converted = STRBUF_INIT;
613 + convert_object_file(source->odb->repo, &converted, algo, compat,
614 + buf, len, type, 0);
615 + hash_object_file(compat, converted.buf, converted.len,
616 + type, &compat_oid);
617 + strbuf_release(&converted);
618 + }
619 + }
620 +
621 + /* Normally if we have it in the pack then we do not bother writing
622 + * it out into .git/objects/??/?{38} file.
623 + */
624 + write_object_file_prepare(algo, buf, len, type, oid, hdr, &hdrlen);
625 + if (odb_freshen_object(source->odb, oid))
626 + return 0;
627 + if (write_loose_object(source, oid, hdr, hdrlen, buf, len, 0, flags))
628 + return -1;
629 + if (compat)
630 + return repo_add_loose_object_map(loose, oid, &compat_oid);
631 + return 0;
632 +}
633 +
634 static void odb_source_loose_clear_cache(struct odb_source_loose *loose)
635 {
636 oidtree_clear(loose->cache);
@@ -647,6 +690,7 @@ struct odb_source_loose *odb_source_loose_new(struct odb_source_files *files)
690 loose->base.find_abbrev_len = odb_source_loose_find_abbrev_len;
691 loose->base.count_objects = odb_source_loose_count_objects;
692 loose->base.freshen_object = odb_source_loose_freshen_object;
693 + loose->base.write_object = odb_source_loose_write_object;
694
695 if (!is_absolute_path(loose->base.path))
696 chdir_notify_register(NULL, odb_source_loose_reparent, loose);