Skip to content

Commit d2f48b7

Browse files
committed
remote: add remote.*.negotiationRestrict config
In a previous change, the --negotiation-restrict command-line option of 'git fetch' was added as a synonym of --negotiation-tips. Both of these options restrict the set of 'haves' the client can send as part of negotiation. This was previously not available via a configuration option. Add a new 'remote.<name>.negotiationRestrict' multi-valued config option that updates 'git fetch <name>' to use these restrictions by default. If the user provides even one --negotiation-restrict argument, then the config is ignored. An empty value resets the value list to allow ignoring earlier config values, such as those that might be set in system or global config. Signed-off-by: Derrick Stolee <stolee@gmail.com>
1 parent 4332cbf commit d2f48b7

5 files changed

Lines changed: 71 additions & 4 deletions

File tree

Documentation/config/remote.adoc

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,25 @@ priority configuration file (e.g. `.git/config` in a repository) to clear
107107
the values inherited from a lower priority configuration files (e.g.
108108
`$HOME/.gitconfig`).
109109

110+
remote.<name>.negotiationRestrict::
111+
When negotiating with this remote during `git fetch` and `git push`,
112+
restrict the commits advertised as "have" lines to only those
113+
reachable from refs matching the given patterns. This multi-valued
114+
config option behaves like `--negotiation-restrict` on the command
115+
line.
116+
+
117+
Each value is either an exact ref name (e.g. `refs/heads/release`) or a
118+
glob pattern (e.g. `refs/heads/release/*`). The pattern syntax is the
119+
same as for `--negotiation-restrict`.
120+
+
121+
These config values are used as defaults for the `--negotiation-restrict`
122+
command-line option. If `--negotiation-restrict` (or its synonym
123+
`--negotiation-tip`) is specified on the command line, then the config
124+
values are not used.
125+
+
126+
Blank values signal to ignore all previous values, allowing a reset of
127+
the list from broader config scenarios.
128+
110129
remote.<name>.followRemoteHEAD::
111130
How linkgit:git-fetch[1] should handle updates to `remotes/<name>/HEAD`
112131
when fetching using the configured refspecs of a remote.

builtin/fetch.c

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1601,6 +1601,19 @@ static struct transport *prepare_transport(struct remote *remote, int deepen,
16011601
else
16021602
warning(_("ignoring %s because the protocol does not support it"),
16031603
"--negotiation-restrict");
1604+
} else if (remote->negotiation_restrict.nr) {
1605+
struct string_list_item *item;
1606+
for_each_string_list_item(item, &remote->negotiation_restrict)
1607+
string_list_append(&negotiation_restrict, item->string);
1608+
if (transport->smart_options)
1609+
add_negotiation_restrict_tips(transport->smart_options);
1610+
else {
1611+
struct strbuf config_name = STRBUF_INIT;
1612+
strbuf_addf(&config_name, "remote.%s.negotiationRestrict", remote->name);
1613+
warning(_("ignoring %s because the protocol does not support it"),
1614+
config_name.buf);
1615+
strbuf_release(&config_name);
1616+
}
16041617
}
16051618
return transport;
16061619
}
@@ -2658,10 +2671,6 @@ int cmd_fetch(int argc,
26582671
config.display_format = DISPLAY_FORMAT_PORCELAIN;
26592672
}
26602673

2661-
if (negotiate_only && !negotiation_restrict.nr)
2662-
die(_("%s needs one or more %s"), "--negotiate-only",
2663-
"--negotiation-restrict=*");
2664-
26652674
if (deepen_relative) {
26662675
if (deepen_relative < 0)
26672676
die(_("negative depth in --deepen is not supported"));
@@ -2749,6 +2758,10 @@ int cmd_fetch(int argc,
27492758
if (!remote)
27502759
die(_("must supply remote when using --negotiate-only"));
27512760
gtransport = prepare_transport(remote, 1, &filter_options);
2761+
if (!gtransport->smart_options ||
2762+
!gtransport->smart_options->negotiation_restrict_tips)
2763+
die(_("%s needs one or more %s"), "--negotiate-only",
2764+
"--negotiation-restrict=*");
27522765
if (gtransport->smart_options) {
27532766
gtransport->smart_options->acked_commits = &acked_commits;
27542767
} else {

remote.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ static struct remote *make_remote(struct remote_state *remote_state,
152152
refspec_init_push(&ret->push);
153153
refspec_init_fetch(&ret->fetch);
154154
string_list_init_dup(&ret->server_options);
155+
string_list_init_dup(&ret->negotiation_restrict);
155156

156157
ALLOC_GROW(remote_state->remotes, remote_state->remotes_nr + 1,
157158
remote_state->remotes_alloc);
@@ -179,6 +180,7 @@ static void remote_clear(struct remote *remote)
179180
FREE_AND_NULL(remote->http_proxy);
180181
FREE_AND_NULL(remote->http_proxy_authmethod);
181182
string_list_clear(&remote->server_options, 0);
183+
string_list_clear(&remote->negotiation_restrict, 0);
182184
}
183185

184186
static void add_merge(struct branch *branch, const char *name)
@@ -562,6 +564,12 @@ static int handle_config(const char *key, const char *value,
562564
} else if (!strcmp(subkey, "serveroption")) {
563565
return parse_transport_option(key, value,
564566
&remote->server_options);
567+
} else if (!strcmp(subkey, "negotiationrestrict")) {
568+
/* reset list on empty value. */
569+
if (!value || !*value)
570+
string_list_clear(&remote->negotiation_restrict, 0);
571+
else
572+
string_list_append(&remote->negotiation_restrict, value);
565573
} else if (!strcmp(subkey, "followremotehead")) {
566574
const char *no_warn_branch;
567575
if (!strcmp(value, "never"))

remote.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ struct remote {
117117
char *http_proxy_authmethod;
118118

119119
struct string_list server_options;
120+
struct string_list negotiation_restrict;
120121

121122
enum follow_remote_head_settings follow_remote_head;
122123
const char *no_warn_branch;

t/t5510-fetch.sh

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1485,6 +1485,32 @@ test_expect_success '--negotiation-restrict and --negotiation-tip can be mixed'
14851485
check_negotiation_tip
14861486
'
14871487

1488+
test_expect_success 'remote.<name>.negotiationRestrict used as default' '
1489+
setup_negotiation_tip server server 0 &&
1490+
1491+
# test the reset of the list on an empty value
1492+
git -C client config --add remote.origin.negotiationRestrict alpha_2 &&
1493+
git -C client config --add remote.origin.negotiationRestrict "" &&
1494+
git -C client config --add remote.origin.negotiationRestrict alpha_1 &&
1495+
git -C client config --add remote.origin.negotiationRestrict beta_1 &&
1496+
GIT_TRACE_PACKET="$(pwd)/trace" git -C client fetch \
1497+
origin alpha_s beta_s &&
1498+
check_negotiation_tip
1499+
'
1500+
1501+
test_expect_success 'CLI --negotiation-restrict overrides remote config' '
1502+
setup_negotiation_tip server server 0 &&
1503+
git -C client config --add remote.origin.negotiationRestrict alpha_1 &&
1504+
git -C client config --add remote.origin.negotiationRestrict beta_1 &&
1505+
ALPHA_1=$(git -C client rev-parse alpha_1) &&
1506+
GIT_TRACE_PACKET="$(pwd)/trace" git -C client fetch \
1507+
--negotiation-restrict=alpha_1 \
1508+
origin alpha_s beta_s &&
1509+
test_grep "fetch> have $ALPHA_1" trace &&
1510+
BETA_1=$(git -C client rev-parse beta_1) &&
1511+
test_grep ! "fetch> have $BETA_1" trace
1512+
'
1513+
14881514
test_expect_success SYMLINKS 'clone does not get confused by a D/F conflict' '
14891515
git init df-conflict &&
14901516
(

0 commit comments

Comments
 (0)