Skip to content

Commit 288ea6c

Browse files
derrickstoleegitster
authored andcommitted
remote: add negotiationRequire config as default for --negotiation-require
Add a new 'remote.<name>.negotiationRequire' multi-valued config option that provides default values for --negotiation-require when no --negotiation-require arguments are specified over the command line. This is a mirror of how 'remote.<name>.negotiationRestrict' specifies defaults for the --negotiation-restrict arguments. Each value is either an exact ref name or a glob pattern whose tips should always be sent as 'have' lines during negotiation. The config values are resolved through the same resolve_negotiation_require() codepath as the CLI options. This option is additive with the normal negotiation process: the negotiation algorithm still runs and advertises its own selected commits, but the refs matching the config are sent unconditionally on top of those heuristically selected commits. Signed-off-by: Derrick Stolee <stolee@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 18d5475 commit 288ea6c

File tree

6 files changed

+91
-0
lines changed

6 files changed

+91
-0
lines changed

Documentation/config/remote.adoc

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,30 @@ command-line option. If `--negotiation-restrict` (or its synonym
123123
`--negotiation-tip`) is specified on the command line, then the config
124124
values are not used.
125125

126+
remote.<name>.negotiationRequire::
127+
When negotiating with this remote during `git fetch` and `git push`,
128+
the client advertises a list of commits that exist locally. In
129+
repos with many references, this list of "haves" can be truncated.
130+
Depending on data shape, dropping certain references may be
131+
expensive. This multi-valued config option specifies ref patterns
132+
whose tips should always be sent as "have" commits during fetch
133+
negotiation with this remote.
134+
+
135+
Each value is either an exact ref name (e.g. `refs/heads/release`) or a
136+
glob pattern (e.g. `refs/heads/release/*`). The pattern syntax is the same
137+
as for `--negotiation-restrict`.
138+
+
139+
These config values are used as defaults for the `--negotiation-require`
140+
command-line option. If `--negotiation-require` is specified on the
141+
command line, then the config values are not used.
142+
+
143+
This option is additive with the normal negotiation process: the
144+
negotiation algorithm still runs and advertises its own selected commits,
145+
but the refs matching `remote.<name>.negotiationRequire` are sent
146+
unconditionally on top of those heuristically selected commits. This
147+
option is also used during push negotiation when `push.negotiate` is
148+
enabled.
149+
126150
remote.<name>.followRemoteHEAD::
127151
How linkgit:git-fetch[1] should handle updates to `remotes/<name>/HEAD`
128152
when fetching using the configured refspecs of a remote.

Documentation/fetch-options.adoc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,10 @@ is the same as for `--negotiation-restrict`.
9191
If `--negotiation-restrict` is used, the have set is first restricted by
9292
that option and then increased to include the tips specified by
9393
`--negotiation-require`.
94+
+
95+
If this option is not specified on the command line, then any
96+
`remote.<name>.negotiationRequire` config values for the current remote
97+
are used instead.
9498

9599
`--negotiate-only`::
96100
Do not fetch anything from the server, and instead print the

builtin/fetch.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1622,6 +1622,16 @@ static struct transport *prepare_transport(struct remote *remote, int deepen,
16221622
else
16231623
warning(_("ignoring %s because the protocol does not support it"),
16241624
"--negotiation-require");
1625+
} else if (remote->negotiation_require.nr) {
1626+
if (transport->smart_options) {
1627+
transport->smart_options->negotiation_require = &remote->negotiation_require;
1628+
} else {
1629+
struct strbuf config_name = STRBUF_INIT;
1630+
strbuf_addf(&config_name, "remote.%s.negotiationRequire", remote->name);
1631+
warning(_("ignoring %s because the protocol does not support it"),
1632+
config_name.buf);
1633+
strbuf_release(&config_name);
1634+
}
16251635
}
16261636
return transport;
16271637
}

remote.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ static struct remote *make_remote(struct remote_state *remote_state,
153153
refspec_init_fetch(&ret->fetch);
154154
string_list_init_dup(&ret->server_options);
155155
string_list_init_dup(&ret->negotiation_restrict);
156+
string_list_init_dup(&ret->negotiation_require);
156157

157158
ALLOC_GROW(remote_state->remotes, remote_state->remotes_nr + 1,
158159
remote_state->remotes_alloc);
@@ -181,6 +182,7 @@ static void remote_clear(struct remote *remote)
181182
FREE_AND_NULL(remote->http_proxy_authmethod);
182183
string_list_clear(&remote->server_options, 0);
183184
string_list_clear(&remote->negotiation_restrict, 0);
185+
string_list_clear(&remote->negotiation_require, 0);
184186
}
185187

186188
static void add_merge(struct branch *branch, const char *name)
@@ -568,6 +570,10 @@ static int handle_config(const char *key, const char *value,
568570
if (!value)
569571
return config_error_nonbool(key);
570572
string_list_append(&remote->negotiation_restrict, value);
573+
} else if (!strcmp(subkey, "negotiationrequire")) {
574+
if (!value)
575+
return config_error_nonbool(key);
576+
string_list_append(&remote->negotiation_require, value);
571577
} else if (!strcmp(subkey, "followremotehead")) {
572578
const char *no_warn_branch;
573579
if (!strcmp(value, "never"))

remote.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ struct remote {
118118

119119
struct string_list server_options;
120120
struct string_list negotiation_restrict;
121+
struct string_list negotiation_require;
121122

122123
enum follow_remote_head_settings follow_remote_head;
123124
const char *no_warn_branch;

t/t5510-fetch.sh

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1573,6 +1573,52 @@ test_expect_success '--negotiation-require avoids duplicates with negotiator' '
15731573
test_line_count = 1 matches
15741574
'
15751575

1576+
test_expect_success 'remote.<name>.negotiationRequire used as default for --negotiation-require' '
1577+
test_when_finished rm -f trace &&
1578+
setup_negotiation_tip server server 0 &&
1579+
1580+
git -C client config --add remote.origin.negotiationRequire refs/tags/beta_1 &&
1581+
GIT_TRACE_PACKET="$(pwd)/trace" git -C client fetch \
1582+
--negotiation-restrict=alpha_1 \
1583+
origin alpha_s beta_s &&
1584+
1585+
ALPHA_1=$(git -C client rev-parse alpha_1) &&
1586+
test_grep "fetch> have $ALPHA_1" trace &&
1587+
BETA_1=$(git -C client rev-parse beta_1) &&
1588+
test_grep "fetch> have $BETA_1" trace
1589+
'
1590+
1591+
test_expect_success 'remote.<name>.negotiationRequire works with glob patterns' '
1592+
test_when_finished rm -f trace &&
1593+
setup_negotiation_tip server server 0 &&
1594+
1595+
git -C client config --add remote.origin.negotiationRequire "refs/tags/beta_*" &&
1596+
GIT_TRACE_PACKET="$(pwd)/trace" git -C client fetch \
1597+
--negotiation-restrict=alpha_1 \
1598+
origin alpha_s beta_s &&
1599+
1600+
BETA_1=$(git -C client rev-parse beta_1) &&
1601+
test_grep "fetch> have $BETA_1" trace &&
1602+
BETA_2=$(git -C client rev-parse beta_2) &&
1603+
test_grep "fetch> have $BETA_2" trace
1604+
'
1605+
1606+
test_expect_success 'CLI --negotiation-require overrides remote.<name>.negotiationRequire' '
1607+
test_when_finished rm -f trace &&
1608+
setup_negotiation_tip server server 0 &&
1609+
1610+
git -C client config --add remote.origin.negotiationRequire refs/tags/beta_2 &&
1611+
GIT_TRACE_PACKET="$(pwd)/trace" git -C client fetch \
1612+
--negotiation-restrict=alpha_1 \
1613+
--negotiation-require=refs/tags/beta_1 \
1614+
origin alpha_s beta_s &&
1615+
1616+
BETA_1=$(git -C client rev-parse beta_1) &&
1617+
test_grep "fetch> have $BETA_1" trace &&
1618+
BETA_2=$(git -C client rev-parse beta_2) &&
1619+
test_grep ! "fetch> have $BETA_2" trace
1620+
'
1621+
15761622
test_expect_success SYMLINKS 'clone does not get confused by a D/F conflict' '
15771623
git init df-conflict &&
15781624
(

0 commit comments

Comments
 (0)