When renaming a remote with git remote rename X Y Git already renames any branch.<name>.remote and branch.<name>.pushRemote values from X to Y. 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 when set in a repo configuration though. Signed-off-by: Bert Wesarg <bert.wesarg@xxxxxxxxxxxxxx> --- Matthew, you are in Cc because of your current work 'config: allow user to know scope of config options'. I think I'm correct to assuming an ordering of the enum config_scope. Cc: Junio C Hamano <gitster@xxxxxxxxx> Cc: Johannes Schindelin <johannes.schindelin@xxxxxx> Cc: Matthew Rogers <mattr94@xxxxxxxxx> --- builtin/remote.c | 43 ++++++++++++++++++++++++++++++++++++++++ t/t5505-remote.sh | 50 ++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 92 insertions(+), 1 deletion(-) diff --git a/builtin/remote.c b/builtin/remote.c index 0cb930fe00..52172e523a 100644 --- a/builtin/remote.c +++ b/builtin/remote.c @@ -611,6 +611,29 @@ static int migrate_file(struct remote *remote) return 0; } +struct push_default_info +{ + struct rename_info *rename; + 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") || strcmp(value, info->rename->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 int mv(int argc, const char **argv) { struct option options[] = { @@ -746,6 +769,26 @@ static int mv(int argc, const char **argv) die(_("creating '%s' failed"), buf.buf); } string_list_clear(&remote_branches, 1); + + struct push_default_info push_default; + push_default.rename = &rename; + push_default.scope = CONFIG_SCOPE_UNKNOWN; + push_default.origin = &buf; + git_config(config_read_push_default, &push_default); + if (push_default.scope >= CONFIG_SCOPE_CMDLINE) + ; /* pass */ + else if (push_default.scope >= CONFIG_SCOPE_REPO) { + git_config_set("remote.pushDefault", rename.new_name); + } 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, + rename.old_name); + } + return 0; } diff --git a/t/t5505-remote.sh b/t/t5505-remote.sh index 59a1681636..3b84c7bf9b 100755 --- a/t/t5505-remote.sh +++ b/t/t5505-remote.sh @@ -737,6 +737,7 @@ test_expect_success 'rename a remote' ' git clone one four && ( cd four && + test_config_global remote.pushDefault origin && git config branch.master.pushRemote origin && git remote rename origin upstream && test -z "$(git for-each-ref refs/remotes/origin)" && @@ -744,7 +745,54 @@ 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 remote.pushDefault)" = "upstream" + ) +' + +test_expect_success 'rename a remote keeps global remote.pushDefault' ' + git clone one four.2 && + ( + cd four.2 && + test_config_global remote.pushDefault origin && + git config remote.pushDefault other && + git remote rename origin upstream && + test "$(git config --global remote.pushDefault)" = "origin" && + test "$(git config remote.pushDefault)" = "other" + ) +' + +test_expect_success 'rename a remote renames repo remote.pushDefault but ignores global' ' + git clone one four.3 && + ( + cd four.3 && + test_config_global remote.pushDefault other && + git config remote.pushDefault origin && + git remote rename origin upstream && + test "$(git config --global remote.pushDefault)" = "other" && + test "$(git config remote.pushDefault)" = "upstream" + ) +' + +test_expect_success 'rename a remote renames repo remote.pushDefault but keeps global' ' + git clone one four.4 && + ( + cd four.4 && + test_config_global remote.pushDefault origin && + git config remote.pushDefault origin && + git remote rename origin upstream && + test "$(git config --global remote.pushDefault)" = "origin" && + test "$(git config remote.pushDefault)" = "upstream" ) ' -- 2.24.1.497.g9abd7b20b4.dirty