]> git.ipfire.org Git - thirdparty/git.git/commitdiff
remote: handle rename of remote without fetch refspec
authorJeff King <peff@peff.net>
Thu, 22 Sep 2022 05:33:29 +0000 (01:33 -0400)
committerJunio C Hamano <gitster@pobox.com>
Thu, 22 Sep 2022 19:59:52 +0000 (12:59 -0700)
We return an error when trying to rename a remote that has no fetch
refspec:

  $ git config --unset-all remote.origin.fetch
  $ git remote rename origin foo
  fatal: could not unset 'remote.foo.fetch'

To make things even more confusing, we actually _do_ complete the config
modification, via git_config_rename_section(). After that we try to
rewrite the fetch refspec (to say refs/remotes/foo instead of origin).
But our call to git_config_set_multivar() to remove the existing entries
fails, since there aren't any, and it calls die().

We could fix this by using the "gently" form of the config call, and
checking the error code. But there is an even simpler fix: if we know
that there are no refspecs to rewrite, then we can skip that part
entirely.

Reported-by: John A. Leuenhagen <john@zlima12.com>
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin/remote.c
t/t5505-remote.sh

index a3a0c27d7a09da9f5df1f258d3c21fe426690ea0..2d6b330ea97c57f2993b6fbb5682ee8bf2e3b5cd 100644 (file)
@@ -726,29 +726,31 @@ static int mv(int argc, const char **argv)
                return error(_("Could not rename config section '%s' to '%s'"),
                                buf.buf, buf2.buf);
 
-       strbuf_reset(&buf);
-       strbuf_addf(&buf, "remote.%s.fetch", rename.new_name);
-       git_config_set_multivar(buf.buf, NULL, NULL, CONFIG_FLAGS_MULTI_REPLACE);
-       strbuf_addf(&old_remote_context, ":refs/remotes/%s/", rename.old_name);
-       for (i = 0; i < oldremote->fetch.raw_nr; i++) {
-               char *ptr;
-
-               strbuf_reset(&buf2);
-               strbuf_addstr(&buf2, oldremote->fetch.raw[i]);
-               ptr = strstr(buf2.buf, old_remote_context.buf);
-               if (ptr) {
-                       refspec_updated = 1;
-                       strbuf_splice(&buf2,
-                                     ptr-buf2.buf + strlen(":refs/remotes/"),
-                                     strlen(rename.old_name), rename.new_name,
-                                     strlen(rename.new_name));
-               } else
-                       warning(_("Not updating non-default fetch refspec\n"
-                                 "\t%s\n"
-                                 "\tPlease update the configuration manually if necessary."),
-                               buf2.buf);
-
-               git_config_set_multivar(buf.buf, buf2.buf, "^$", 0);
+       if (oldremote->fetch.raw_nr) {
+               strbuf_reset(&buf);
+               strbuf_addf(&buf, "remote.%s.fetch", rename.new_name);
+               git_config_set_multivar(buf.buf, NULL, NULL, CONFIG_FLAGS_MULTI_REPLACE);
+               strbuf_addf(&old_remote_context, ":refs/remotes/%s/", rename.old_name);
+               for (i = 0; i < oldremote->fetch.raw_nr; i++) {
+                       char *ptr;
+
+                       strbuf_reset(&buf2);
+                       strbuf_addstr(&buf2, oldremote->fetch.raw[i]);
+                       ptr = strstr(buf2.buf, old_remote_context.buf);
+                       if (ptr) {
+                               refspec_updated = 1;
+                               strbuf_splice(&buf2,
+                                             ptr-buf2.buf + strlen(":refs/remotes/"),
+                                             strlen(rename.old_name), rename.new_name,
+                                             strlen(rename.new_name));
+                       } else
+                               warning(_("Not updating non-default fetch refspec\n"
+                                         "\t%s\n"
+                                         "\tPlease update the configuration manually if necessary."),
+                                       buf2.buf);
+
+                       git_config_set_multivar(buf.buf, buf2.buf, "^$", 0);
+               }
        }
 
        read_branches();
index fff14e13ed43b385f1ce7c0d01c0bea815c954d5..404529717922968eb91136558c7033389b351b8b 100755 (executable)
@@ -836,6 +836,17 @@ test_expect_success 'rename a remote renames repo remote.pushDefault but keeps g
        )
 '
 
+test_expect_success 'rename handles remote without fetch refspec' '
+       git clone --bare one no-refspec.git &&
+       # confirm assumption that bare clone does not create refspec
+       test_expect_code 5 \
+               git -C no-refspec.git config --unset-all remote.origin.fetch &&
+       git -C no-refspec.git config remote.origin.url >expect &&
+       git -C no-refspec.git remote rename origin foo &&
+       git -C no-refspec.git config remote.foo.url >actual &&
+       test_cmp expect actual
+'
+
 test_expect_success 'rename does not update a non-default fetch refspec' '
        git clone one four.one &&
        (