Merge branch 'xx/remote-server-option-config'
A new configuration variable remote.<name>.serverOption makes the
transport layer act as if the --serverOption=<value> option is
given from the command line.
* xx/remote-server-option-config:
ls-remote: leakfix for not clearing server_options
fetch: respect --server-option when fetching multiple remotes
transport.c:🤝 make use of server options from remote
remote: introduce remote.<name>.serverOption configuration
transport: introduce parse_transport_option() method
This commit is contained in:
@ -96,3 +96,13 @@ remote.<name>.partialclonefilter::
|
|||||||
Changing or clearing this value will only affect fetches for new commits.
|
Changing or clearing this value will only affect fetches for new commits.
|
||||||
To fetch associated objects for commits already present in the local object
|
To fetch associated objects for commits already present in the local object
|
||||||
database, use the `--refetch` option of linkgit:git-fetch[1].
|
database, use the `--refetch` option of linkgit:git-fetch[1].
|
||||||
|
|
||||||
|
remote.<name>.serverOption::
|
||||||
|
The default set of server options used when fetching from this remote.
|
||||||
|
These server options can be overridden by the `--server-option=` command
|
||||||
|
line arguments.
|
||||||
|
+
|
||||||
|
This is a multi-valued variable, and an empty value can be used in a higher
|
||||||
|
priority configuration file (e.g. `.git/config` in a repository) to clear
|
||||||
|
the values inherited from a lower priority configuration files (e.g.
|
||||||
|
`$HOME/.gitconfig`).
|
||||||
|
@ -305,6 +305,9 @@ endif::git-pull[]
|
|||||||
unknown ones, is server-specific.
|
unknown ones, is server-specific.
|
||||||
When multiple `--server-option=<option>` are given, they are all
|
When multiple `--server-option=<option>` are given, they are all
|
||||||
sent to the other side in the order listed on the command line.
|
sent to the other side in the order listed on the command line.
|
||||||
|
When no `--server-option=<option>` is given from the command line,
|
||||||
|
the values of configuration variable `remote.<name>.serverOption`
|
||||||
|
are used instead.
|
||||||
|
|
||||||
--show-forced-updates::
|
--show-forced-updates::
|
||||||
By default, git checks if a branch is force-updated during
|
By default, git checks if a branch is force-updated during
|
||||||
|
@ -149,6 +149,9 @@ objects from the source repository into a pack in the cloned repository.
|
|||||||
unknown ones, is server-specific.
|
unknown ones, is server-specific.
|
||||||
When multiple `--server-option=<option>` are given, they are all
|
When multiple `--server-option=<option>` are given, they are all
|
||||||
sent to the other side in the order listed on the command line.
|
sent to the other side in the order listed on the command line.
|
||||||
|
When no ++--server-option=++__<option>__ is given from the command
|
||||||
|
line, the values of configuration variable `remote.<name>.serverOption`
|
||||||
|
are used instead.
|
||||||
|
|
||||||
`-n`::
|
`-n`::
|
||||||
`--no-checkout`::
|
`--no-checkout`::
|
||||||
|
@ -81,6 +81,9 @@ OPTIONS
|
|||||||
character.
|
character.
|
||||||
When multiple `--server-option=<option>` are given, they are all
|
When multiple `--server-option=<option>` are given, they are all
|
||||||
sent to the other side in the order listed on the command line.
|
sent to the other side in the order listed on the command line.
|
||||||
|
When no `--server-option=<option>` is given from the command line,
|
||||||
|
the values of configuration variable `remote.<name>.serverOption`
|
||||||
|
are used instead.
|
||||||
|
|
||||||
<repository>::
|
<repository>::
|
||||||
The "remote" repository to query. This parameter can be
|
The "remote" repository to query. This parameter can be
|
||||||
|
@ -1981,6 +1981,8 @@ static int fetch_multiple(struct string_list *list, int max_children,
|
|||||||
strvec_pushl(&argv, "-c", "fetch.bundleURI=",
|
strvec_pushl(&argv, "-c", "fetch.bundleURI=",
|
||||||
"fetch", "--append", "--no-auto-gc",
|
"fetch", "--append", "--no-auto-gc",
|
||||||
"--no-write-commit-graph", NULL);
|
"--no-write-commit-graph", NULL);
|
||||||
|
for (i = 0; i < server_options.nr; i++)
|
||||||
|
strvec_pushf(&argv, "--server-option=%s", server_options.items[i].string);
|
||||||
add_options_to_argv(&argv, config);
|
add_options_to_argv(&argv, config);
|
||||||
|
|
||||||
if (max_children != 1 && list->nr != 1) {
|
if (max_children != 1 && list->nr != 1) {
|
||||||
|
@ -173,5 +173,6 @@ int cmd_ls_remote(int argc,
|
|||||||
transport_ls_refs_options_release(&transport_options);
|
transport_ls_refs_options_release(&transport_options);
|
||||||
|
|
||||||
strvec_clear(&pattern);
|
strvec_clear(&pattern);
|
||||||
|
string_list_clear(&server_options, 0);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
@ -519,14 +519,7 @@ static int git_push_config(const char *k, const char *v,
|
|||||||
RECURSE_SUBMODULES_ON_DEMAND : RECURSE_SUBMODULES_OFF;
|
RECURSE_SUBMODULES_ON_DEMAND : RECURSE_SUBMODULES_OFF;
|
||||||
recurse_submodules = val;
|
recurse_submodules = val;
|
||||||
} else if (!strcmp(k, "push.pushoption")) {
|
} else if (!strcmp(k, "push.pushoption")) {
|
||||||
if (!v)
|
return parse_transport_option(k, v, &push_options_config);
|
||||||
return config_error_nonbool(k);
|
|
||||||
else
|
|
||||||
if (!*v)
|
|
||||||
string_list_clear(&push_options_config, 0);
|
|
||||||
else
|
|
||||||
string_list_append(&push_options_config, v);
|
|
||||||
return 0;
|
|
||||||
} else if (!strcmp(k, "color.push")) {
|
} else if (!strcmp(k, "color.push")) {
|
||||||
push_use_color = git_config_colorbool(k, v);
|
push_use_color = git_config_colorbool(k, v);
|
||||||
return 0;
|
return 0;
|
||||||
|
6
remote.c
6
remote.c
@ -24,6 +24,7 @@
|
|||||||
#include "advice.h"
|
#include "advice.h"
|
||||||
#include "connect.h"
|
#include "connect.h"
|
||||||
#include "parse-options.h"
|
#include "parse-options.h"
|
||||||
|
#include "transport.h"
|
||||||
|
|
||||||
enum map_direction { FROM_SRC, FROM_DST };
|
enum map_direction { FROM_SRC, FROM_DST };
|
||||||
|
|
||||||
@ -143,6 +144,7 @@ static struct remote *make_remote(struct remote_state *remote_state,
|
|||||||
ret->name = xstrndup(name, len);
|
ret->name = xstrndup(name, len);
|
||||||
refspec_init(&ret->push, REFSPEC_PUSH);
|
refspec_init(&ret->push, REFSPEC_PUSH);
|
||||||
refspec_init(&ret->fetch, REFSPEC_FETCH);
|
refspec_init(&ret->fetch, REFSPEC_FETCH);
|
||||||
|
string_list_init_dup(&ret->server_options);
|
||||||
|
|
||||||
ALLOC_GROW(remote_state->remotes, remote_state->remotes_nr + 1,
|
ALLOC_GROW(remote_state->remotes, remote_state->remotes_nr + 1,
|
||||||
remote_state->remotes_alloc);
|
remote_state->remotes_alloc);
|
||||||
@ -166,6 +168,7 @@ static void remote_clear(struct remote *remote)
|
|||||||
free((char *)remote->uploadpack);
|
free((char *)remote->uploadpack);
|
||||||
FREE_AND_NULL(remote->http_proxy);
|
FREE_AND_NULL(remote->http_proxy);
|
||||||
FREE_AND_NULL(remote->http_proxy_authmethod);
|
FREE_AND_NULL(remote->http_proxy_authmethod);
|
||||||
|
string_list_clear(&remote->server_options, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void add_merge(struct branch *branch, const char *name)
|
static void add_merge(struct branch *branch, const char *name)
|
||||||
@ -508,6 +511,9 @@ static int handle_config(const char *key, const char *value,
|
|||||||
} else if (!strcmp(subkey, "vcs")) {
|
} else if (!strcmp(subkey, "vcs")) {
|
||||||
FREE_AND_NULL(remote->foreign_vcs);
|
FREE_AND_NULL(remote->foreign_vcs);
|
||||||
return git_config_string(&remote->foreign_vcs, key, value);
|
return git_config_string(&remote->foreign_vcs, key, value);
|
||||||
|
} else if (!strcmp(subkey, "serveroption")) {
|
||||||
|
return parse_transport_option(key, value,
|
||||||
|
&remote->server_options);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
3
remote.h
3
remote.h
@ -4,6 +4,7 @@
|
|||||||
#include "hash.h"
|
#include "hash.h"
|
||||||
#include "hashmap.h"
|
#include "hashmap.h"
|
||||||
#include "refspec.h"
|
#include "refspec.h"
|
||||||
|
#include "string-list.h"
|
||||||
#include "strvec.h"
|
#include "strvec.h"
|
||||||
|
|
||||||
struct option;
|
struct option;
|
||||||
@ -104,6 +105,8 @@ struct remote {
|
|||||||
|
|
||||||
/* The method used for authenticating against `http_proxy`. */
|
/* The method used for authenticating against `http_proxy`. */
|
||||||
char *http_proxy_authmethod;
|
char *http_proxy_authmethod;
|
||||||
|
|
||||||
|
struct string_list server_options;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -185,6 +185,43 @@ test_expect_success 'server-options are sent when using ls-remote' '
|
|||||||
grep "server-option=world" log
|
grep "server-option=world" log
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'server-options from configuration are used by ls-remote' '
|
||||||
|
test_when_finished "rm -rf log myclone" &&
|
||||||
|
git clone "file://$(pwd)/file_parent" myclone &&
|
||||||
|
cat >expect <<-EOF &&
|
||||||
|
$(git -C file_parent rev-parse refs/heads/main)$(printf "\t")refs/heads/main
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Default server options from configuration are used
|
||||||
|
git -C myclone config --add remote.origin.serverOption foo &&
|
||||||
|
git -C myclone config --add remote.origin.serverOption bar &&
|
||||||
|
GIT_TRACE_PACKET="$(pwd)/log" git -C myclone -c protocol.version=2 \
|
||||||
|
ls-remote origin main >actual &&
|
||||||
|
test_cmp expect actual &&
|
||||||
|
test_grep "ls-remote> server-option=foo" log &&
|
||||||
|
test_grep "ls-remote> server-option=bar" log &&
|
||||||
|
rm -f log &&
|
||||||
|
|
||||||
|
# Empty value of remote.<name>.serverOption clears the list
|
||||||
|
git -C myclone config --add remote.origin.serverOption "" &&
|
||||||
|
git -C myclone config --add remote.origin.serverOption tar &&
|
||||||
|
GIT_TRACE_PACKET="$(pwd)/log" git -C myclone -c protocol.version=2 \
|
||||||
|
ls-remote origin main >actual &&
|
||||||
|
test_cmp expect actual &&
|
||||||
|
test_grep "ls-remote> server-option=tar" log &&
|
||||||
|
test_grep ! "ls-remote> server-option=foo" log &&
|
||||||
|
test_grep ! "ls-remote> server-option=bar" log &&
|
||||||
|
rm -f log &&
|
||||||
|
|
||||||
|
# Server option from command line overrides those from configuration
|
||||||
|
GIT_TRACE_PACKET="$(pwd)/log" git -C myclone -c protocol.version=2 \
|
||||||
|
ls-remote -o hello -o world origin main >actual &&
|
||||||
|
test_cmp expect actual &&
|
||||||
|
test_grep "ls-remote> server-option=hello" log &&
|
||||||
|
test_grep "ls-remote> server-option=world" log &&
|
||||||
|
test_grep ! "ls-remote> server-option=tar" log
|
||||||
|
'
|
||||||
|
|
||||||
test_expect_success 'warn if using server-option with ls-remote with legacy protocol' '
|
test_expect_success 'warn if using server-option with ls-remote with legacy protocol' '
|
||||||
test_must_fail env GIT_TEST_PROTOCOL_VERSION=0 git -c protocol.version=0 \
|
test_must_fail env GIT_TEST_PROTOCOL_VERSION=0 git -c protocol.version=0 \
|
||||||
ls-remote -o hello -o world "file://$(pwd)/file_parent" main 2>err &&
|
ls-remote -o hello -o world "file://$(pwd)/file_parent" main 2>err &&
|
||||||
@ -381,6 +418,54 @@ test_expect_success 'server-options are sent when fetching' '
|
|||||||
grep "server-option=world" log
|
grep "server-option=world" log
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'server-options are sent when fetch multiple remotes' '
|
||||||
|
test_when_finished "rm -f log server_options_sent" &&
|
||||||
|
git clone "file://$(pwd)/file_parent" child_multi_remotes &&
|
||||||
|
git -C child_multi_remotes remote add another "file://$(pwd)/file_parent" &&
|
||||||
|
GIT_TRACE_PACKET="$(pwd)/log" git -C child_multi_remotes -c protocol.version=2 \
|
||||||
|
fetch -o hello --all &&
|
||||||
|
grep "fetch> server-option=hello" log >server_options_sent &&
|
||||||
|
test_line_count = 2 server_options_sent
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'server-options from configuration are used by git-fetch' '
|
||||||
|
test_when_finished "rm -rf log myclone" &&
|
||||||
|
git clone "file://$(pwd)/file_parent" myclone &&
|
||||||
|
git -C file_parent log -1 --format=%s >expect &&
|
||||||
|
|
||||||
|
# Default server options from configuration are used
|
||||||
|
git -C myclone config --add remote.origin.serverOption foo &&
|
||||||
|
git -C myclone config --add remote.origin.serverOption bar &&
|
||||||
|
GIT_TRACE_PACKET="$(pwd)/log" git -C myclone -c protocol.version=2 \
|
||||||
|
fetch origin main &&
|
||||||
|
git -C myclone log -1 --format=%s origin/main >actual &&
|
||||||
|
test_cmp expect actual &&
|
||||||
|
test_grep "fetch> server-option=foo" log &&
|
||||||
|
test_grep "fetch> server-option=bar" log &&
|
||||||
|
rm -f log &&
|
||||||
|
|
||||||
|
# Empty value of remote.<name>.serverOption clears the list
|
||||||
|
git -C myclone config --add remote.origin.serverOption "" &&
|
||||||
|
git -C myclone config --add remote.origin.serverOption tar &&
|
||||||
|
GIT_TRACE_PACKET="$(pwd)/log" git -C myclone -c protocol.version=2 \
|
||||||
|
fetch origin main &&
|
||||||
|
git -C myclone log -1 --format=%s origin/main >actual &&
|
||||||
|
test_cmp expect actual &&
|
||||||
|
test_grep "fetch> server-option=tar" log &&
|
||||||
|
test_grep ! "fetch> server-option=foo" log &&
|
||||||
|
test_grep ! "fetch> server-option=bar" log &&
|
||||||
|
rm -f log &&
|
||||||
|
|
||||||
|
# Server option from command line overrides those from configuration
|
||||||
|
GIT_TRACE_PACKET="$(pwd)/log" git -C myclone -c protocol.version=2 \
|
||||||
|
fetch -o hello -o world origin main &&
|
||||||
|
git -C myclone log -1 --format=%s origin/main >actual &&
|
||||||
|
test_cmp expect actual &&
|
||||||
|
test_grep "fetch> server-option=hello" log &&
|
||||||
|
test_grep "fetch> server-option=world" log &&
|
||||||
|
test_grep ! "fetch> server-option=tar" log
|
||||||
|
'
|
||||||
|
|
||||||
test_expect_success 'warn if using server-option with fetch with legacy protocol' '
|
test_expect_success 'warn if using server-option with fetch with legacy protocol' '
|
||||||
test_when_finished "rm -rf temp_child" &&
|
test_when_finished "rm -rf temp_child" &&
|
||||||
|
|
||||||
@ -404,6 +489,37 @@ test_expect_success 'server-options are sent when cloning' '
|
|||||||
grep "server-option=world" log
|
grep "server-option=world" log
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'server-options from configuration are used by git-clone' '
|
||||||
|
test_when_finished "rm -rf log myclone" &&
|
||||||
|
|
||||||
|
# Default server options from configuration are used
|
||||||
|
GIT_TRACE_PACKET="$(pwd)/log" git -c protocol.version=2 \
|
||||||
|
-c remote.origin.serverOption=foo -c remote.origin.serverOption=bar \
|
||||||
|
clone "file://$(pwd)/file_parent" myclone &&
|
||||||
|
test_grep "clone> server-option=foo" log &&
|
||||||
|
test_grep "clone> server-option=bar" log &&
|
||||||
|
rm -rf log myclone &&
|
||||||
|
|
||||||
|
# Empty value of remote.<name>.serverOption clears the list
|
||||||
|
GIT_TRACE_PACKET="$(pwd)/log" git -c protocol.version=2 \
|
||||||
|
-c remote.origin.serverOption=foo -c remote.origin.serverOption=bar \
|
||||||
|
-c remote.origin.serverOption= -c remote.origin.serverOption=tar \
|
||||||
|
clone "file://$(pwd)/file_parent" myclone &&
|
||||||
|
test_grep "clone> server-option=tar" log &&
|
||||||
|
test_grep ! "clone> server-option=foo" log &&
|
||||||
|
test_grep ! "clone> server-option=bar" log &&
|
||||||
|
rm -rf log myclone &&
|
||||||
|
|
||||||
|
# Server option from command line overrides those from configuration
|
||||||
|
GIT_TRACE_PACKET="$(pwd)/log" git -c protocol.version=2 \
|
||||||
|
-c remote.origin.serverOption=tar \
|
||||||
|
clone --server-option=hello --server-option=world \
|
||||||
|
"file://$(pwd)/file_parent" myclone &&
|
||||||
|
test_grep "clone> server-option=hello" log &&
|
||||||
|
test_grep "clone> server-option=world" log &&
|
||||||
|
test_grep ! "clone> server-option=tar" log
|
||||||
|
'
|
||||||
|
|
||||||
test_expect_success 'warn if using server-option with clone with legacy protocol' '
|
test_expect_success 'warn if using server-option with clone with legacy protocol' '
|
||||||
test_when_finished "rm -rf myclone" &&
|
test_when_finished "rm -rf myclone" &&
|
||||||
|
|
||||||
@ -415,6 +531,23 @@ test_expect_success 'warn if using server-option with clone with legacy protocol
|
|||||||
test_grep "server options require protocol version 2 or later" err
|
test_grep "server options require protocol version 2 or later" err
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'server-option configuration with legacy protocol is ok' '
|
||||||
|
test_when_finished "rm -rf myclone" &&
|
||||||
|
|
||||||
|
env GIT_TEST_PROTOCOL_VERSION=0 git -c protocol.version=0 \
|
||||||
|
-c remote.origin.serverOption=foo -c remote.origin.serverOption=bar \
|
||||||
|
clone "file://$(pwd)/file_parent" myclone
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'invalid server-option configuration' '
|
||||||
|
test_when_finished "rm -rf myclone" &&
|
||||||
|
|
||||||
|
test_must_fail git -c protocol.version=2 \
|
||||||
|
-c remote.origin.serverOption \
|
||||||
|
clone "file://$(pwd)/file_parent" myclone 2>err &&
|
||||||
|
test_grep "error: missing value for '\''remote.origin.serveroption'\''" err
|
||||||
|
'
|
||||||
|
|
||||||
test_expect_success 'upload-pack respects config using protocol v2' '
|
test_expect_success 'upload-pack respects config using protocol v2' '
|
||||||
git init server &&
|
git init server &&
|
||||||
write_script server/.git/hook <<-\EOF &&
|
write_script server/.git/hook <<-\EOF &&
|
||||||
|
15
transport.c
15
transport.c
@ -334,6 +334,9 @@ static struct ref *handshake(struct transport *transport, int for_push,
|
|||||||
data->version = discover_version(&reader);
|
data->version = discover_version(&reader);
|
||||||
switch (data->version) {
|
switch (data->version) {
|
||||||
case protocol_v2:
|
case protocol_v2:
|
||||||
|
if ((!transport->server_options || !transport->server_options->nr) &&
|
||||||
|
transport->remote->server_options.nr)
|
||||||
|
transport->server_options = &transport->remote->server_options;
|
||||||
if (server_feature_v2("session-id", &server_sid))
|
if (server_feature_v2("session-id", &server_sid))
|
||||||
trace2_data_string("transfer", NULL, "server-sid", server_sid);
|
trace2_data_string("transfer", NULL, "server-sid", server_sid);
|
||||||
if (must_list_refs)
|
if (must_list_refs)
|
||||||
@ -1108,6 +1111,18 @@ int is_transport_allowed(const char *type, int from_user)
|
|||||||
BUG("invalid protocol_allow_config type");
|
BUG("invalid protocol_allow_config type");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int parse_transport_option(const char *var, const char *value,
|
||||||
|
struct string_list *transport_options)
|
||||||
|
{
|
||||||
|
if (!value)
|
||||||
|
return config_error_nonbool(var);
|
||||||
|
if (!*value)
|
||||||
|
string_list_clear(transport_options, 0);
|
||||||
|
else
|
||||||
|
string_list_append(transport_options, value);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void transport_check_allowed(const char *type)
|
void transport_check_allowed(const char *type)
|
||||||
{
|
{
|
||||||
if (!is_transport_allowed(type, -1))
|
if (!is_transport_allowed(type, -1))
|
||||||
|
@ -342,4 +342,8 @@ void transport_print_push_status(const char *dest, struct ref *refs,
|
|||||||
/* common method used by transport-helper.c and send-pack.c */
|
/* common method used by transport-helper.c and send-pack.c */
|
||||||
void reject_atomic_push(struct ref *refs, int mirror_mode);
|
void reject_atomic_push(struct ref *refs, int mirror_mode);
|
||||||
|
|
||||||
|
/* common method to parse push-option or server-option from config */
|
||||||
|
int parse_transport_option(const char *var, const char *value,
|
||||||
|
struct string_list *transport_options);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Reference in New Issue
Block a user