Skip to content

Commit b3fd6cb

Browse files
bertwesarggitster
authored andcommitted
remote rename/remove: gently handle remote.pushDefault config
When renaming a remote with git remote rename X Y git remote remove X Git already renames or removes any branch.<name>.remote and branch.<name>.pushRemote configurations if their value is X. However remote.pushDefault needs a more gentle approach, as this may be set in a non-repo configuration file. In such a case only a warning is printed, such as: warning: The global configuration remote.pushDefault in: $HOME/.gitconfig:35 now names the non-existent remote origin It is changed to remote.pushDefault = Y or removed when set in a repo configuration though. Signed-off-by: Bert Wesarg <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent f2a2327 commit b3fd6cb

File tree

2 files changed

+129
-2
lines changed

2 files changed

+129
-2
lines changed

builtin/remote.c

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -615,6 +615,56 @@ static int migrate_file(struct remote *remote)
615615
return 0;
616616
}
617617

618+
struct push_default_info
619+
{
620+
const char *old_name;
621+
enum config_scope scope;
622+
struct strbuf origin;
623+
int linenr;
624+
};
625+
626+
static int config_read_push_default(const char *key, const char *value,
627+
void *cb)
628+
{
629+
struct push_default_info* info = cb;
630+
if (strcmp(key, "remote.pushdefault") ||
631+
!value || strcmp(value, info->old_name))
632+
return 0;
633+
634+
info->scope = current_config_scope();
635+
strbuf_reset(&info->origin);
636+
strbuf_addstr(&info->origin, current_config_name());
637+
info->linenr = current_config_line();
638+
639+
return 0;
640+
}
641+
642+
static void handle_push_default(const char* old_name, const char* new_name)
643+
{
644+
struct push_default_info push_default = {
645+
old_name, CONFIG_SCOPE_UNKNOWN, STRBUF_INIT, -1 };
646+
git_config(config_read_push_default, &push_default);
647+
if (push_default.scope >= CONFIG_SCOPE_COMMAND)
648+
; /* pass */
649+
else if (push_default.scope >= CONFIG_SCOPE_LOCAL) {
650+
int result = git_config_set_gently("remote.pushDefault",
651+
new_name);
652+
if (new_name && result && result != CONFIG_NOTHING_SET)
653+
die(_("could not set '%s'"), "remote.pushDefault");
654+
else if (!new_name && result && result != CONFIG_NOTHING_SET)
655+
die(_("could not unset '%s'"), "remote.pushDefault");
656+
} else if (push_default.scope >= CONFIG_SCOPE_SYSTEM) {
657+
/* warn */
658+
warning(_("The %s configuration remote.pushDefault in:\n"
659+
"\t%s:%d\n"
660+
"now names the non-existent remote '%s'"),
661+
config_scope_name(push_default.scope),
662+
push_default.origin.buf, push_default.linenr,
663+
old_name);
664+
}
665+
}
666+
667+
618668
static int mv(int argc, const char **argv)
619669
{
620670
struct option options[] = {
@@ -750,6 +800,9 @@ static int mv(int argc, const char **argv)
750800
die(_("creating '%s' failed"), buf.buf);
751801
}
752802
string_list_clear(&remote_branches, 1);
803+
804+
handle_push_default(rename.old_name, rename.new_name);
805+
753806
return 0;
754807
}
755808

@@ -835,6 +888,8 @@ static int rm(int argc, const char **argv)
835888
strbuf_addf(&buf, "remote.%s", remote->name);
836889
if (git_config_rename_section(buf.buf, NULL) < 1)
837890
return error(_("Could not remove config section '%s'"), buf.buf);
891+
892+
handle_push_default(remote->name, NULL);
838893
}
839894

840895
return result;

t/t5505-remote.sh

Lines changed: 74 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -734,6 +734,7 @@ test_expect_success 'reject adding remote with an invalid name' '
734734
# the last two ones check if the config is updated.
735735

736736
test_expect_success 'rename a remote' '
737+
test_config_global remote.pushDefault origin &&
737738
git clone one four &&
738739
(
739740
cd four &&
@@ -744,7 +745,42 @@ test_expect_success 'rename a remote' '
744745
test "$(git rev-parse upstream/master)" = "$(git rev-parse master)" &&
745746
test "$(git config remote.upstream.fetch)" = "+refs/heads/*:refs/remotes/upstream/*" &&
746747
test "$(git config branch.master.remote)" = "upstream" &&
747-
test "$(git config branch.master.pushRemote)" = "upstream"
748+
test "$(git config branch.master.pushRemote)" = "upstream" &&
749+
test "$(git config --global remote.pushDefault)" = "origin"
750+
)
751+
'
752+
753+
test_expect_success 'rename a remote renames repo remote.pushDefault' '
754+
git clone one four.1 &&
755+
(
756+
cd four.1 &&
757+
git config remote.pushDefault origin &&
758+
git remote rename origin upstream &&
759+
test "$(git config --local remote.pushDefault)" = "upstream"
760+
)
761+
'
762+
763+
test_expect_success 'rename a remote renames repo remote.pushDefault but ignores global' '
764+
test_config_global remote.pushDefault other &&
765+
git clone one four.2 &&
766+
(
767+
cd four.2 &&
768+
git config remote.pushDefault origin &&
769+
git remote rename origin upstream &&
770+
test "$(git config --global remote.pushDefault)" = "other" &&
771+
test "$(git config --local remote.pushDefault)" = "upstream"
772+
)
773+
'
774+
775+
test_expect_success 'rename a remote renames repo remote.pushDefault but keeps global' '
776+
test_config_global remote.pushDefault origin &&
777+
git clone one four.3 &&
778+
(
779+
cd four.3 &&
780+
git config remote.pushDefault origin &&
781+
git remote rename origin upstream &&
782+
test "$(git config --global remote.pushDefault)" = "origin" &&
783+
test "$(git config --local remote.pushDefault)" = "upstream"
748784
)
749785
'
750786

@@ -787,14 +823,50 @@ test_expect_success 'rename succeeds with existing remote.<target>.prune' '
787823
'
788824

789825
test_expect_success 'remove a remote' '
826+
test_config_global remote.pushDefault origin &&
790827
git clone one four.five &&
791828
(
792829
cd four.five &&
793830
git config branch.master.pushRemote origin &&
794831
git remote remove origin &&
795832
test -z "$(git for-each-ref refs/remotes/origin)" &&
796833
test_must_fail git config branch.master.remote &&
797-
test_must_fail git config branch.master.pushRemote
834+
test_must_fail git config branch.master.pushRemote &&
835+
test "$(git config --global remote.pushDefault)" = "origin"
836+
)
837+
'
838+
839+
test_expect_success 'remove a remote removes repo remote.pushDefault' '
840+
git clone one four.five.1 &&
841+
(
842+
cd four.five.1 &&
843+
git config remote.pushDefault origin &&
844+
git remote remove origin &&
845+
test_must_fail git config --local remote.pushDefault
846+
)
847+
'
848+
849+
test_expect_success 'remove a remote removes repo remote.pushDefault but ignores global' '
850+
test_config_global remote.pushDefault other &&
851+
git clone one four.five.2 &&
852+
(
853+
cd four.five.2 &&
854+
git config remote.pushDefault origin &&
855+
git remote remove origin &&
856+
test "$(git config --global remote.pushDefault)" = "other" &&
857+
test_must_fail git config --local remote.pushDefault
858+
)
859+
'
860+
861+
test_expect_success 'remove a remote removes repo remote.pushDefault but keeps global' '
862+
test_config_global remote.pushDefault origin &&
863+
git clone one four.five.3 &&
864+
(
865+
cd four.five.3 &&
866+
git config remote.pushDefault origin &&
867+
git remote remove origin &&
868+
test "$(git config --global remote.pushDefault)" = "origin" &&
869+
test_must_fail git config --local remote.pushDefault
798870
)
799871
'
800872

0 commit comments

Comments
 (0)