Skip to content

Commit dca16f2

Browse files
committed
Merge branch 'ch/fetch-followremotehead-lazy-validation' into seen
Validation of the 'fetch.followRemoteHEAD' configuration variable has been deferred to when it is actually used, preventing irrelevant warnings during 'git fetch' invocations that do not consult it. * ch/fetch-followremotehead-lazy-validation: fetch.c: defer fetch.followRemoteHEAD validation
2 parents ff6f178 + 86129fd commit dca16f2

2 files changed

Lines changed: 44 additions & 36 deletions

File tree

‎builtin/fetch.c‎

Lines changed: 37 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,8 @@ static struct string_list negotiation_include = STRING_LIST_INIT_NODUP;
104104

105105
struct fetch_config {
106106
enum display_format display_format;
107-
enum follow_remote_head_settings follow_remote_head;
107+
char *follow_remote_head_raw;
108+
int follow_remote_head_seen;
108109
int all;
109110
int prune;
110111
int prune_tags;
@@ -212,24 +213,31 @@ static int git_fetch_config(const char *k, const char *v,
212213
}
213214

214215
if (!strcmp(k, "fetch.followremotehead")) {
215-
if (!v)
216-
return config_error_nonbool(k);
217-
else if (!strcmp(v, "never"))
218-
fetch_config->follow_remote_head = FOLLOW_REMOTE_NEVER;
219-
else if (!strcmp(v, "create"))
220-
fetch_config->follow_remote_head = FOLLOW_REMOTE_CREATE;
221-
else if (!strcmp(v, "warn"))
222-
fetch_config->follow_remote_head = FOLLOW_REMOTE_WARN;
223-
else if (!strcmp(v, "always"))
224-
fetch_config->follow_remote_head = FOLLOW_REMOTE_ALWAYS;
225-
else
226-
warning(_("unrecognized fetch.followRemoteHEAD value '%s' ignored"), v);
216+
free(fetch_config->follow_remote_head_raw);
217+
fetch_config->follow_remote_head_raw = xstrdup_or_null(v);
218+
fetch_config->follow_remote_head_seen = 1;
227219
return 0;
228220
}
229221

230222
return git_default_config(k, v, ctx, cb);
231223
}
232224

225+
static enum follow_remote_head_settings get_follow_remote_head(const char *setting)
226+
{
227+
if (!setting)
228+
die(_("missing value for 'fetch.followRemoteHEAD'"));
229+
else if (!strcmp(setting, "never"))
230+
return FOLLOW_REMOTE_NEVER;
231+
else if (!strcmp(setting, "create"))
232+
return FOLLOW_REMOTE_CREATE;
233+
else if (!strcmp(setting, "warn"))
234+
return FOLLOW_REMOTE_WARN;
235+
else if (!strcmp(setting, "always"))
236+
return FOLLOW_REMOTE_ALWAYS;
237+
warning(_("unrecognized fetch.followRemoteHEAD value '%s' ignored"), setting);
238+
return BUILTIN_FOLLOW_REMOTE_HEAD_DFLT;
239+
}
240+
233241
static int parse_refmap_arg(const struct option *opt, const char *arg, int unset)
234242
{
235243
BUG_ON_OPT_NEG(unset);
@@ -1978,11 +1986,10 @@ static int do_fetch(struct transport *transport,
19781986
TRANSPORT_LS_REFS_OPTIONS_INIT;
19791987
struct fetch_head fetch_head = { 0 };
19801988
struct strbuf err = STRBUF_INIT;
1981-
int do_set_head = 0;
19821989
struct ref_update_display_info_array display_array = { 0 };
19831990
struct strmap rejected_refs = STRMAP_INIT;
19841991
int summary_width = 0;
1985-
int follow_remote_head;
1992+
int follow_remote_head = FOLLOW_REMOTE_NEVER;
19861993

19871994
if (tags == TAGS_DEFAULT) {
19881995
if (transport->remote->fetch_tags == 2)
@@ -1998,22 +2005,6 @@ static int do_fetch(struct transport *transport,
19982005
goto cleanup;
19992006
}
20002007

2001-
/*
2002-
* NEEDSWORK: By the time this function executes, we have already parsed
2003-
* all such followRemoteHEAD values from the external configuration,
2004-
* potentially emitting warning messages for bogus values. Ideally, if
2005-
* this fetch ends up not needing to consult these values, then git would
2006-
* not ever output a value warning. (eg: when pulling from a URL directly -
2007-
* rather than a configured remote, or when a remote's followRemoteHEAD
2008-
* overrides the fallback fetch setting)
2009-
*/
2010-
if (transport->remote->follow_remote_head)
2011-
follow_remote_head = transport->remote->follow_remote_head;
2012-
else if (config->follow_remote_head)
2013-
follow_remote_head = config->follow_remote_head;
2014-
else
2015-
follow_remote_head = BUILTIN_FOLLOW_REMOTE_HEAD_DFLT;
2016-
20172008
if (rs->nr) {
20182009
refspec_ref_prefixes(rs, &transport_ls_refs_options.ref_prefixes);
20192010
} else {
@@ -2022,8 +2013,16 @@ static int do_fetch(struct transport *transport,
20222013
if (transport->remote->fetch.nr) {
20232014
refspec_ref_prefixes(&transport->remote->fetch,
20242015
&transport_ls_refs_options.ref_prefixes);
2025-
if (follow_remote_head != FOLLOW_REMOTE_NEVER)
2026-
do_set_head = 1;
2016+
/*
2017+
* See remote.c's handling of remote.<name>.followRemoteHEAD
2018+
* for the analogous, still-unresolved case.
2019+
*/
2020+
if (transport->remote->follow_remote_head)
2021+
follow_remote_head = transport->remote->follow_remote_head;
2022+
else if (config->follow_remote_head_seen)
2023+
follow_remote_head = get_follow_remote_head(config->follow_remote_head_raw);
2024+
else
2025+
follow_remote_head = BUILTIN_FOLLOW_REMOTE_HEAD_DFLT;
20272026
}
20282027
if (branch && branch_has_merge_config(branch) &&
20292028
!strcmp(branch->remote_name, transport->remote->name)) {
@@ -2047,7 +2046,7 @@ static int do_fetch(struct transport *transport,
20472046
strvec_push(&transport_ls_refs_options.ref_prefixes,
20482047
"refs/tags/");
20492048

2050-
if (do_set_head)
2049+
if (follow_remote_head != FOLLOW_REMOTE_NEVER)
20512050
strvec_push(&transport_ls_refs_options.ref_prefixes,
20522051
"HEAD");
20532052

@@ -2226,7 +2225,7 @@ static int do_fetch(struct transport *transport,
22262225
"you need to specify exactly one branch with the --set-upstream option"));
22272226
}
22282227
}
2229-
if (do_set_head) {
2228+
if (follow_remote_head != FOLLOW_REMOTE_NEVER) {
22302229
/*
22312230
* Way too many cases where this can go wrong so let's just
22322231
* ignore errors and fail silently for now.
@@ -2593,7 +2592,8 @@ int cmd_fetch(int argc,
25932592
{
25942593
struct fetch_config config = {
25952594
.display_format = DISPLAY_FORMAT_FULL,
2596-
.follow_remote_head = FOLLOW_REMOTE_UNCONFIGURED,
2595+
.follow_remote_head_raw = NULL,
2596+
.follow_remote_head_seen = 0,
25972597
.prune = -1,
25982598
.prune_tags = -1,
25992599
.show_forced_updates = 1,
@@ -3051,5 +3051,6 @@ int cmd_fetch(int argc,
30513051
oidset_clear(&updated_tips);
30523052
string_list_clear(&list, 0);
30533053
list_objects_filter_release(&filter_options);
3054+
free(config.follow_remote_head_raw);
30543055
return result;
30553056
}

‎remote.c‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -582,6 +582,13 @@ static int handle_config(const char *key, const char *value,
582582
&remote->negotiation_include);
583583
} else if (!strcmp(subkey, "followremotehead")) {
584584
const char *no_warn_branch;
585+
/*
586+
* NEEDSWORK: this is validated/warned about here, during config
587+
* parsing, regardless of whether the fetch that triggered this
588+
* parse will ever consult it for this particular remote. See
589+
* fetch.c's deferred handling of fetch.followRemoteHEAD for the
590+
* pattern this should likely follow.
591+
*/
585592
if (!strcmp(value, "never"))
586593
remote->follow_remote_head = FOLLOW_REMOTE_NEVER;
587594
else if (!strcmp(value, "create"))

0 commit comments

Comments
 (0)