]> git.ipfire.org Git - thirdparty/git.git/commitdiff
object-file: refactor writing objects to use loose source
authorPatrick Steinhardt <ps@pks.im>
Thu, 21 May 2026 08:22:35 +0000 (10:22 +0200)
committerJunio C Hamano <gitster@pobox.com>
Thu, 21 May 2026 13:35:20 +0000 (22:35 +0900)
The "object-file" subsystem still hosts the majority of logic used to
write loose objects. Eventually, we'll want to move this logic into
"odb/source-loose.c", but this isn't yet easily possible because a lot
of the writing logic is still being shared with `force_object_loose()`.

We will eventually detangle this logic so that we can indeed move all of
it into the "loose" source. Meanwhile though, refactor the code so that
it operates on a `struct odb_source_loose` directly to already make the
dependency explicit.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
http-walker.c
http.c
object-file.c
object-file.h
odb/source-files.c
odb/source-loose.c

index 1b6d496548373e3b4fd129a588d0aaaec784ece9..435a7265408fa4570881f86b98e94aa143bcced9 100644 (file)
@@ -539,8 +539,9 @@ static int fetch_object(struct walker *walker, const struct object_id *oid)
        } else if (!oideq(&obj_req->oid, &req->real_oid)) {
                ret = error("File %s has bad hash", hex);
        } else if (req->rename < 0) {
+               struct odb_source_files *files = odb_source_files_downcast(the_repository->objects->sources);
                struct strbuf buf = STRBUF_INIT;
-               odb_loose_path(the_repository->objects->sources, &buf, &req->oid);
+               odb_loose_path(files->loose, &buf, &req->oid);
                ret = error("unable to write sha1 filename %s", buf.buf);
                strbuf_release(&buf);
        }
diff --git a/http.c b/http.c
index ea9b16861bc3d4ef2c5c2a65b9c8b080ec018a84..3fcc0122337ba40af2f55c6fc1e7625ab0fecf0e 100644 (file)
--- a/http.c
+++ b/http.c
@@ -2826,6 +2826,7 @@ static size_t fwrite_sha1_file(char *ptr, size_t eltsize, size_t nmemb,
 struct http_object_request *new_http_object_request(const char *base_url,
                                                    const struct object_id *oid)
 {
+       struct odb_source_files *files = odb_source_files_downcast(the_repository->objects->sources);
        char *hex = oid_to_hex(oid);
        struct strbuf filename = STRBUF_INIT;
        struct strbuf prevfile = STRBUF_INIT;
@@ -2840,7 +2841,7 @@ struct http_object_request *new_http_object_request(const char *base_url,
        oidcpy(&freq->oid, oid);
        freq->localfile = -1;
 
-       odb_loose_path(the_repository->objects->sources, &filename, oid);
+       odb_loose_path(files->loose, &filename, oid);
        strbuf_addf(&freq->tmpfile, "%s.temp", filename.buf);
 
        strbuf_addf(&prevfile, "%s.prev", filename.buf);
@@ -2966,6 +2967,7 @@ void process_http_object_request(struct http_object_request *freq)
 
 int finish_http_object_request(struct http_object_request *freq)
 {
+       struct odb_source_files *files = odb_source_files_downcast(the_repository->objects->sources);
        struct stat st;
        struct strbuf filename = STRBUF_INIT;
 
@@ -2992,7 +2994,7 @@ int finish_http_object_request(struct http_object_request *freq)
                unlink_or_warn(freq->tmpfile.buf);
                return -1;
        }
-       odb_loose_path(the_repository->objects->sources, &filename, &freq->oid);
+       odb_loose_path(files->loose, &filename, &freq->oid);
        freq->rename = finalize_object_file(the_repository, freq->tmpfile.buf, filename.buf);
        strbuf_release(&filename);
 
index 7bb5b31bcad88b5d2f5ca6c03216923f4d656baa..bce941874eb994c8dbaf391ede6c84a09fa96f56 100644 (file)
@@ -54,14 +54,14 @@ static void fill_loose_path(struct strbuf *buf,
        }
 }
 
-const char *odb_loose_path(struct odb_source *source,
+const char *odb_loose_path(struct odb_source_loose *loose,
                           struct strbuf *buf,
                           const struct object_id *oid)
 {
        strbuf_reset(buf);
-       strbuf_addstr(buf, source->path);
+       strbuf_addstr(buf, loose->base.path);
        strbuf_addch(buf, '/');
-       fill_loose_path(buf, oid, source->odb->repo->hash_algo);
+       fill_loose_path(buf, oid, loose->base.odb->repo->hash_algo);
        return buf->buf;
 }
 
@@ -575,14 +575,14 @@ static void flush_loose_object_transaction(struct odb_transaction_files *transac
 }
 
 /* Finalize a file on disk, and close it. */
-static void close_loose_object(struct odb_source *source,
+static void close_loose_object(struct odb_source_loose *loose,
                               int fd, const char *filename)
 {
-       if (source->will_destroy)
+       if (loose->base.will_destroy)
                goto out;
 
        if (batch_fsync_enabled(FSYNC_COMPONENT_LOOSE_OBJECT))
-               fsync_loose_object_transaction(source->odb->transaction, fd, filename);
+               fsync_loose_object_transaction(loose->base.odb->transaction, fd, filename);
        else if (fsync_object_files > 0)
                fsync_or_die(fd, filename);
        else
@@ -651,7 +651,7 @@ static int create_tmpfile(struct repository *repo,
  * Returns a "fd", which should later be provided to
  * end_loose_object_common().
  */
-static int start_loose_object_common(struct odb_source *source,
+static int start_loose_object_common(struct odb_source_loose *loose,
                                     struct strbuf *tmp_file,
                                     const char *filename, unsigned flags,
                                     git_zstream *stream,
@@ -659,18 +659,18 @@ static int start_loose_object_common(struct odb_source *source,
                                     struct git_hash_ctx *c, struct git_hash_ctx *compat_c,
                                     char *hdr, int hdrlen)
 {
-       const struct git_hash_algo *algo = source->odb->repo->hash_algo;
-       const struct git_hash_algo *compat = source->odb->repo->compat_hash_algo;
+       const struct git_hash_algo *algo = loose->base.odb->repo->hash_algo;
+       const struct git_hash_algo *compat = loose->base.odb->repo->compat_hash_algo;
        int fd;
 
-       fd = create_tmpfile(source->odb->repo, tmp_file, filename);
+       fd = create_tmpfile(loose->base.odb->repo, tmp_file, filename);
        if (fd < 0) {
                if (flags & ODB_WRITE_OBJECT_SILENT)
                        return -1;
                else if (errno == EACCES)
                        return error(_("insufficient permission for adding "
                                       "an object to repository database %s"),
-                                    source->path);
+                                    loose->base.path);
                else
                        return error_errno(
                                _("unable to create temporary file"));
@@ -700,14 +700,14 @@ static int start_loose_object_common(struct odb_source *source,
  * Common steps for the inner git_deflate() loop for writing loose
  * objects. Returns what git_deflate() returns.
  */
-static int write_loose_object_common(struct odb_source *source,
+static int write_loose_object_common(struct odb_source_loose *loose,
                                     struct git_hash_ctx *c, struct git_hash_ctx *compat_c,
                                     git_zstream *stream, const int flush,
                                     unsigned char *in0, const int fd,
                                     unsigned char *compressed,
                                     const size_t compressed_len)
 {
-       const struct git_hash_algo *compat = source->odb->repo->compat_hash_algo;
+       const struct git_hash_algo *compat = loose->base.odb->repo->compat_hash_algo;
        int ret;
 
        ret = git_deflate(stream, flush ? Z_FINISH : 0);
@@ -728,12 +728,12 @@ static int write_loose_object_common(struct odb_source *source,
  * - End the compression of zlib stream.
  * - Get the calculated oid to "oid".
  */
-static int end_loose_object_common(struct odb_source *source,
+static int end_loose_object_common(struct odb_source_loose *loose,
                                   struct git_hash_ctx *c, struct git_hash_ctx *compat_c,
                                   git_zstream *stream, struct object_id *oid,
                                   struct object_id *compat_oid)
 {
-       const struct git_hash_algo *compat = source->odb->repo->compat_hash_algo;
+       const struct git_hash_algo *compat = loose->base.odb->repo->compat_hash_algo;
        int ret;
 
        ret = git_deflate_end_gently(stream);
@@ -746,7 +746,7 @@ static int end_loose_object_common(struct odb_source *source,
        return Z_OK;
 }
 
-int write_loose_object(struct odb_source *source,
+int write_loose_object(struct odb_source_loose *loose,
                       const struct object_id *oid, char *hdr,
                       int hdrlen, const void *buf, unsigned long len,
                       time_t mtime, unsigned flags)
@@ -760,11 +760,11 @@ int write_loose_object(struct odb_source *source,
        static struct strbuf filename = STRBUF_INIT;
 
        if (batch_fsync_enabled(FSYNC_COMPONENT_LOOSE_OBJECT))
-               prepare_loose_object_transaction(source->odb->transaction);
+               prepare_loose_object_transaction(loose->base.odb->transaction);
 
-       odb_loose_path(source, &filename, oid);
+       odb_loose_path(loose, &filename, oid);
 
-       fd = start_loose_object_common(source, &tmp_file, filename.buf, flags,
+       fd = start_loose_object_common(loose, &tmp_file, filename.buf, flags,
                                       &stream, compressed, sizeof(compressed),
                                       &c, NULL, hdr, hdrlen);
        if (fd < 0)
@@ -776,14 +776,14 @@ int write_loose_object(struct odb_source *source,
        do {
                unsigned char *in0 = stream.next_in;
 
-               ret = write_loose_object_common(source, &c, NULL, &stream, 1, in0, fd,
+               ret = write_loose_object_common(loose, &c, NULL, &stream, 1, in0, fd,
                                                compressed, sizeof(compressed));
        } while (ret == Z_OK);
 
        if (ret != Z_STREAM_END)
                die(_("unable to deflate new object %s (%d)"), oid_to_hex(oid),
                    ret);
-       ret = end_loose_object_common(source, &c, NULL, &stream, &parano_oid, NULL);
+       ret = end_loose_object_common(loose, &c, NULL, &stream, &parano_oid, NULL);
        if (ret != Z_OK)
                die(_("deflateEnd on object %s failed (%d)"), oid_to_hex(oid),
                    ret);
@@ -791,7 +791,7 @@ int write_loose_object(struct odb_source *source,
                die(_("confused by unstable object source data for %s"),
                    oid_to_hex(oid));
 
-       close_loose_object(source, fd, tmp_file.buf);
+       close_loose_object(loose, fd, tmp_file.buf);
 
        if (mtime) {
                struct utimbuf utb;
@@ -802,16 +802,15 @@ int write_loose_object(struct odb_source *source,
                        warning_errno(_("failed utime() on %s"), tmp_file.buf);
        }
 
-       return finalize_object_file_flags(source->odb->repo, tmp_file.buf, filename.buf,
+       return finalize_object_file_flags(loose->base.odb->repo, tmp_file.buf, filename.buf,
                                          FOF_SKIP_COLLISION_CHECK);
 }
 
-int odb_source_loose_write_stream(struct odb_source *source,
+int odb_source_loose_write_stream(struct odb_source_loose *loose,
                                  struct odb_write_stream *in_stream, size_t len,
                                  struct object_id *oid)
 {
-       struct odb_source_files *files = odb_source_files_downcast(source);
-       const struct git_hash_algo *compat = source->odb->repo->compat_hash_algo;
+       const struct git_hash_algo *compat = loose->base.odb->repo->compat_hash_algo;
        struct object_id compat_oid;
        int fd, ret, err = 0, flush = 0;
        unsigned char compressed[4096];
@@ -825,10 +824,10 @@ int odb_source_loose_write_stream(struct odb_source *source,
        int hdrlen;
 
        if (batch_fsync_enabled(FSYNC_COMPONENT_LOOSE_OBJECT))
-               prepare_loose_object_transaction(source->odb->transaction);
+               prepare_loose_object_transaction(loose->base.odb->transaction);
 
        /* Since oid is not determined, save tmp file to odb path. */
-       strbuf_addf(&filename, "%s/", source->path);
+       strbuf_addf(&filename, "%s/", loose->base.path);
        hdrlen = format_object_header(hdr, sizeof(hdr), OBJ_BLOB, len);
 
        /*
@@ -839,7 +838,7 @@ int odb_source_loose_write_stream(struct odb_source *source,
         *  - Setup zlib stream for compression.
         *  - Start to feed header to zlib stream.
         */
-       fd = start_loose_object_common(source, &tmp_file, filename.buf, 0,
+       fd = start_loose_object_common(loose, &tmp_file, filename.buf, 0,
                                       &stream, compressed, sizeof(compressed),
                                       &c, &compat_c, hdr, hdrlen);
        if (fd < 0) {
@@ -867,7 +866,7 @@ int odb_source_loose_write_stream(struct odb_source *source,
                        if (in_stream->is_finished)
                                flush = 1;
                }
-               ret = write_loose_object_common(source, &c, &compat_c, &stream, flush, in0, fd,
+               ret = write_loose_object_common(loose, &c, &compat_c, &stream, flush, in0, fd,
                                                compressed, sizeof(compressed));
                /*
                 * Unlike write_loose_object(), we do not have the entire
@@ -890,16 +889,16 @@ int odb_source_loose_write_stream(struct odb_source *source,
         */
        if (ret != Z_STREAM_END)
                die(_("unable to stream deflate new object (%d)"), ret);
-       ret = end_loose_object_common(source, &c, &compat_c, &stream, oid, &compat_oid);
+       ret = end_loose_object_common(loose, &c, &compat_c, &stream, oid, &compat_oid);
        if (ret != Z_OK)
                die(_("deflateEnd on stream object failed (%d)"), ret);
-       close_loose_object(source, fd, tmp_file.buf);
+       close_loose_object(loose, fd, tmp_file.buf);
 
-       if (odb_freshen_object(source->odb, oid)) {
+       if (odb_freshen_object(loose->base.odb, oid)) {
                unlink_or_warn(tmp_file.buf);
                goto cleanup;
        }
-       odb_loose_path(source, &filename, oid);
+       odb_loose_path(loose, &filename, oid);
 
        /* We finally know the object path, and create the missing dir. */
        dirlen = directory_size(filename.buf);
@@ -907,7 +906,7 @@ int odb_source_loose_write_stream(struct odb_source *source,
                struct strbuf dir = STRBUF_INIT;
                strbuf_add(&dir, filename.buf, dirlen);
 
-               if (safe_create_dir_in_gitdir(source->odb->repo, dir.buf) &&
+               if (safe_create_dir_in_gitdir(loose->base.odb->repo, dir.buf) &&
                    errno != EEXIST) {
                        err = error_errno(_("unable to create directory %s"), dir.buf);
                        strbuf_release(&dir);
@@ -916,10 +915,10 @@ int odb_source_loose_write_stream(struct odb_source *source,
                strbuf_release(&dir);
        }
 
-       err = finalize_object_file_flags(source->odb->repo, tmp_file.buf, filename.buf,
+       err = finalize_object_file_flags(loose->base.odb->repo, tmp_file.buf, filename.buf,
                                         FOF_SKIP_COLLISION_CHECK);
        if (!err && compat)
-               err = repo_add_loose_object_map(files->loose, oid, &compat_oid);
+               err = repo_add_loose_object_map(loose, oid, &compat_oid);
 cleanup:
        strbuf_release(&tmp_file);
        strbuf_release(&filename);
@@ -957,7 +956,7 @@ int force_object_loose(struct odb_source *source,
                                     oid_to_hex(oid), compat->name);
        }
        hdrlen = format_object_header(hdr, sizeof(hdr), type, len);
-       ret = write_loose_object(source, oid, hdr, hdrlen, buf, len, mtime, 0);
+       ret = write_loose_object(files->loose, oid, hdr, hdrlen, buf, len, mtime, 0);
        if (!ret && compat)
                ret = repo_add_loose_object_map(files->loose, oid, &compat_oid);
        free(buf);
index 2b32592de1135b0afdbed1b9c85381236ed99d42..d30f1b10b2eb36ba1ed1b65be2a3444577ee291f 100644 (file)
@@ -23,7 +23,7 @@ int index_path(struct index_state *istate, struct object_id *oid, const char *pa
 struct object_info;
 struct odb_source;
 
-int odb_source_loose_write_stream(struct odb_source *source,
+int odb_source_loose_write_stream(struct odb_source_loose *loose,
                                  struct odb_write_stream *stream, size_t len,
                                  struct object_id *oid);
 
@@ -31,7 +31,7 @@ int odb_source_loose_write_stream(struct odb_source *source,
  * Put in `buf` the name of the file in the local object database that
  * would be used to store a loose object with the specified oid.
  */
-const char *odb_loose_path(struct odb_source *source,
+const char *odb_loose_path(struct odb_source_loose *source,
                           struct strbuf *buf,
                           const struct object_id *oid);
 
@@ -127,7 +127,7 @@ void write_object_file_prepare(const struct git_hash_algo *algo,
                               const void *buf, unsigned long len,
                               enum object_type type, struct object_id *oid,
                               char *hdr, int *hdrlen);
-int write_loose_object(struct odb_source *source,
+int write_loose_object(struct odb_source_loose *loose,
                       const struct object_id *oid, char *hdr,
                       int hdrlen, const void *buf, unsigned long len,
                       time_t mtime, unsigned flags);
index 52ba04237acfd715697f36a761ab1490006a2cbf..2ba1def776e006c2600abedee9f1a47bf31bb4fd 100644 (file)
@@ -174,7 +174,8 @@ static int odb_source_files_write_object_stream(struct odb_source *source,
                                                size_t len,
                                                struct object_id *oid)
 {
-       return odb_source_loose_write_stream(source, stream, len, oid);
+       struct odb_source_files *files = odb_source_files_downcast(source);
+       return odb_source_loose_write_stream(files->loose, stream, len, oid);
 }
 
 static int odb_source_files_begin_transaction(struct odb_source *source,
index c91018109e5b6836f7312b0f4e48b58d2e54921a..da8a60dba1c04c9b7d4f944dedbc081515b01ad5 100644 (file)
@@ -220,7 +220,7 @@ static int odb_source_loose_read_object_info(struct odb_source *source,
        if (flags & OBJECT_INFO_SECOND_READ)
                return -1;
 
-       odb_loose_path(source, &buf, oid);
+       odb_loose_path(loose, &buf, oid);
        return read_object_info_from_path(loose, buf.buf, oid, oi, flags);
 }
 
@@ -238,7 +238,7 @@ static int open_loose_object(struct odb_source_loose *loose,
        static struct strbuf buf = STRBUF_INIT;
        int fd;
 
-       *path = odb_loose_path(&loose->base, &buf, oid);
+       *path = odb_loose_path(loose, &buf, oid);
        fd = git_open(*path);
        if (fd >= 0)
                return fd;
@@ -584,8 +584,9 @@ out:
 static int odb_source_loose_freshen_object(struct odb_source *source,
                                           const struct object_id *oid)
 {
+       struct odb_source_loose *loose = odb_source_loose_downcast(source);
        static struct strbuf path = STRBUF_INIT;
-       odb_loose_path(source, &path, oid);
+       odb_loose_path(loose, &path, oid);
        return !!check_and_freshen_file(path.buf, 1);
 }
 
@@ -624,7 +625,7 @@ static int odb_source_loose_write_object(struct odb_source *source,
        write_object_file_prepare(algo, buf, len, type, oid, hdr, &hdrlen);
        if (odb_freshen_object(source->odb, oid))
                return 0;
-       if (write_loose_object(source, oid, hdr, hdrlen, buf, len, 0, flags))
+       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);