]> git.ipfire.org Git - thirdparty/git.git/commitdiff
branch: expose helpers for finding the remote owning a tracking ref
authorHarald Nordgren <haraldnordgren@gmail.com>
Sat, 23 May 2026 19:48:33 +0000 (19:48 +0000)
committerJunio C Hamano <gitster@pobox.com>
Sun, 24 May 2026 08:35:40 +0000 (17:35 +0900)
The remote-lookup that setup_tracking() does is useful outside
branch.c too; for example, deciding which remote to "git fetch"
from given a remote-tracking ref.

Move 'struct tracking' to branch.h and add two helpers backed by the
existing for_each_remote walk: find_tracking_remote_for_ref() and
advise_ambiguous_fetch_refspec(). setup_tracking() uses both. No
behavior change.

Signed-off-by: Harald Nordgren <haraldnordgren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
branch.c
branch.h

index 243db7d0fc02266b9ec79cd8cb90f620c0ce1970..46ae7f00354c9db823231ef17d870c4108ea0444 100644 (file)
--- a/branch.c
+++ b/branch.c
 #include "run-command.h"
 #include "strmap.h"
 
-struct tracking {
-       struct refspec_item spec;
-       struct string_list *srcs;
-       const char *remote;
-       int matches;
-};
-
 struct find_tracked_branch_cb {
        struct tracking *tracking;
-       struct string_list ambiguous_remotes;
+       struct string_list *ambiguous_remotes;
 };
 
 static int find_tracked_branch(struct remote *remote, void *priv)
@@ -45,10 +38,10 @@ static int find_tracked_branch(struct remote *remote, void *priv)
                        break;
                case 2:
                        /* there are at least two remotes; backfill the first one */
-                       string_list_append(&ftb->ambiguous_remotes, tracking->remote);
+                       string_list_append(ftb->ambiguous_remotes, tracking->remote);
                        /* fall through */
                default:
-                       string_list_append(&ftb->ambiguous_remotes, remote->name);
+                       string_list_append(ftb->ambiguous_remotes, remote->name);
                        free(tracking->spec.src);
                        string_list_clear(tracking->srcs, 0);
                break;
@@ -59,6 +52,51 @@ static int find_tracked_branch(struct remote *remote, void *priv)
        return 0;
 }
 
+void find_tracking_remote_for_ref(struct tracking *tracking,
+                                 struct string_list *ambiguous_remotes)
+{
+       struct find_tracked_branch_cb ftb_cb = {
+               .tracking = tracking,
+               .ambiguous_remotes = ambiguous_remotes,
+       };
+
+       for_each_remote(find_tracked_branch, &ftb_cb);
+}
+
+void advise_ambiguous_fetch_refspec(const char *dst,
+                                   const struct string_list *ambiguous_remotes)
+{
+       struct strbuf remotes_advice = STRBUF_INIT;
+       struct string_list_item *item;
+
+       if (!advice_enabled(ADVICE_AMBIGUOUS_FETCH_REFSPEC))
+               return;
+
+       for_each_string_list_item(item, ambiguous_remotes)
+               /*
+                * TRANSLATORS: This is a line listing a remote with duplicate
+                * refspecs in the advice message below. For RTL languages you'll
+                * probably want to swap the "%s" and leading "  " space around.
+                */
+               strbuf_addf(&remotes_advice, _("  %s\n"), item->string);
+
+       /*
+        * TRANSLATORS: The second argument is a \n-delimited list of
+        * duplicate refspecs, composed above.
+        */
+       advise(_("There are multiple remotes whose fetch refspecs map to the remote\n"
+                "tracking ref '%s':\n"
+                "%s"
+                "\n"
+                "This is typically a configuration error.\n"
+                "\n"
+                "To support setting up tracking branches, ensure that\n"
+                "different remotes' fetch refspecs map into different\n"
+                "tracking namespaces."), dst,
+              remotes_advice.buf);
+       strbuf_release(&remotes_advice);
+}
+
 static int should_setup_rebase(const char *origin)
 {
        switch (autorebase) {
@@ -254,11 +292,8 @@ static void setup_tracking(const char *new_ref, const char *orig_ref,
 {
        struct tracking tracking;
        struct string_list tracking_srcs = STRING_LIST_INIT_DUP;
+       struct string_list ambiguous_remotes = STRING_LIST_INIT_DUP;
        int config_flags = quiet ? 0 : BRANCH_CONFIG_VERBOSE;
-       struct find_tracked_branch_cb ftb_cb = {
-               .tracking = &tracking,
-               .ambiguous_remotes = STRING_LIST_INIT_DUP,
-       };
 
        if (!track)
                BUG("asked to set up tracking, but tracking is disallowed");
@@ -267,7 +302,7 @@ static void setup_tracking(const char *new_ref, const char *orig_ref,
        tracking.spec.dst = (char *)orig_ref;
        tracking.srcs = &tracking_srcs;
        if (track != BRANCH_TRACK_INHERIT)
-               for_each_remote(find_tracked_branch, &ftb_cb);
+               find_tracking_remote_for_ref(&tracking, &ambiguous_remotes);
        else if (inherit_tracking(&tracking, orig_ref))
                goto cleanup;
 
@@ -293,34 +328,7 @@ static void setup_tracking(const char *new_ref, const char *orig_ref,
        if (tracking.matches > 1) {
                int status = die_message(_("not tracking: ambiguous information for ref '%s'"),
                                            orig_ref);
-               if (advice_enabled(ADVICE_AMBIGUOUS_FETCH_REFSPEC)) {
-                       struct strbuf remotes_advice = STRBUF_INIT;
-                       struct string_list_item *item;
-
-                       for_each_string_list_item(item, &ftb_cb.ambiguous_remotes)
-                               /*
-                                * TRANSLATORS: This is a line listing a remote with duplicate
-                                * refspecs in the advice message below. For RTL languages you'll
-                                * probably want to swap the "%s" and leading "  " space around.
-                                */
-                               strbuf_addf(&remotes_advice, _("  %s\n"), item->string);
-
-                       /*
-                        * TRANSLATORS: The second argument is a \n-delimited list of
-                        * duplicate refspecs, composed above.
-                        */
-                       advise(_("There are multiple remotes whose fetch refspecs map to the remote\n"
-                                "tracking ref '%s':\n"
-                                "%s"
-                                "\n"
-                                "This is typically a configuration error.\n"
-                                "\n"
-                                "To support setting up tracking branches, ensure that\n"
-                                "different remotes' fetch refspecs map into different\n"
-                                "tracking namespaces."), orig_ref,
-                              remotes_advice.buf);
-                       strbuf_release(&remotes_advice);
-               }
+               advise_ambiguous_fetch_refspec(orig_ref, &ambiguous_remotes);
                exit(status);
        }
 
@@ -347,7 +355,7 @@ static void setup_tracking(const char *new_ref, const char *orig_ref,
 
 cleanup:
        string_list_clear(&tracking_srcs, 0);
-       string_list_clear(&ftb_cb.ambiguous_remotes, 0);
+       string_list_clear(&ambiguous_remotes, 0);
 }
 
 int read_branch_desc(struct strbuf *buf, const char *branch_name)
index 3dc6e2a0ffe6359eecd9ca169ff4483e8880a256..0aafa1673fc7a589f01c806be77b0dd49a979b0d 100644 (file)
--- a/branch.h
+++ b/branch.h
@@ -1,9 +1,25 @@
 #ifndef BRANCH_H
 #define BRANCH_H
 
+#include "refspec.h"
+#include "string-list.h"
+
 struct repository;
 struct strbuf;
 
+struct tracking {
+       struct refspec_item spec;
+       struct string_list *srcs;
+       const char *remote;
+       int matches;
+};
+
+void find_tracking_remote_for_ref(struct tracking *tracking,
+                                 struct string_list *ambiguous_remotes);
+
+void advise_ambiguous_fetch_refspec(const char *dst,
+                                   const struct string_list *ambiguous_remotes);
+
 enum branch_track {
        BRANCH_TRACK_UNSPECIFIED = -1,
        BRANCH_TRACK_NEVER = 0,