Merge branch 'js/remote-rename-with-half-configured-remote'
authorJunio C Hamano <gitster@pobox.com>
Tue, 31 Jan 2017 21:14:59 +0000 (13:14 -0800)
committerJunio C Hamano <gitster@pobox.com>
Tue, 31 Jan 2017 21:14:59 +0000 (13:14 -0800)
With anticipatory tweaking for remotes defined in ~/.gitconfig
(e.g. "remote.origin.prune" set to true, even though there may or
may not actually be "origin" remote defined in a particular Git
repository), "git remote rename" and other commands misinterpreted
and behaved as if such a non-existing remote actually existed.

* js/remote-rename-with-half-configured-remote:
remote rename: more carefully determine whether a remote is configured
remote rename: demonstrate a bogus "remote exists" bug

builtin/fetch.c
builtin/remote.c
remote.c
remote.h
t/t5505-remote.sh
index f1570e346434e8695e80ba568c28b1363b2c0cb5..b5ad09d0460cc7a51f35a56a4304e6a1fb26d26e 100644 (file)
@@ -1177,7 +1177,7 @@ static int add_remote_or_group(const char *name, struct string_list *list)
        git_config(get_remote_group, &g);
        if (list->nr == prev_nr) {
                struct remote *remote = remote_get(name);
-               if (!remote_is_configured(remote))
+               if (!remote_is_configured(remote, 0))
                        return 0;
                string_list_append(list, remote->name);
        }
index e52cf3925b2388008221de6f7cbedeecd6cdd010..5339ed6ad17bb0c83e05d3e60d654c4f0632ee50 100644 (file)
@@ -186,7 +186,7 @@ static int add(int argc, const char **argv)
        url = argv[1];
 
        remote = remote_get(name);
-       if (remote_is_configured(remote))
+       if (remote_is_configured(remote, 1))
                die(_("remote %s already exists."), name);
 
        strbuf_addf(&buf2, "refs/heads/test:refs/remotes/%s/test", name);
@@ -618,14 +618,14 @@ static int mv(int argc, const char **argv)
        rename.remote_branches = &remote_branches;
 
        oldremote = remote_get(rename.old);
-       if (!remote_is_configured(oldremote))
+       if (!remote_is_configured(oldremote, 1))
                die(_("No such remote: %s"), rename.old);
 
        if (!strcmp(rename.old, rename.new) && oldremote->origin != REMOTE_CONFIG)
                return migrate_file(oldremote);
 
        newremote = remote_get(rename.new);
-       if (remote_is_configured(newremote))
+       if (remote_is_configured(newremote, 1))
                die(_("remote %s already exists."), rename.new);
 
        strbuf_addf(&buf, "refs/heads/test:refs/remotes/%s/test", rename.new);
@@ -753,7 +753,7 @@ static int rm(int argc, const char **argv)
                usage_with_options(builtin_remote_rm_usage, options);
 
        remote = remote_get(argv[1]);
-       if (!remote_is_configured(remote))
+       if (!remote_is_configured(remote, 1))
                die(_("No such remote: %s"), argv[1]);
 
        known_remotes.to_delete = remote;
@@ -1415,7 +1415,7 @@ static int set_remote_branches(const char *remotename, const char **branches,
        strbuf_addf(&key, "remote.%s.fetch", remotename);
 
        remote = remote_get(remotename);
-       if (!remote_is_configured(remote))
+       if (!remote_is_configured(remote, 1))
                die(_("No such remote '%s'"), remotename);
 
        if (!add_mode && remove_all_fetch_refspecs(remotename, key.buf)) {
@@ -1469,7 +1469,7 @@ static int get_url(int argc, const char **argv)
        remotename = argv[0];
 
        remote = remote_get(remotename);
-       if (!remote_is_configured(remote))
+       if (!remote_is_configured(remote, 1))
                die(_("No such remote '%s'"), remotename);
 
        url_nr = 0;
@@ -1537,7 +1537,7 @@ static int set_url(int argc, const char **argv)
                oldurl = newurl;
 
        remote = remote_get(remotename);
-       if (!remote_is_configured(remote))
+       if (!remote_is_configured(remote, 1))
                die(_("No such remote '%s'"), remotename);
 
        if (push_mode) {
index d5eaec73742e74738c522cdc36ba9bf811b158b2..bf1bf2309128bf886eac16959b8162b9990c98d7 100644 (file)
--- a/remote.c
+++ b/remote.c
@@ -255,6 +255,7 @@ static void read_remotes_file(struct remote *remote)
 
        if (!f)
                return;
+       remote->configured_in_repo = 1;
        remote->origin = REMOTE_REMOTES;
        while (strbuf_getline(&buf, f) != EOF) {
                const char *v;
@@ -289,6 +290,7 @@ static void read_branches_file(struct remote *remote)
                return;
        }
 
+       remote->configured_in_repo = 1;
        remote->origin = REMOTE_BRANCHES;
 
        /*
@@ -371,6 +373,8 @@ static int handle_config(const char *key, const char *value, void *cb)
        }
        remote = make_remote(name, namelen);
        remote->origin = REMOTE_CONFIG;
+       if (current_config_scope() == CONFIG_SCOPE_REPO)
+               remote->configured_in_repo = 1;
        if (!strcmp(subkey, "mirror"))
                remote->mirror = git_config_bool(key, value);
        else if (!strcmp(subkey, "skipdefaultupdate"))
@@ -714,9 +718,13 @@ struct remote *pushremote_get(const char *name)
        return remote_get_1(name, pushremote_for_branch);
 }
 
-int remote_is_configured(struct remote *remote)
+int remote_is_configured(struct remote *remote, int in_repo)
 {
-       return remote && remote->origin;
+       if (!remote)
+               return 0;
+       if (in_repo)
+               return remote->configured_in_repo;
+       return !!remote->origin;
 }
 
 int for_each_remote(each_remote_fn fn, void *priv)
index 924881169d9f6c5b9b09e2434d964f62e0e28d09..a5bbbe0ef965c5e62be50e8ee0c03794e393cc8c 100644 (file)
--- a/remote.h
+++ b/remote.h
@@ -15,7 +15,7 @@ struct remote {
        struct hashmap_entry ent;  /* must be first */
 
        const char *name;
-       int origin;
+       int origin, configured_in_repo;
 
        const char *foreign_vcs;
 
@@ -60,7 +60,7 @@ struct remote {
 
 struct remote *remote_get(const char *name);
 struct remote *pushremote_get(const char *name);
-int remote_is_configured(struct remote *remote);
+int remote_is_configured(struct remote *remote, int in_repo);
 
 typedef int each_remote_fn(struct remote *remote, void *priv);
 int for_each_remote(each_remote_fn fn, void *priv);
index 8198d8eb05c5366c7d61a12351c333902a2265b6..ba46e86de0a7285bf88ff5fe05e378c8bfd256f9 100755 (executable)
@@ -764,6 +764,13 @@ test_expect_success 'rename a remote with name prefix of other remote' '
        )
 '
 
+test_expect_success 'rename succeeds with existing remote.<target>.prune' '
+       git clone one four.four &&
+       test_when_finished git config --global --unset remote.upstream.prune &&
+       git config --global remote.upstream.prune true &&
+       git -C four.four remote rename origin upstream
+'
+
 cat >remotes_origin <<EOF
 URL: $(pwd)/one
 Push: refs/heads/master:refs/heads/upstream