From: Patrick Steinhardt Date: Mon, 1 Jun 2026 08:20:38 +0000 (+0200) Subject: object-file: refactor writing objects to use loose source X-Git-Url: http://git.ipfire.org/gitweb/index.cgi?a=commitdiff_plain;h=b9906a645c38ef77643d661ac9a5a6aa31fbeaf4;p=thirdparty%2Fgit.git object-file: refactor writing objects to use loose source 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 Signed-off-by: Junio C Hamano --- diff --git a/http-walker.c b/http-walker.c index 1b6d496548..435a726540 100644 --- a/http-walker.c +++ b/http-walker.c @@ -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 ea9b16861b..3fcc012233 100644 --- 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); diff --git a/object-file.c b/object-file.c index 7bb5b31bca..bce941874e 100644 --- a/object-file.c +++ b/object-file.c @@ -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, ¶no_oid, NULL); + ret = end_loose_object_common(loose, &c, NULL, &stream, ¶no_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); diff --git a/object-file.h b/object-file.h index 2b32592de1..d30f1b10b2 100644 --- a/object-file.h +++ b/object-file.h @@ -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); diff --git a/odb/source-files.c b/odb/source-files.c index 52ba04237a..2ba1def776 100644 --- a/odb/source-files.c +++ b/odb/source-files.c @@ -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, diff --git a/odb/source-loose.c b/odb/source-loose.c index c91018109e..da8a60dba1 100644 --- a/odb/source-loose.c +++ b/odb/source-loose.c @@ -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);