remote: write correct fetch spec when renaming remote 'remote'

When renaming a remote whose name is contained in a configured fetch refspec for that remote, we currently replace the first occurrence of the remote name in the refspec. This is correct in most cases, but breaks if the remote name occurs in the fetch refspec before the expected place. For example, we currently change [remote "remote"] url = git://git.kernel.org/pub/scm/git/git.git fetch = +refs/heads/*:refs/remotes/remote/* into [remote "origin"] url = git://git.kernel.org/pub/scm/git/git.git fetch = +refs/heads/*:refs/origins/remote/* Reduce the risk of changing incorrect sections of the refspec by matching the entire ":refs/remotes/<name>/" instead of just "<name>". Signed-off-by: Martin von Zweigbergk <martin.von.zweigbergk@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Martin von Zweigbergk committed Sep 1, 2011 at 20:50 UTC 28f555f6357ee0706847aff5b476b31b472b325c
2 files changed +28 -4
builtin/remote.c
+8 -4
@@ -631,7 +631,8 @@ static int mv(int argc, const char **argv)
631 OPT_END()
632 };
633 struct remote *oldremote, *newremote;
634 - struct strbuf buf = STRBUF_INIT, buf2 = STRBUF_INIT, buf3 = STRBUF_INIT;
634 + struct strbuf buf = STRBUF_INIT, buf2 = STRBUF_INIT, buf3 = STRBUF_INIT,
635 + old_remote_context = STRBUF_INIT;
636 struct string_list remote_branches = STRING_LIST_INIT_NODUP;
637 struct rename_info rename;
638 int i;
@@ -669,15 +670,18 @@ static int mv(int argc, const char **argv)
670 strbuf_addf(&buf, "remote.%s.fetch", rename.new);
671 if (git_config_set_multivar(buf.buf, NULL, NULL, 1))
672 return error("Could not remove config section '%s'", buf.buf);
673 + strbuf_addf(&old_remote_context, ":refs/remotes/%s/", rename.old);
674 for (i = 0; i < oldremote->fetch_refspec_nr; i++) {
675 char *ptr;
676
677 strbuf_reset(&buf2);
678 strbuf_addstr(&buf2, oldremote->fetch_refspec[i]);
677 - ptr = strstr(buf2.buf, rename.old);
679 + ptr = strstr(buf2.buf, old_remote_context.buf);
680 if (ptr)
679 - strbuf_splice(&buf2, ptr-buf2.buf, strlen(rename.old),
680 - rename.new, strlen(rename.new));
681 + strbuf_splice(&buf2,
682 + ptr-buf2.buf + strlen(":refs/remotes/"),
683 + strlen(rename.old), rename.new,
684 + strlen(rename.new));
685 if (git_config_set_multivar(buf.buf, buf2.buf, "^$", 0))
686 return error("Could not append '%s'", buf.buf);
687 }
t/t5505-remote.sh
+20
@@ -631,6 +631,26 @@ test_expect_success 'rename a remote' '
631
632 '
633
634 +test_expect_success 'rename does not update a non-default fetch refspec' '
635 +
636 + git clone one four.one &&
637 + (cd four.one &&
638 + git config remote.origin.fetch +refs/heads/*:refs/heads/origin/* &&
639 + git remote rename origin upstream &&
640 + test "$(git config remote.upstream.fetch)" = "+refs/heads/*:refs/heads/origin/*")
641 +
642 +'
643 +
644 +test_expect_success 'rename a remote with name part of fetch spec' '
645 +
646 + git clone one four.two &&
647 + (cd four.two &&
648 + git remote rename origin remote &&
649 + git remote rename remote upstream &&
650 + test "$(git config remote.upstream.fetch)" = "+refs/heads/*:refs/remotes/upstream/*")
651 +
652 +'
653 +
654 cat > remotes_origin << EOF
655 URL: $(pwd)/one
656 Push: refs/heads/master:refs/heads/upstream