Skip to content

Commit 8e4c8af

Browse files
tgummerergitster
authored andcommitted
push: disallow --all and refspecs when remote.<name>.mirror is set
Pushes with --all, or refspecs are disallowed when --mirror is given to 'git push', or when 'remote.<name>.mirror' is set in the config of the repository, because they can have surprising effects. 800a4ab ("push: check for errors earlier", 2018-05-16) refactored this code to do that check earlier, so we can explicitly check for the presence of flags, instead of their sideeffects. However when 'remote.<name>.mirror' is set in the config, the TRANSPORT_PUSH_MIRROR flag would only be set after we calling 'do_push()', so the checks would miss it entirely. This leads to surprises for users [*1*]. Fix this by making sure we set the flag (if appropriate) before checking for compatibility of the various options. *1*: https://twitter.com/FiloSottile/status/1163918701462249472 Reported-by: Filippo Valsorda <[email protected]> Helped-by: Saleem Rashid Signed-off-by: Thomas Gummerer <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 0d0ac38 commit 8e4c8af

File tree

2 files changed

+46
-33
lines changed

2 files changed

+46
-33
lines changed

builtin/push.c

Lines changed: 36 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -382,30 +382,14 @@ static int push_with_options(struct transport *transport, struct refspec *rs,
382382
}
383383

384384
static int do_push(const char *repo, int flags,
385-
const struct string_list *push_options)
385+
const struct string_list *push_options,
386+
struct remote *remote)
386387
{
387388
int i, errs;
388-
struct remote *remote = pushremote_get(repo);
389389
const char **url;
390390
int url_nr;
391391
struct refspec *push_refspec = &rs;
392392

393-
if (!remote) {
394-
if (repo)
395-
die(_("bad repository '%s'"), repo);
396-
die(_("No configured push destination.\n"
397-
"Either specify the URL from the command-line or configure a remote repository using\n"
398-
"\n"
399-
" git remote add <name> <url>\n"
400-
"\n"
401-
"and then push using the remote name\n"
402-
"\n"
403-
" git push <name>\n"));
404-
}
405-
406-
if (remote->mirror)
407-
flags |= (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE);
408-
409393
if (push_options->nr)
410394
flags |= TRANSPORT_PUSH_OPTIONS;
411395

@@ -545,6 +529,7 @@ int cmd_push(int argc, const char **argv, const char *prefix)
545529
struct string_list push_options_cmdline = STRING_LIST_INIT_DUP;
546530
struct string_list *push_options;
547531
const struct string_list_item *item;
532+
struct remote *remote;
548533

549534
struct option options[] = {
550535
OPT__VERBOSITY(&verbosity),
@@ -599,20 +584,6 @@ int cmd_push(int argc, const char **argv, const char *prefix)
599584
die(_("--delete is incompatible with --all, --mirror and --tags"));
600585
if (deleterefs && argc < 2)
601586
die(_("--delete doesn't make sense without any refs"));
602-
if (flags & TRANSPORT_PUSH_ALL) {
603-
if (tags)
604-
die(_("--all and --tags are incompatible"));
605-
if (argc >= 2)
606-
die(_("--all can't be combined with refspecs"));
607-
}
608-
if (flags & TRANSPORT_PUSH_MIRROR) {
609-
if (tags)
610-
die(_("--mirror and --tags are incompatible"));
611-
if (argc >= 2)
612-
die(_("--mirror can't be combined with refspecs"));
613-
}
614-
if ((flags & TRANSPORT_PUSH_ALL) && (flags & TRANSPORT_PUSH_MIRROR))
615-
die(_("--all and --mirror are incompatible"));
616587

617588
if (recurse_submodules == RECURSE_SUBMODULES_CHECK)
618589
flags |= TRANSPORT_RECURSE_SUBMODULES_CHECK;
@@ -629,11 +600,43 @@ int cmd_push(int argc, const char **argv, const char *prefix)
629600
set_refspecs(argv + 1, argc - 1, repo);
630601
}
631602

603+
remote = pushremote_get(repo);
604+
if (!remote) {
605+
if (repo)
606+
die(_("bad repository '%s'"), repo);
607+
die(_("No configured push destination.\n"
608+
"Either specify the URL from the command-line or configure a remote repository using\n"
609+
"\n"
610+
" git remote add <name> <url>\n"
611+
"\n"
612+
"and then push using the remote name\n"
613+
"\n"
614+
" git push <name>\n"));
615+
}
616+
617+
if (remote->mirror)
618+
flags |= (TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE);
619+
620+
if (flags & TRANSPORT_PUSH_ALL) {
621+
if (tags)
622+
die(_("--all and --tags are incompatible"));
623+
if (argc >= 2)
624+
die(_("--all can't be combined with refspecs"));
625+
}
626+
if (flags & TRANSPORT_PUSH_MIRROR) {
627+
if (tags)
628+
die(_("--mirror and --tags are incompatible"));
629+
if (argc >= 2)
630+
die(_("--mirror can't be combined with refspecs"));
631+
}
632+
if ((flags & TRANSPORT_PUSH_ALL) && (flags & TRANSPORT_PUSH_MIRROR))
633+
die(_("--all and --mirror are incompatible"));
634+
632635
for_each_string_list_item(item, push_options)
633636
if (strchr(item->string, '\n'))
634637
die(_("push options must not have new line characters"));
635638

636-
rc = do_push(repo, flags, push_options);
639+
rc = do_push(repo, flags, push_options, remote);
637640
string_list_clear(&push_options_cmdline, 0);
638641
string_list_clear(&push_options_config, 0);
639642
if (rc == -1)

t/t5517-push-mirror.sh

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,4 +265,14 @@ test_expect_success 'remote.foo.mirror=no has no effect' '
265265
266266
'
267267

268+
test_expect_success 'push to mirrored repository with refspec fails' '
269+
mk_repo_pair &&
270+
(
271+
cd master &&
272+
echo one >foo && git add foo && git commit -m one &&
273+
git config --add remote.up.mirror true &&
274+
test_must_fail git push up master
275+
)
276+
'
277+
268278
test_done

0 commit comments

Comments
 (0)