[PATCH] fetch.c: defer fetch.followRemoteHEAD validation
- From
Colin Hinton <colinlewishinton@gmail.com>
- Date
- Sep 22, 2026, 04:00 UTC
- Message-ID
- <20260922040047.2567-1-colinlewishinton@gmail.com>
Previously, fetch.followRemoteHEAD was validated and any invalid value was warned about unconditionally during config parsing.
Now store the raw config string instead, and resolve/validate it lazily at the one call in do_fetch(), so an irrelevant fetch no longer warns about an unrelated config value it never needed.
Signed-off-by: Colin Hinton <colinlewishinton@gmail.com> --- builtin/fetch.c | 57 ++++++++++++++++++++++++------------------------- 1 file changed, 28 insertions(+), 29 deletions(-)
diff --git a/builtin/fetch.c b/builtin/fetch.c index ab7db2be06..64ad26f5d4 100644 --- a/builtin/fetch.c +++ b/builtin/fetch.c @@ -103,7 +103,7 @@ static struct string_list negotiation_include = STRING_LIST_INIT_NODUP; struct fetch_config { enum display_format display_format; - enum follow_remote_head_settings follow_remote_head; + char *follow_remote_head_raw; int all; int prune; int prune_tags; @@ -178,22 +178,29 @@ static int git_fetch_config(const char *k, const char *v, if (!strcmp(k, "fetch.followremotehead")) { if (!v) return config_error_nonbool(k); - else if (!strcmp(v, "never")) - fetch_config->follow_remote_head = FOLLOW_REMOTE_NEVER; - else if (!strcmp(v, "create")) - fetch_config->follow_remote_head = FOLLOW_REMOTE_CREATE; - else if (!strcmp(v, "warn")) - fetch_config->follow_remote_head = FOLLOW_REMOTE_WARN; - else if (!strcmp(v, "always")) - fetch_config->follow_remote_head = FOLLOW_REMOTE_ALWAYS; - else - warning(_("unrecognized fetch.followRemoteHEAD value '%s' ignored"), v); + free(fetch_config->follow_remote_head_raw); + fetch_config->follow_remote_head_raw = xstrdup(v); + return 0; } return git_default_config(k, v, ctx, cb); } +static enum follow_remote_head_settings get_follow_remote_head(const char *setting) +{ + if (!strcmp(setting, "never")) + return FOLLOW_REMOTE_NEVER; + else if (!strcmp(setting, "create")) + return FOLLOW_REMOTE_CREATE; + else if (!strcmp(setting, "warn")) + return FOLLOW_REMOTE_WARN; + else if (!strcmp(setting, "always")) + return FOLLOW_REMOTE_ALWAYS; + warning(_("unrecognized fetch.followRemoteHEAD value '%s' ignored"), setting); + return FOLLOW_REMOTE_UNCONFIGURED; +} + static int parse_refmap_arg(const struct option *opt, const char *arg, int unset) { BUG_ON_OPT_NEG(unset); @@ -1922,7 +1929,7 @@ static int do_fetch(struct transport *transport, struct ref_update_display_info_array display_array = { 0 }; struct strmap rejected_refs = STRMAP_INIT; int summary_width = 0; - int follow_remote_head; + int follow_remote_head = 0; if (tags == TAGS_DEFAULT) { if (transport->remote->fetch_tags == 2) @@ -1938,22 +1945,6 @@ static int do_fetch(struct transport *transport, goto cleanup; } - /* - * NEEDSWORK: By the time this function executes, we have already parsed - * all such followRemoteHEAD values from the external configuration, - * potentially emitting warning messages for bogus values. Ideally, if - * this fetch ends up not needing to consult these values, then git would - * not ever output a value warning. (eg: when pulling from a URL directly - - * rather than a configured remote, or when a remote's followRemoteHEAD - * overrides the fallback fetch setting) - */ - if (transport->remote->follow_remote_head) - follow_remote_head = transport->remote->follow_remote_head; - else if (config->follow_remote_head) - follow_remote_head = config->follow_remote_head; - else - follow_remote_head = BUILTIN_FOLLOW_REMOTE_HEAD_DFLT; - if (rs->nr) { refspec_ref_prefixes(rs, &transport_ls_refs_options.ref_prefixes); } else { @@ -1962,6 +1953,14 @@ static int do_fetch(struct transport *transport, if (transport->remote->fetch.nr) { refspec_ref_prefixes(&transport->remote->fetch, &transport_ls_refs_options.ref_prefixes); + + if (transport->remote->follow_remote_head) + follow_remote_head = transport->remote->follow_remote_head; + else if (config->follow_remote_head_raw) + follow_remote_head = get_follow_remote_head(config->follow_remote_head_raw); + else + follow_remote_head = BUILTIN_FOLLOW_REMOTE_HEAD_DFLT; + if (follow_remote_head != FOLLOW_REMOTE_NEVER) do_set_head = 1; } @@ -2509,7 +2508,7 @@ int cmd_fetch(int argc, { struct fetch_config config = { .display_format = DISPLAY_FORMAT_FULL, - .follow_remote_head = FOLLOW_REMOTE_UNCONFIGURED, + .follow_remote_head_raw = NULL, .prune = -1, .prune_tags = -1, .show_forced_updates = 1,
-- 2.55.0.windows.3