]> git.ipfire.org Git - thirdparty/git.git/commitdiff
remote rename/remove: gently handle remote.pushDefault config
authorBert Wesarg <bert.wesarg@googlemail.com>
Sat, 1 Feb 2020 09:34:09 +0000 (10:34 +0100)
committerJunio C Hamano <gitster@pobox.com>
Mon, 10 Feb 2020 18:52:10 +0000 (10:52 -0800)
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>
builtin/remote.c
t/t5505-remote.sh

index a2379a14bf988942e7b7011a0eed26e819f887b3..555d4c896c5fba060f3ef65ba591bbdb7d16a355 100644 (file)
@@ -615,6 +615,56 @@ static int migrate_file(struct remote *remote)
        return 0;
 }
 
+struct push_default_info
+{
+       const char *old_name;
+       enum config_scope scope;
+       struct strbuf origin;
+       int linenr;
+};
+
+static int config_read_push_default(const char *key, const char *value,
+       void *cb)
+{
+       struct push_default_info* info = cb;
+       if (strcmp(key, "remote.pushdefault") ||
+           !value || strcmp(value, info->old_name))
+               return 0;
+
+       info->scope = current_config_scope();
+       strbuf_reset(&info->origin);
+       strbuf_addstr(&info->origin, current_config_name());
+       info->linenr = current_config_line();
+
+       return 0;
+}
+
+static void handle_push_default(const char* old_name, const char* new_name)
+{
+       struct push_default_info push_default = {
+               old_name, CONFIG_SCOPE_UNKNOWN, STRBUF_INIT, -1 };
+       git_config(config_read_push_default, &push_default);
+       if (push_default.scope >= CONFIG_SCOPE_COMMAND)
+               ; /* pass */
+       else if (push_default.scope >= CONFIG_SCOPE_LOCAL) {
+               int result = git_config_set_gently("remote.pushDefault",
+                                                  new_name);
+               if (new_name && result && result != CONFIG_NOTHING_SET)
+                       die(_("could not set '%s'"), "remote.pushDefault");
+               else if (!new_name && result && result != CONFIG_NOTHING_SET)
+                       die(_("could not unset '%s'"), "remote.pushDefault");
+       } else if (push_default.scope >= CONFIG_SCOPE_SYSTEM) {
+               /* warn */
+               warning(_("The %s configuration remote.pushDefault in:\n"
+                         "\t%s:%d\n"
+                         "now names the non-existent remote '%s'"),
+                       config_scope_name(push_default.scope),
+                       push_default.origin.buf, push_default.linenr,
+                       old_name);
+       }
+}
+
+
 static int mv(int argc, const char **argv)
 {
        struct option options[] = {
@@ -750,6 +800,9 @@ static int mv(int argc, const char **argv)
                        die(_("creating '%s' failed"), buf.buf);
        }
        string_list_clear(&remote_branches, 1);
+
+       handle_push_default(rename.old_name, rename.new_name);
+
        return 0;
 }
 
@@ -835,6 +888,8 @@ static int rm(int argc, const char **argv)
                strbuf_addf(&buf, "remote.%s", remote->name);
                if (git_config_rename_section(buf.buf, NULL) < 1)
                        return error(_("Could not remove config section '%s'"), buf.buf);
+
+               handle_push_default(remote->name, NULL);
        }
 
        return result;
index 082042b05aeccd1bfe481447d1aa15c81f747822..dda81b7d07a2ee7c5ee24f28f5f8a527a3f187da 100755 (executable)
@@ -734,6 +734,7 @@ test_expect_success 'reject adding remote with an invalid name' '
 # the last two ones check if the config is updated.
 
 test_expect_success 'rename a remote' '
+       test_config_global remote.pushDefault origin &&
        git clone one four &&
        (
                cd four &&
@@ -744,7 +745,42 @@ test_expect_success 'rename a remote' '
                test "$(git rev-parse upstream/master)" = "$(git rev-parse master)" &&
                test "$(git config remote.upstream.fetch)" = "+refs/heads/*:refs/remotes/upstream/*" &&
                test "$(git config branch.master.remote)" = "upstream" &&
-               test "$(git config branch.master.pushRemote)" = "upstream"
+               test "$(git config branch.master.pushRemote)" = "upstream" &&
+               test "$(git config --global remote.pushDefault)" = "origin"
+       )
+'
+
+test_expect_success 'rename a remote renames repo remote.pushDefault' '
+       git clone one four.1 &&
+       (
+               cd four.1 &&
+               git config remote.pushDefault origin &&
+               git remote rename origin upstream &&
+               test "$(git config --local remote.pushDefault)" = "upstream"
+       )
+'
+
+test_expect_success 'rename a remote renames repo remote.pushDefault but ignores global' '
+       test_config_global remote.pushDefault other &&
+       git clone one four.2 &&
+       (
+               cd four.2 &&
+               git config remote.pushDefault origin &&
+               git remote rename origin upstream &&
+               test "$(git config --global remote.pushDefault)" = "other" &&
+               test "$(git config --local remote.pushDefault)" = "upstream"
+       )
+'
+
+test_expect_success 'rename a remote renames repo remote.pushDefault but keeps global' '
+       test_config_global remote.pushDefault origin &&
+       git clone one four.3 &&
+       (
+               cd four.3 &&
+               git config remote.pushDefault origin &&
+               git remote rename origin upstream &&
+               test "$(git config --global remote.pushDefault)" = "origin" &&
+               test "$(git config --local remote.pushDefault)" = "upstream"
        )
 '
 
@@ -787,6 +823,7 @@ test_expect_success 'rename succeeds with existing remote.<target>.prune' '
 '
 
 test_expect_success 'remove a remote' '
+       test_config_global remote.pushDefault origin &&
        git clone one four.five &&
        (
                cd four.five &&
@@ -794,7 +831,42 @@ test_expect_success 'remove a remote' '
                git remote remove origin &&
                test -z "$(git for-each-ref refs/remotes/origin)" &&
                test_must_fail git config branch.master.remote &&
-               test_must_fail git config branch.master.pushRemote
+               test_must_fail git config branch.master.pushRemote &&
+               test "$(git config --global remote.pushDefault)" = "origin"
+       )
+'
+
+test_expect_success 'remove a remote removes repo remote.pushDefault' '
+       git clone one four.five.1 &&
+       (
+               cd four.five.1 &&
+               git config remote.pushDefault origin &&
+               git remote remove origin &&
+               test_must_fail git config --local remote.pushDefault
+       )
+'
+
+test_expect_success 'remove a remote removes repo remote.pushDefault but ignores global' '
+       test_config_global remote.pushDefault other &&
+       git clone one four.five.2 &&
+       (
+               cd four.five.2 &&
+               git config remote.pushDefault origin &&
+               git remote remove origin &&
+               test "$(git config --global remote.pushDefault)" = "other" &&
+               test_must_fail git config --local remote.pushDefault
+       )
+'
+
+test_expect_success 'remove a remote removes repo remote.pushDefault but keeps global' '
+       test_config_global remote.pushDefault origin &&
+       git clone one four.five.3 &&
+       (
+               cd four.five.3 &&
+               git config remote.pushDefault origin &&
+               git remote remove origin &&
+               test "$(git config --global remote.pushDefault)" = "origin" &&
+               test_must_fail git config --local remote.pushDefault
        )
 '