]> git.ipfire.org Git - thirdparty/git.git/commitdiff
object-file: refactor freshening of objects
authorPatrick Steinhardt <ps@pks.im>
Mon, 3 Nov 2025 07:42:06 +0000 (08:42 +0100)
committerJunio C Hamano <gitster@pobox.com>
Mon, 3 Nov 2025 20:18:47 +0000 (12:18 -0800)
When writing an object that already exists in our object database we
skip the write and instead only update mtimes of the object, either in
its packed or loose object format. This logic is wholly contained in
"object-file.c", but that file is really only concerned with loose
objects. So it does not really make sense that it also contains the
logic to freshen a packed object.

Introduce a new `odb_freshen_object()` function that sits on the object
database level and two functions `packfile_store_freshen_object()` and
`odb_source_loose_freshen_object()`. Like this, the format-specific
functions can be part of their respective subsystems, while the backend
agnostic function to freshen an object sits at the object database
layer.

Note that this change also moves the logic that iterates through object
sources from the object source layer into the object database layer.
This change is intentional: object sources should ideally only have to
worry about themselves, and coordination of different sources should be
handled on the object database level.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
object-file.c
object-file.h
odb.c
odb.h
packfile.c
packfile.h

index 79e7ab8d2e3d0e8c64246aa90aa272b954f35fb4..893c32adcddbbd34c250c98d24d842cfb2046fff 100644 (file)
@@ -968,30 +968,10 @@ static int write_loose_object(struct odb_source *source,
                                          FOF_SKIP_COLLISION_CHECK);
 }
 
-static int freshen_loose_object(struct object_database *odb,
-                               const struct object_id *oid)
+int odb_source_loose_freshen_object(struct odb_source *source,
+                                   const struct object_id *oid)
 {
-       odb_prepare_alternates(odb);
-       for (struct odb_source *source = odb->sources; source; source = source->next)
-               if (check_and_freshen_source(source, oid, 1))
-                       return 1;
-       return 0;
-}
-
-static int freshen_packed_object(struct object_database *odb,
-                                const struct object_id *oid)
-{
-       struct pack_entry e;
-       if (!find_pack_entry(odb->repo, oid, &e))
-               return 0;
-       if (e.p->is_cruft)
-               return 0;
-       if (e.p->freshened)
-               return 1;
-       if (!freshen_file(e.p->pack_name))
-               return 0;
-       e.p->freshened = 1;
-       return 1;
+       return !!check_and_freshen_source(source, oid, 1);
 }
 
 int stream_loose_object(struct odb_source *source,
@@ -1073,12 +1053,10 @@ int stream_loose_object(struct odb_source *source,
                die(_("deflateEnd on stream object failed (%d)"), ret);
        close_loose_object(source, fd, tmp_file.buf);
 
-       if (freshen_packed_object(source->odb, oid) ||
-           freshen_loose_object(source->odb, oid)) {
+       if (odb_freshen_object(source->odb, oid)) {
                unlink_or_warn(tmp_file.buf);
                goto cleanup;
        }
-
        odb_loose_path(source, &filename, oid);
 
        /* We finally know the object path, and create the missing dir. */
@@ -1137,8 +1115,7 @@ int write_object_file(struct odb_source *source,
         * it out into .git/objects/??/?{38} file.
         */
        write_object_file_prepare(algo, buf, len, type, oid, hdr, &hdrlen);
-       if (freshen_packed_object(source->odb, oid) ||
-           freshen_loose_object(source->odb, oid))
+       if (odb_freshen_object(source->odb, oid))
                return 0;
        if (write_loose_object(source, oid, hdr, hdrlen, buf, len, 0, flags))
                return -1;
index 065a44bb8a019e62a34bb4b92a0528cf161773ca..ee5b24cec66c340b94752cbdeaebb5cc476630e8 100644 (file)
@@ -59,6 +59,9 @@ void *odb_source_loose_map_object(struct odb_source *source,
 int odb_source_loose_has_object(struct odb_source *source,
                                const struct object_id *oid);
 
+int odb_source_loose_freshen_object(struct odb_source *source,
+                                   const struct object_id *oid);
+
 /*
  * Populate and return the loose object cache array corresponding to the
  * given object ID.
diff --git a/odb.c b/odb.c
index 4c0b4fdcd54ce18242b92871209df5097b2c49ce..17734bdaffe8e64673726b615ff3dc98649cde76 100644 (file)
--- a/odb.c
+++ b/odb.c
@@ -987,6 +987,22 @@ int odb_has_object(struct object_database *odb, const struct object_id *oid,
        return odb_read_object_info_extended(odb, oid, NULL, object_info_flags) >= 0;
 }
 
+int odb_freshen_object(struct object_database *odb,
+                      const struct object_id *oid)
+{
+       struct odb_source *source;
+
+       if (packfile_store_freshen_object(odb->packfiles, oid))
+               return 1;
+
+       odb_prepare_alternates(odb);
+       for (source = odb->sources; source; source = source->next)
+               if (odb_source_loose_freshen_object(source, oid))
+                       return 1;
+
+       return 0;
+}
+
 void odb_assert_oid_type(struct object_database *odb,
                         const struct object_id *oid, enum object_type expect)
 {
diff --git a/odb.h b/odb.h
index f9a3137a34aa3b2756c85c28bbe91e8f98ba9657..2653247e0cc871793ca44324312e8c93f9ba9a9d 100644 (file)
--- a/odb.h
+++ b/odb.h
@@ -396,6 +396,9 @@ int odb_has_object(struct object_database *odb,
                   const struct object_id *oid,
                   unsigned flags);
 
+int odb_freshen_object(struct object_database *odb,
+                      const struct object_id *oid);
+
 void odb_assert_oid_type(struct object_database *odb,
                         const struct object_id *oid, enum object_type expect);
 
index 1ae2b2fe1eda77a57f007f78726724bd26f6a743..40f733dd234900662dc23d5c48906690b0046d88 100644 (file)
@@ -819,6 +819,22 @@ struct packed_git *packfile_store_load_pack(struct packfile_store *store,
        return p;
 }
 
+int packfile_store_freshen_object(struct packfile_store *store,
+                                 const struct object_id *oid)
+{
+       struct pack_entry e;
+       if (!find_pack_entry(store->odb->repo, oid, &e))
+               return 0;
+       if (e.p->is_cruft)
+               return 0;
+       if (e.p->freshened)
+               return 1;
+       if (utime(e.p->pack_name, NULL))
+               return 0;
+       e.p->freshened = 1;
+       return 1;
+}
+
 void (*report_garbage)(unsigned seen_bits, const char *path);
 
 static void report_helper(const struct string_list *list,
index c9d0b93446b5f569aadb12f48fce8ffc6aace59d..58fcc88e20224b18319168d4d6efdb6e2d6a3dff 100644 (file)
@@ -163,6 +163,9 @@ struct list_head *packfile_store_get_packs_mru(struct packfile_store *store);
 struct packed_git *packfile_store_load_pack(struct packfile_store *store,
                                            const char *idx_path, int local);
 
+int packfile_store_freshen_object(struct packfile_store *store,
+                                 const struct object_id *oid);
+
 struct pack_window {
        struct pack_window *next;
        unsigned char *base;