Skip to content

Commit c692fe2

Browse files
committed
Merge branch 'mp/push-pushoption-config'
The "--push-option=<string>" option to "git push" now defaults to a list of strings configured via push.pushOption variable. * mp/push-pushoption-config: builtin/push.c: add push.pushOption config
2 parents b4d658b + d805275 commit c692fe2

File tree

4 files changed

+135
-7
lines changed

4 files changed

+135
-7
lines changed

Documentation/config.txt

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2624,6 +2624,35 @@ push.gpgSign::
26242624
override a value from a lower-priority config file. An explicit
26252625
command-line flag always overrides this config option.
26262626

2627+
push.pushOption::
2628+
When no `--push-option=<option>` argument is given from the
2629+
command line, `git push` behaves as if each <value> of
2630+
this variable is given as `--push-option=<value>`.
2631+
+
2632+
This is a multi-valued variable, and an empty value can be used in a
2633+
higher priority configuration file (e.g. `.git/config` in a
2634+
repository) to clear the values inherited from a lower priority
2635+
configuration files (e.g. `$HOME/.gitconfig`).
2636+
+
2637+
--
2638+
2639+
Example:
2640+
2641+
/etc/gitconfig
2642+
push.pushoption = a
2643+
push.pushoption = b
2644+
2645+
~/.gitconfig
2646+
push.pushoption = c
2647+
2648+
repo/.git/config
2649+
push.pushoption =
2650+
push.pushoption = b
2651+
2652+
This will result in only b (a and c are cleared).
2653+
2654+
--
2655+
26272656
push.recurseSubmodules::
26282657
Make sure all submodule commits used by the revisions to be pushed
26292658
are available on a remote-tracking branch. If the value is 'check'

Documentation/git-push.txt

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,11 +156,17 @@ already exists on the remote side.
156156
Either all refs are updated, or on error, no refs are updated.
157157
If the server does not support atomic pushes the push will fail.
158158

159-
-o::
160-
--push-option::
159+
-o <option>::
160+
--push-option=<option>::
161161
Transmit the given string to the server, which passes them to
162162
the pre-receive as well as the post-receive hook. The given string
163163
must not contain a NUL or LF character.
164+
When multiple `--push-option=<option>` are given, they are
165+
all sent to the other side in the order listed on the
166+
command line.
167+
When no `--push-option=<option>` is given from the command
168+
line, the values of configuration variable `push.pushOption`
169+
are used instead.
164170

165171
--receive-pack=<git-receive-pack>::
166172
--exec=<git-receive-pack>::

builtin/push.c

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ static const char **refspec;
3232
static int refspec_nr;
3333
static int refspec_alloc;
3434

35+
static struct string_list push_options_config = STRING_LIST_INIT_DUP;
36+
3537
static void add_refspec(const char *ref)
3638
{
3739
refspec_nr++;
@@ -503,6 +505,15 @@ static int git_push_config(const char *k, const char *v, void *cb)
503505
int val = git_config_bool(k, v) ?
504506
RECURSE_SUBMODULES_ON_DEMAND : RECURSE_SUBMODULES_OFF;
505507
recurse_submodules = val;
508+
} else if (!strcmp(k, "push.pushoption")) {
509+
if (!v)
510+
return config_error_nonbool(k);
511+
else
512+
if (!*v)
513+
string_list_clear(&push_options_config, 0);
514+
else
515+
string_list_append(&push_options_config, v);
516+
return 0;
506517
}
507518

508519
return git_default_config(k, v, NULL);
@@ -515,7 +526,8 @@ int cmd_push(int argc, const char **argv, const char *prefix)
515526
int push_cert = -1;
516527
int rc;
517528
const char *repo = NULL; /* default repository */
518-
struct string_list push_options = STRING_LIST_INIT_DUP;
529+
struct string_list push_options_cmdline = STRING_LIST_INIT_DUP;
530+
struct string_list *push_options;
519531
const struct string_list_item *item;
520532

521533
struct option options[] = {
@@ -551,7 +563,7 @@ int cmd_push(int argc, const char **argv, const char *prefix)
551563
0, "signed", &push_cert, "yes|no|if-asked", N_("GPG sign the push"),
552564
PARSE_OPT_OPTARG, option_parse_push_signed },
553565
OPT_BIT(0, "atomic", &flags, N_("request atomic transaction on remote side"), TRANSPORT_PUSH_ATOMIC),
554-
OPT_STRING_LIST('o', "push-option", &push_options, N_("server-specific"), N_("option to transmit")),
566+
OPT_STRING_LIST('o', "push-option", &push_options_cmdline, N_("server-specific"), N_("option to transmit")),
555567
OPT_SET_INT('4', "ipv4", &family, N_("use IPv4 addresses only"),
556568
TRANSPORT_FAMILY_IPV4),
557569
OPT_SET_INT('6', "ipv6", &family, N_("use IPv6 addresses only"),
@@ -562,6 +574,9 @@ int cmd_push(int argc, const char **argv, const char *prefix)
562574
packet_trace_identity("push");
563575
git_config(git_push_config, &flags);
564576
argc = parse_options(argc, argv, prefix, options, push_usage, 0);
577+
push_options = (push_options_cmdline.nr
578+
? &push_options_cmdline
579+
: &push_options_config);
565580
set_push_cert_flags(&flags, push_cert);
566581

567582
if (deleterefs && (tags || (flags & (TRANSPORT_PUSH_ALL | TRANSPORT_PUSH_MIRROR))))
@@ -584,12 +599,13 @@ int cmd_push(int argc, const char **argv, const char *prefix)
584599
set_refspecs(argv + 1, argc - 1, repo);
585600
}
586601

587-
for_each_string_list_item(item, &push_options)
602+
for_each_string_list_item(item, push_options)
588603
if (strchr(item->string, '\n'))
589604
die(_("push options must not have new line characters"));
590605

591-
rc = do_push(repo, flags, &push_options);
592-
string_list_clear(&push_options, 0);
606+
rc = do_push(repo, flags, push_options);
607+
string_list_clear(&push_options_cmdline, 0);
608+
string_list_clear(&push_options_config, 0);
593609
if (rc == -1)
594610
usage_with_options(push_usage, options);
595611
else

t/t5545-push-options.sh

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,83 @@ test_expect_success 'push options and submodules' '
140140
test_cmp expect parent_upstream/.git/hooks/post-receive.push_options
141141
'
142142

143+
test_expect_success 'default push option' '
144+
mk_repo_pair &&
145+
git -C upstream config receive.advertisePushOptions true &&
146+
(
147+
cd workbench &&
148+
test_commit one &&
149+
git push --mirror up &&
150+
test_commit two &&
151+
git -c push.pushOption=default push up master
152+
) &&
153+
test_refs master master &&
154+
echo "default" >expect &&
155+
test_cmp expect upstream/.git/hooks/pre-receive.push_options &&
156+
test_cmp expect upstream/.git/hooks/post-receive.push_options
157+
'
158+
159+
test_expect_success 'two default push options' '
160+
mk_repo_pair &&
161+
git -C upstream config receive.advertisePushOptions true &&
162+
(
163+
cd workbench &&
164+
test_commit one &&
165+
git push --mirror up &&
166+
test_commit two &&
167+
git -c push.pushOption=default1 -c push.pushOption=default2 push up master
168+
) &&
169+
test_refs master master &&
170+
printf "default1\ndefault2\n" >expect &&
171+
test_cmp expect upstream/.git/hooks/pre-receive.push_options &&
172+
test_cmp expect upstream/.git/hooks/post-receive.push_options
173+
'
174+
175+
test_expect_success 'push option from command line overrides from-config push option' '
176+
mk_repo_pair &&
177+
git -C upstream config receive.advertisePushOptions true &&
178+
(
179+
cd workbench &&
180+
test_commit one &&
181+
git push --mirror up &&
182+
test_commit two &&
183+
git -c push.pushOption=default push --push-option=manual up master
184+
) &&
185+
test_refs master master &&
186+
echo "manual" >expect &&
187+
test_cmp expect upstream/.git/hooks/pre-receive.push_options &&
188+
test_cmp expect upstream/.git/hooks/post-receive.push_options
189+
'
190+
191+
test_expect_success 'empty value of push.pushOption in config clears the list' '
192+
mk_repo_pair &&
193+
git -C upstream config receive.advertisePushOptions true &&
194+
(
195+
cd workbench &&
196+
test_commit one &&
197+
git push --mirror up &&
198+
test_commit two &&
199+
git -c push.pushOption=default1 -c push.pushOption= -c push.pushOption=default2 push up master
200+
) &&
201+
test_refs master master &&
202+
echo "default2" >expect &&
203+
test_cmp expect upstream/.git/hooks/pre-receive.push_options &&
204+
test_cmp expect upstream/.git/hooks/post-receive.push_options
205+
'
206+
207+
test_expect_success 'invalid push option in config' '
208+
mk_repo_pair &&
209+
git -C upstream config receive.advertisePushOptions true &&
210+
(
211+
cd workbench &&
212+
test_commit one &&
213+
git push --mirror up &&
214+
test_commit two &&
215+
test_must_fail git -c push.pushOption push up master
216+
) &&
217+
test_refs master HEAD@{1}
218+
'
219+
143220
. "$TEST_DIRECTORY"/lib-httpd.sh
144221
start_httpd
145222

0 commit comments

Comments
 (0)