@matheusbsbs / matheus-bagliano / commits / b3fd6cbf29
Fork 0

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 <bert.wesarg@googlemail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Bert Wesarg committed Feb 1, 2020 at 10:34 UTC b3fd6cbf29435f8b49a0a5d9f86236e00b084624
2 files changed +129 -2
builtin/remote.c
+55
@@ -615,6 +615,56 @@ static int migrate_file(struct remote *remote)
615 return 0;
616 }
617
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 +
668 static int mv(int argc, const char **argv)
669 {
670 struct option options[] = {
@@ -750,6 +800,9 @@ static int mv(int argc, const char **argv)
800 die(_("creating '%s' failed"), buf.buf);
801 }
802 string_list_clear(&remote_branches, 1);
803 +
804 + handle_push_default(rename.old_name, rename.new_name);
805 +
806 return 0;
807 }
808
@@ -835,6 +888,8 @@ static int rm(int argc, const char **argv)
888 strbuf_addf(&buf, "remote.%s", remote->name);
889 if (git_config_rename_section(buf.buf, NULL) < 1)
890 return error(_("Could not remove config section '%s'"), buf.buf);
891 +
892 + handle_push_default(remote->name, NULL);
893 }
894
895 return result;
t/t5505-remote.sh
+74 -2
@@ -734,6 +734,7 @@ test_expect_success 'reject adding remote with an invalid name' '
734 # the last two ones check if the config is updated.
735
736 test_expect_success 'rename a remote' '
737 + test_config_global remote.pushDefault origin &&
738 git clone one four &&
739 (
740 cd four &&
@@ -744,7 +745,42 @@ test_expect_success 'rename a remote' '
745 test "$(git rev-parse upstream/master)" = "$(git rev-parse master)" &&
746 test "$(git config remote.upstream.fetch)" = "+refs/heads/*:refs/remotes/upstream/*" &&
747 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"
784 )
785 '
786
@@ -787,6 +823,7 @@ test_expect_success 'rename succeeds with existing remote.<target>.prune' '
823 '
824
825 test_expect_success 'remove a remote' '
826 + test_config_global remote.pushDefault origin &&
827 git clone one four.five &&
828 (
829 cd four.five &&
@@ -794,7 +831,42 @@ test_expect_success 'remove a remote' '
831 git remote remove origin &&
832 test -z "$(git for-each-ref refs/remotes/origin)" &&
833 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
870 )
871 '
872