]> git.ipfire.org Git - thirdparty/git.git/commitdiff
odb/source: make `write_alternate()` function pluggable
authorPatrick Steinhardt <ps@pks.im>
Thu, 5 Mar 2026 14:19:56 +0000 (15:19 +0100)
committerJunio C Hamano <gitster@pobox.com>
Thu, 5 Mar 2026 19:45:17 +0000 (11:45 -0800)
Introduce a new callback function in `struct odb_source` to make the
function pluggable.

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

diff --git a/odb.c b/odb.c
index d9424cdfd0610da401951662338b78270b1db345..84a31084d3884b01663c2b8f8967eb9397dc3b44 100644 (file)
--- a/odb.c
+++ b/odb.c
@@ -236,58 +236,6 @@ static struct odb_source *odb_add_alternate_recursively(struct object_database *
        return alternate;
 }
 
-static int odb_source_write_alternate(struct odb_source *source,
-                                     const char *alternate)
-{
-       struct lock_file lock = LOCK_INIT;
-       char *path = xstrfmt("%s/%s", source->path, "info/alternates");
-       FILE *in, *out;
-       int found = 0;
-       int ret;
-
-       hold_lock_file_for_update(&lock, path, LOCK_DIE_ON_ERROR);
-       out = fdopen_lock_file(&lock, "w");
-       if (!out) {
-               ret = error_errno(_("unable to fdopen alternates lockfile"));
-               goto out;
-       }
-
-       in = fopen(path, "r");
-       if (in) {
-               struct strbuf line = STRBUF_INIT;
-
-               while (strbuf_getline(&line, in) != EOF) {
-                       if (!strcmp(alternate, line.buf)) {
-                               found = 1;
-                               break;
-                       }
-                       fprintf_or_die(out, "%s\n", line.buf);
-               }
-
-               strbuf_release(&line);
-               fclose(in);
-       } else if (errno != ENOENT) {
-               ret = error_errno(_("unable to read alternates file"));
-               goto out;
-       }
-
-       if (found) {
-               rollback_lock_file(&lock);
-       } else {
-               fprintf_or_die(out, "%s\n", alternate);
-               if (commit_lock_file(&lock)) {
-                       ret = error_errno(_("unable to move new alternates file into place"));
-                       goto out;
-               }
-       }
-
-       ret = 0;
-
-out:
-       free(path);
-       return ret;
-}
-
 void odb_add_to_alternates_file(struct object_database *odb,
                                const char *dir)
 {
index 199c55cfa4ca1a86bb930d2cf23ee4564205be93..c32cd67b2650258dfb448333be0779cc643bcfa3 100644 (file)
@@ -1,12 +1,15 @@
 #include "git-compat-util.h"
 #include "abspath.h"
 #include "chdir-notify.h"
+#include "gettext.h"
+#include "lockfile.h"
 #include "object-file.h"
 #include "odb.h"
 #include "odb/source.h"
 #include "odb/source-files.h"
 #include "packfile.h"
 #include "strbuf.h"
+#include "write-or-die.h"
 
 static void odb_source_files_reparent(const char *name UNUSED,
                                      const char *old_cwd,
@@ -138,6 +141,58 @@ static int odb_source_files_read_alternates(struct odb_source *source,
        return 0;
 }
 
+static int odb_source_files_write_alternate(struct odb_source *source,
+                                           const char *alternate)
+{
+       struct lock_file lock = LOCK_INIT;
+       char *path = xstrfmt("%s/%s", source->path, "info/alternates");
+       FILE *in, *out;
+       int found = 0;
+       int ret;
+
+       hold_lock_file_for_update(&lock, path, LOCK_DIE_ON_ERROR);
+       out = fdopen_lock_file(&lock, "w");
+       if (!out) {
+               ret = error_errno(_("unable to fdopen alternates lockfile"));
+               goto out;
+       }
+
+       in = fopen(path, "r");
+       if (in) {
+               struct strbuf line = STRBUF_INIT;
+
+               while (strbuf_getline(&line, in) != EOF) {
+                       if (!strcmp(alternate, line.buf)) {
+                               found = 1;
+                               break;
+                       }
+                       fprintf_or_die(out, "%s\n", line.buf);
+               }
+
+               strbuf_release(&line);
+               fclose(in);
+       } else if (errno != ENOENT) {
+               ret = error_errno(_("unable to read alternates file"));
+               goto out;
+       }
+
+       if (found) {
+               rollback_lock_file(&lock);
+       } else {
+               fprintf_or_die(out, "%s\n", alternate);
+               if (commit_lock_file(&lock)) {
+                       ret = error_errno(_("unable to move new alternates file into place"));
+                       goto out;
+               }
+       }
+
+       ret = 0;
+
+out:
+       free(path);
+       return ret;
+}
+
 struct odb_source_files *odb_source_files_new(struct object_database *odb,
                                              const char *path,
                                              bool local)
@@ -159,6 +214,7 @@ struct odb_source_files *odb_source_files_new(struct object_database *odb,
        files->base.write_object = odb_source_files_write_object;
        files->base.write_object_stream = odb_source_files_write_object_stream;
        files->base.read_alternates = odb_source_files_read_alternates;
+       files->base.write_alternate = odb_source_files_write_alternate;
 
        /*
         * Ideally, we would only ever store absolute paths in the source. This
index fbdddcb2eb4312188c2ea04603e39ec197841362..ee540630d293d80bc972295551f2944ab763e951 100644 (file)
@@ -245,6 +245,19 @@ struct odb_source {
         */
        int (*read_alternates)(struct odb_source *source,
                               struct strvec *out);
+
+       /*
+        * This callback is expected to persist the singular alternate passed
+        * to it into its list of alternates. Any pre-existing alternates are
+        * expected to remain active. Subsequent calls to `read_alternates` are
+        * thus expected to yield the pre-existing list of alternates plus the
+        * newly added alternate appended to its end.
+        *
+        * The callback is expected to return 0 on success, a negative error
+        * code otherwise.
+        */
+       int (*write_alternate)(struct odb_source *source,
+                              const char *alternate);
 };
 
 /*
@@ -412,4 +425,17 @@ static inline int odb_source_read_alternates(struct odb_source *source,
        return source->read_alternates(source, out);
 }
 
+/*
+ * Write and persist a new alternate object database source for the given
+ * source. Any preexisting alternates are expected to stay valid, and the new
+ * alternate shall be appended to the end of the list.
+ *
+ * Returns 0 on success, a negative error code otherwise.
+ */
+static inline int odb_source_write_alternate(struct odb_source *source,
+                                             const char *alternate)
+{
+       return source->write_alternate(source, alternate);
+}
+
 #endif