The function `force_object_loose()` is used to loosen packed objects
before repacking. It passes the pack's mtime along so that the newly
written loose object inherits the same timestamp. This matters for
object pruning, which uses the mtime to determine whether an object is
old enough to be pruned.
In a subsequent commit, `force_object_loose()` will be converted to use
the generic `odb_source_write_object()` interface instead of calling
`write_loose_object()` directly. But the generic interface doesn't yet
support setting a specific mtime, which makes it impossible to implement
the logic as of now.
Prepare for the change by introducing a new `mtime` parameter to this
function that we plumb through the stack. If set, the backends are
instructed to set the object's mtime accordingly. If unset, the backends
are expected to use the current time instead.
Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Patrick Steinhardt committedJul 17, 2026 at 11:32 UTC8d9135dce3be50c961f23f5e89352b0fd1d61117
11 files changed+67-35
builtin/pack-objects.c
+1-1
index ea5eab4cf8..e64a96f1a7 100644--- a/builtin/pack-objects.c+++ b/builtin/pack-objects.c@@ -4642,7 +4642,7 @@ static void loosen_unused_packed_objects(void) !has_sha1_pack_kept_or_nonlocal(&oid) && !loosened_object_can_be_discarded(&oid, p->mtime)) { if (force_object_loose(the_repository->objects->sources,- &oid, p->mtime))+ &oid, &p->mtime)) die(_("unable to force loose object")); loosened_objects_nr++; }
object-file.c
+20-9
index 9ca14f484d..5b07530950 100644--- a/object-file.c+++ b/object-file.c@@ -67,9 +67,17 @@ const char *odb_loose_path(struct odb_source_loose *loose, } /* Returns 1 if we have successfully freshened the file, 0 otherwise. */-static int freshen_file(const char *fn)+static int freshen_file(const char *fn, const time_t *mtime) {- return !utime(fn, NULL);+ struct utimbuf times, *timesp = NULL;++ if (mtime) {+ times.actime = *mtime;+ times.modtime = *mtime;+ timesp = ×+ }++ return !utime(fn, timesp); } /*@@ -79,11 +87,12 @@ static int freshen_file(const char *fn) * either does not exist on disk, or has a stale mtime and may be subject to * pruning). */-int check_and_freshen_file(const char *fn, int freshen)+int check_and_freshen_file(const char *fn, int freshen,+ const time_t *mtime) { if (access(fn, F_OK)) return 0;- if (freshen && !freshen_file(fn))+ if (freshen && !freshen_file(fn, mtime)) return 0; return 1; }@@ -706,7 +715,7 @@ static int end_loose_object_common(struct odb_source_loose *loose, 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)+ const time_t *mtime, unsigned flags) { int fd, ret; unsigned char compressed[4096];@@ -751,9 +760,11 @@ int write_loose_object(struct odb_source_loose *loose, close_loose_object(loose, fd, tmp_file.buf); if (mtime) {- struct utimbuf utb;- utb.actime = mtime;- utb.modtime = mtime;+ struct utimbuf utb = {+ .actime = *mtime,+ .modtime = *mtime,+ };+ if (utime(tmp_file.buf, &utb) < 0 && !(flags & ODB_WRITE_OBJECT_SILENT)) warning_errno(_("failed utime() on %s"), tmp_file.buf);@@ -883,7 +894,7 @@ cleanup: } int force_object_loose(struct odb_source *source,- const struct object_id *oid, time_t mtime)+ const struct object_id *oid, const time_t *mtime) { struct odb_source_files *files = odb_source_files_downcast(source); const struct git_hash_algo *compat = source->odb->repo->compat_hash_algo;
object-file.h
+5-3
index 08aafcda0d..9fd540afb6 100644--- a/object-file.h+++ b/object-file.h@@ -99,7 +99,8 @@ int format_object_header(char *str, size_t size, enum object_type type, size_t objsize); int force_object_loose(struct odb_source *source,- const struct object_id *oid, time_t mtime);+ const struct object_id *oid,+ const time_t *mtime); /** * With in-core object data in "buf", rehash it to make sure the@@ -137,10 +138,11 @@ void hash_object_file(const struct git_hash_algo *algo, const void *buf, 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);+ const time_t *mtime, unsigned flags); /* Helper to check and "touch" a file */-int check_and_freshen_file(const char *fn, int freshen);+int check_and_freshen_file(const char *fn, int freshen,+ const time_t *mtime); /* * Open the loose object at path, check its hash, and return the contents,