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, ¶no_oid, NULL);
878
+ ret = end_loose_object_common(source, &c, NULL, &stream, ¶no_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)