object-file: get rid of `the_repository` when writing objects

The logic that writes loose objects still relies on `the_repository` to decide where exactly the object shall be written to. Refactor it so that the logic instead operates on a `struct odb_source` so that we can get rid of this global dependency. Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Patrick Steinhardt committed Jul 17, 2025 at 06:56 UTC e7e952f5c27bbca3d98bbcea6d20cd5b63d7d8e5
4 files changed +58 -51
builtin/unpack-objects.c
+2 -1
@@ -403,7 +403,8 @@ static void stream_blob(unsigned long size, unsigned nr)
403 data.zstream = &zstream;
404 git_inflate_init(&zstream);
405
406 - if (stream_loose_object(&in_stream, size, &info->oid))
406 + if (stream_loose_object(the_repository->objects->sources,
407 + &in_stream, size, &info->oid))
408 die(_("failed to write object in stream"));
409
410 if (data.status != Z_STREAM_END)
object-file.c
+50 -46
@@ -667,9 +667,10 @@ void hash_object_file(const struct git_hash_algo *algo, const void *buf,
667 }
668
669 /* Finalize a file on disk, and close it. */
670 -static void close_loose_object(int fd, const char *filename)
670 +static void close_loose_object(struct odb_source *source,
671 + int fd, const char *filename)
672 {
672 - if (the_repository->objects->sources->will_destroy)
673 + if (source->will_destroy)
674 goto out;
675
676 if (batch_fsync_enabled(FSYNC_COMPONENT_LOOSE_OBJECT))
@@ -701,7 +702,8 @@ static inline int directory_size(const char *filename)
702 * We want to avoid cross-directory filename renames, because those
703 * can have problems on various filesystems (FAT, NFS, Coda).
704 */
704 -static int create_tmpfile(struct strbuf *tmp, const char *filename)
705 +static int create_tmpfile(struct repository *repo,
706 + struct strbuf *tmp, const char *filename)
707 {
708 int fd, dirlen = directory_size(filename);
709
@@ -720,7 +722,7 @@ static int create_tmpfile(struct strbuf *tmp, const char *filename)
722 strbuf_add(tmp, filename, dirlen - 1);
723 if (mkdir(tmp->buf, 0777) && errno != EEXIST)
724 return -1;
723 - if (adjust_shared_perm(the_repository, tmp->buf))
725 + if (adjust_shared_perm(repo, tmp->buf))
726 return -1;
727
728 /* Try again */
@@ -741,26 +743,26 @@ static int create_tmpfile(struct strbuf *tmp, const char *filename)
743 * Returns a "fd", which should later be provided to
744 * end_loose_object_common().
745 */
744 -static int start_loose_object_common(struct strbuf *tmp_file,
746 +static int start_loose_object_common(struct odb_source *source,
747 + struct strbuf *tmp_file,
748 const char *filename, unsigned flags,
749 git_zstream *stream,
750 unsigned char *buf, size_t buflen,
751 struct git_hash_ctx *c, struct git_hash_ctx *compat_c,
752 char *hdr, int hdrlen)
753 {
751 - struct repository *repo = the_repository;
752 - const struct git_hash_algo *algo = repo->hash_algo;
753 - const struct git_hash_algo *compat = repo->compat_hash_algo;
754 + const struct git_hash_algo *algo = source->odb->repo->hash_algo;
755 + const struct git_hash_algo *compat = source->odb->repo->compat_hash_algo;
756 int fd;
757
756 - fd = create_tmpfile(tmp_file, filename);
758 + fd = create_tmpfile(source->odb->repo, tmp_file, filename);
759 if (fd < 0) {
760 if (flags & WRITE_OBJECT_SILENT)
761 return -1;
762 else if (errno == EACCES)
763 return error(_("insufficient permission for adding "
764 "an object to repository database %s"),
763 - repo_get_object_directory(the_repository));
765 + source->path);
766 else
767 return error_errno(
768 _("unable to create temporary file"));
@@ -790,14 +792,14 @@ static int start_loose_object_common(struct strbuf *tmp_file,
792 * Common steps for the inner git_deflate() loop for writing loose
793 * objects. Returns what git_deflate() returns.
794 */
793 -static int write_loose_object_common(struct git_hash_ctx *c, struct git_hash_ctx *compat_c,
795 +static int write_loose_object_common(struct odb_source *source,
796 + struct git_hash_ctx *c, struct git_hash_ctx *compat_c,
797 git_zstream *stream, const int flush,
798 unsigned char *in0, const int fd,
799 unsigned char *compressed,
800 const size_t compressed_len)
801 {
799 - struct repository *repo = the_repository;
800 - const struct git_hash_algo *compat = repo->compat_hash_algo;
802 + const struct git_hash_algo *compat = source->odb->repo->compat_hash_algo;
803 int ret;
804
805 ret = git_deflate(stream, flush ? Z_FINISH : 0);
@@ -818,12 +820,12 @@ static int write_loose_object_common(struct git_hash_ctx *c, struct git_hash_ctx
820 * - End the compression of zlib stream.
821 * - Get the calculated oid to "oid".
822 */
821 -static int end_loose_object_common(struct git_hash_ctx *c, struct git_hash_ctx *compat_c,
823 +static int end_loose_object_common(struct odb_source *source,
824 + struct git_hash_ctx *c, struct git_hash_ctx *compat_c,
825 git_zstream *stream, struct object_id *oid,
826 struct object_id *compat_oid)
827 {
825 - struct repository *repo = the_repository;
826 - const struct git_hash_algo *compat = repo->compat_hash_algo;
828 + const struct git_hash_algo *compat = source->odb->repo->compat_hash_algo;
829 int ret;
830
831 ret = git_deflate_end_gently(stream);
@@ -836,7 +838,8 @@ static int end_loose_object_common(struct git_hash_ctx *c, struct git_hash_ctx *
838 return Z_OK;
839 }
840
839 -static int write_loose_object(const struct object_id *oid, char *hdr,
841 +static int write_loose_object(struct odb_source *source,
842 + const struct object_id *oid, char *hdr,
843 int hdrlen, const void *buf, unsigned long len,
844 time_t mtime, unsigned flags)
845 {
@@ -851,9 +854,9 @@ static int write_loose_object(const struct object_id *oid, char *hdr,
854 if (batch_fsync_enabled(FSYNC_COMPONENT_LOOSE_OBJECT))
855 prepare_loose_object_bulk_checkin();
856
854 - odb_loose_path(the_repository->objects->sources, &filename, oid);
857 + odb_loose_path(source, &filename, oid);
858
856 - fd = start_loose_object_common(&tmp_file, filename.buf, flags,
859 + fd = start_loose_object_common(source, &tmp_file, filename.buf, flags,
860 &stream, compressed, sizeof(compressed),
861 &c, NULL, hdr, hdrlen);
862 if (fd < 0)
@@ -865,14 +868,14 @@ static int write_loose_object(const struct object_id *oid, char *hdr,
868 do {
869 unsigned char *in0 = stream.next_in;
870
868 - ret = write_loose_object_common(&c, NULL, &stream, 1, in0, fd,
871 + ret = write_loose_object_common(source, &c, NULL, &stream, 1, in0, fd,
872 compressed, sizeof(compressed));
873 } while (ret == Z_OK);
874
875 if (ret != Z_STREAM_END)
876 die(_("unable to deflate new object %s (%d)"), oid_to_hex(oid),
877 ret);
875 - ret = end_loose_object_common(&c, NULL, &stream, &parano_oid, NULL);
878 + ret = end_loose_object_common(source, &c, NULL, &stream, &parano_oid, NULL);
879 if (ret != Z_OK)
880 die(_("deflateEnd on object %s failed (%d)"), oid_to_hex(oid),
881 ret);
@@ -880,7 +883,7 @@ static int write_loose_object(const struct object_id *oid, char *hdr,
883 die(_("confused by unstable object source data for %s"),
884 oid_to_hex(oid));
885
883 - close_loose_object(fd, tmp_file.buf);
886 + close_loose_object(source, fd, tmp_file.buf);
887
888 if (mtime) {
889 struct utimbuf utb;
@@ -891,7 +894,7 @@ static int write_loose_object(const struct object_id *oid, char *hdr,
894 warning_errno(_("failed utime() on %s"), tmp_file.buf);
895 }
896
894 - return finalize_object_file_flags(the_repository, tmp_file.buf, filename.buf,
897 + return finalize_object_file_flags(source->odb->repo, tmp_file.buf, filename.buf,
898 FOF_SKIP_COLLISION_CHECK);
899 }
900
@@ -921,10 +924,11 @@ static int freshen_packed_object(struct object_database *odb,
924 return 1;
925 }
926
924 -int stream_loose_object(struct input_stream *in_stream, size_t len,
927 +int stream_loose_object(struct odb_source *source,
928 + struct input_stream *in_stream, size_t len,
929 struct object_id *oid)
930 {
927 - const struct git_hash_algo *compat = the_repository->compat_hash_algo;
931 + const struct git_hash_algo *compat = source->odb->repo->compat_hash_algo;
932 struct object_id compat_oid;
933 int fd, ret, err = 0, flush = 0;
934 unsigned char compressed[4096];
@@ -940,7 +944,7 @@ int stream_loose_object(struct input_stream *in_stream, size_t len,
944 prepare_loose_object_bulk_checkin();
945
946 /* Since oid is not determined, save tmp file to odb path. */
943 - strbuf_addf(&filename, "%s/", repo_get_object_directory(the_repository));
947 + strbuf_addf(&filename, "%s/", source->path);
948 hdrlen = format_object_header(hdr, sizeof(hdr), OBJ_BLOB, len);
949
950 /*
@@ -951,7 +955,7 @@ int stream_loose_object(struct input_stream *in_stream, size_t len,
955 * - Setup zlib stream for compression.
956 * - Start to feed header to zlib stream.
957 */
954 - fd = start_loose_object_common(&tmp_file, filename.buf, 0,
958 + fd = start_loose_object_common(source, &tmp_file, filename.buf, 0,
959 &stream, compressed, sizeof(compressed),
960 &c, &compat_c, hdr, hdrlen);
961 if (fd < 0) {
@@ -971,7 +975,7 @@ int stream_loose_object(struct input_stream *in_stream, size_t len,
975 if (in_stream->is_finished)
976 flush = 1;
977 }
974 - ret = write_loose_object_common(&c, &compat_c, &stream, flush, in0, fd,
978 + ret = write_loose_object_common(source, &c, &compat_c, &stream, flush, in0, fd,
979 compressed, sizeof(compressed));
980 /*
981 * Unlike write_loose_object(), we do not have the entire
@@ -994,18 +998,18 @@ int stream_loose_object(struct input_stream *in_stream, size_t len,
998 */
999 if (ret != Z_STREAM_END)
1000 die(_("unable to stream deflate new object (%d)"), ret);
997 - ret = end_loose_object_common(&c, &compat_c, &stream, oid, &compat_oid);
1001 + ret = end_loose_object_common(source, &c, &compat_c, &stream, oid, &compat_oid);
1002 if (ret != Z_OK)
1003 die(_("deflateEnd on stream object failed (%d)"), ret);
1000 - close_loose_object(fd, tmp_file.buf);
1004 + close_loose_object(source, fd, tmp_file.buf);
1005
1002 - if (freshen_packed_object(the_repository->objects, oid) ||
1003 - freshen_loose_object(the_repository->objects, oid)) {
1006 + if (freshen_packed_object(source->odb, oid) ||
1007 + freshen_loose_object(source->odb, oid)) {
1008 unlink_or_warn(tmp_file.buf);
1009 goto cleanup;
1010 }
1011
1008 - odb_loose_path(the_repository->objects->sources, &filename, oid);
1012 + odb_loose_path(source, &filename, oid);
1013
1014 /* We finally know the object path, and create the missing dir. */
1015 dirlen = directory_size(filename.buf);
@@ -1013,7 +1017,7 @@ int stream_loose_object(struct input_stream *in_stream, size_t len,
1017 struct strbuf dir = STRBUF_INIT;
1018 strbuf_add(&dir, filename.buf, dirlen);
1019
1016 - if (safe_create_dir_in_gitdir(the_repository, dir.buf) &&
1020 + if (safe_create_dir_in_gitdir(source->odb->repo, dir.buf) &&
1021 errno != EEXIST) {
1022 err = error_errno(_("unable to create directory %s"), dir.buf);
1023 strbuf_release(&dir);
@@ -1022,23 +1026,23 @@ int stream_loose_object(struct input_stream *in_stream, size_t len,
1026 strbuf_release(&dir);
1027 }
1028
1025 - err = finalize_object_file_flags(the_repository, tmp_file.buf, filename.buf,
1029 + err = finalize_object_file_flags(source->odb->repo, tmp_file.buf, filename.buf,
1030 FOF_SKIP_COLLISION_CHECK);
1031 if (!err && compat)
1028 - err = repo_add_loose_object_map(the_repository->objects->sources, oid, &compat_oid);
1032 + err = repo_add_loose_object_map(source, oid, &compat_oid);
1033 cleanup:
1034 strbuf_release(&tmp_file);
1035 strbuf_release(&filename);
1036 return err;
1037 }
1038
1035 -int write_object_file(const void *buf, unsigned long len,
1039 +int write_object_file(struct odb_source *source,
1040 + const void *buf, unsigned long len,
1041 enum object_type type, struct object_id *oid,
1042 struct object_id *compat_oid_in, unsigned flags)
1043 {
1039 - struct repository *repo = the_repository;
1040 - const struct git_hash_algo *algo = repo->hash_algo;
1041 - const struct git_hash_algo *compat = repo->compat_hash_algo;
1044 + const struct git_hash_algo *algo = source->odb->repo->hash_algo;
1045 + const struct git_hash_algo *compat = source->odb->repo->compat_hash_algo;
1046 struct object_id compat_oid;
1047 char hdr[MAX_HEADER_LEN];
1048 int hdrlen = sizeof(hdr);
@@ -1051,7 +1055,7 @@ int write_object_file(const void *buf, unsigned long len,
1055 hash_object_file(compat, buf, len, type, &compat_oid);
1056 else {
1057 struct strbuf converted = STRBUF_INIT;
1054 - convert_object_file(the_repository, &converted, algo, compat,
1058 + convert_object_file(source->odb->repo, &converted, algo, compat,
1059 buf, len, type, 0);
1060 hash_object_file(compat, converted.buf, converted.len,
1061 type, &compat_oid);
@@ -1063,13 +1067,13 @@ int write_object_file(const void *buf, unsigned long len,
1067 * it out into .git/objects/??/?{38} file.
1068 */
1069 write_object_file_prepare(algo, buf, len, type, oid, hdr, &hdrlen);
1066 - if (freshen_packed_object(repo->objects, oid) ||
1067 - freshen_loose_object(repo->objects, oid))
1070 + if (freshen_packed_object(source->odb, oid) ||
1071 + freshen_loose_object(source->odb, oid))
1072 return 0;
1069 - if (write_loose_object(oid, hdr, hdrlen, buf, len, 0, flags))
1073 + if (write_loose_object(source, oid, hdr, hdrlen, buf, len, 0, flags))
1074 return -1;
1075 if (compat)
1072 - return repo_add_loose_object_map(repo->objects->sources, oid, &compat_oid);
1076 + return repo_add_loose_object_map(source, oid, &compat_oid);
1077 return 0;
1078 }
1079
@@ -1101,7 +1105,7 @@ int force_object_loose(const struct object_id *oid, time_t mtime)
1105 oid_to_hex(oid), compat->name);
1106 }
1107 hdrlen = format_object_header(hdr, sizeof(hdr), type, len);
1104 - ret = write_loose_object(oid, hdr, hdrlen, buf, len, mtime, 0);
1108 + ret = write_loose_object(repo->objects->sources, oid, hdr, hdrlen, buf, len, mtime, 0);
1109 if (!ret && compat)
1110 ret = repo_add_loose_object_map(the_repository->objects->sources, oid, &compat_oid);
1111 free(buf);
object-file.h
+4 -2
@@ -157,7 +157,8 @@ enum unpack_loose_header_result unpack_loose_header(git_zstream *stream,
157 struct object_info;
158 int parse_loose_header(const char *hdr, struct object_info *oi);
159
160 -int write_object_file(const void *buf, unsigned long len,
160 +int write_object_file(struct odb_source *source,
161 + const void *buf, unsigned long len,
162 enum object_type type, struct object_id *oid,
163 struct object_id *compat_oid_in, unsigned flags);
164
@@ -167,7 +168,8 @@ struct input_stream {
168 int is_finished;
169 };
170
170 -int stream_loose_object(struct input_stream *in_stream, size_t len,
171 +int stream_loose_object(struct odb_source *source,
172 + struct input_stream *in_stream, size_t len,
173 struct object_id *oid);
174
175 int force_object_loose(const struct object_id *oid, time_t mtime);
odb.c
+2 -2
@@ -980,14 +980,14 @@ void odb_assert_oid_type(struct object_database *odb,
980 type_name(expect));
981 }
982
983 -int odb_write_object_ext(struct object_database *odb UNUSED,
983 +int odb_write_object_ext(struct object_database *odb,
984 const void *buf, unsigned long len,
985 enum object_type type,
986 struct object_id *oid,
987 struct object_id *compat_oid,
988 unsigned flags)
989 {
990 - return write_object_file(buf, len, type, oid, compat_oid, flags);
990 + return write_object_file(odb->sources, buf, len, type, oid, compat_oid, flags);
991 }
992
993 struct object_database *odb_new(struct repository *repo)