Merge branch 'tg/git-remote'
authorJunio C Hamano <gitster@pobox.com>
Fri, 26 Feb 2016 21:37:09 +0000 (13:37 -0800)
committerJunio C Hamano <gitster@pobox.com>
Fri, 26 Feb 2016 21:37:09 +0000 (13:37 -0800)
The internal API to interact with "remote.*" configuration
variables has been streamlined.

* tg/git-remote:
remote: use remote_is_configured() for add and rename
remote: actually check if remote exits
remote: simplify remote_is_configured()
remote: use parse_config_key

1  2 
builtin/fetch.c
remote.c
t/t5505-remote.sh
diff --combined builtin/fetch.c
index 55919a9e4fb8e2fd538b6c111bfdacf83acf62ed,81218300d8cedb539eb221688d6bf7fc398cac3c..48c45ea5e3b77d5e7af339128971f294e6ea9a20
@@@ -38,7 -38,6 +38,7 @@@ static int all, append, dry_run, force
  static int progress = -1, recurse_submodules = RECURSE_SUBMODULES_DEFAULT;
  static int tags = TAGS_DEFAULT, unshallow, update_shallow;
  static int max_children = 1;
 +static enum transport_family family;
  static const char *depth;
  static const char *upload_pack;
  static struct strbuf default_rla = STRBUF_INIT;
@@@ -128,10 -127,6 +128,10 @@@ static struct option builtin_fetch_opti
                 N_("accept refs that update .git/shallow")),
        { OPTION_CALLBACK, 0, "refmap", NULL, N_("refmap"),
          N_("specify fetch refmap"), PARSE_OPT_NONEG, parse_refmap_arg },
 +      OPT_SET_INT('4', "ipv4", &family, N_("use IPv4 addresses only"),
 +                      TRANSPORT_FAMILY_IPV4),
 +      OPT_SET_INT('6', "ipv6", &family, N_("use IPv6 addresses only"),
 +                      TRANSPORT_FAMILY_IPV6),
        OPT_END()
  };
  
@@@ -869,7 -864,6 +869,7 @@@ static struct transport *prepare_transp
        struct transport *transport;
        transport = transport_get(remote, NULL);
        transport_set_verbosity(transport, verbosity, progress);
 +      transport->family = family;
        if (upload_pack)
                set_option(transport, TRANS_OPT_UPLOADPACK, upload_pack);
        if (keep)
@@@ -1022,10 -1016,9 +1022,9 @@@ static int add_remote_or_group(const ch
  
        git_config(get_remote_group, &g);
        if (list->nr == prev_nr) {
-               struct remote *remote;
-               if (!remote_is_configured(name))
+               struct remote *remote = remote_get(name);
+               if (!remote_is_configured(remote))
                        return 0;
-               remote = remote_get(name);
                string_list_append(list, remote->name);
        }
        return 1;
diff --combined remote.c
index 02e698a5e05a02f8905ec511851eea15e86d746f,e4a647cb7bda558854a682e523a50002c345e901..f0016811059b60d6d1a683b8d94874e8599329f6
+++ b/remote.c
@@@ -318,93 -318,88 +318,88 @@@ static void read_branches_file(struct r
  static int handle_config(const char *key, const char *value, void *cb)
  {
        const char *name;
+       int namelen;
        const char *subkey;
        struct remote *remote;
        struct branch *branch;
-       if (starts_with(key, "branch.")) {
-               name = key + 7;
-               subkey = strrchr(name, '.');
-               if (!subkey)
+       if (parse_config_key(key, "branch", &name, &namelen, &subkey) >= 0) {
+               if (!name)
                        return 0;
-               branch = make_branch(name, subkey - name);
-               if (!strcmp(subkey, ".remote")) {
+               branch = make_branch(name, namelen);
+               if (!strcmp(subkey, "remote")) {
                        return git_config_string(&branch->remote_name, key, value);
-               } else if (!strcmp(subkey, ".pushremote")) {
+               } else if (!strcmp(subkey, "pushremote")) {
                        return git_config_string(&branch->pushremote_name, key, value);
-               } else if (!strcmp(subkey, ".merge")) {
+               } else if (!strcmp(subkey, "merge")) {
                        if (!value)
                                return config_error_nonbool(key);
                        add_merge(branch, xstrdup(value));
                }
                return 0;
        }
-       if (starts_with(key, "url.")) {
+       if (parse_config_key(key, "url", &name, &namelen, &subkey) >= 0) {
                struct rewrite *rewrite;
-               name = key + 4;
-               subkey = strrchr(name, '.');
-               if (!subkey)
+               if (!name)
                        return 0;
-               if (!strcmp(subkey, ".insteadof")) {
-                       rewrite = make_rewrite(&rewrites, name, subkey - name);
+               if (!strcmp(subkey, "insteadof")) {
+                       rewrite = make_rewrite(&rewrites, name, namelen);
                        if (!value)
                                return config_error_nonbool(key);
                        add_instead_of(rewrite, xstrdup(value));
-               } else if (!strcmp(subkey, ".pushinsteadof")) {
-                       rewrite = make_rewrite(&rewrites_push, name, subkey - name);
+               } else if (!strcmp(subkey, "pushinsteadof")) {
+                       rewrite = make_rewrite(&rewrites_push, name, namelen);
                        if (!value)
                                return config_error_nonbool(key);
                        add_instead_of(rewrite, xstrdup(value));
                }
        }
  
-       if (!starts_with(key,  "remote."))
+       if (parse_config_key(key, "remote", &name, &namelen, &subkey) < 0)
                return 0;
-       name = key + 7;
  
        /* Handle remote.* variables */
-       if (!strcmp(name, "pushdefault"))
+       if (!name && !strcmp(subkey, "pushdefault"))
                return git_config_string(&pushremote_name, key, value);
  
+       if (!name)
+               return 0;
        /* Handle remote.<name>.* variables */
        if (*name == '/') {
                warning("Config remote shorthand cannot begin with '/': %s",
                        name);
                return 0;
        }
-       subkey = strrchr(name, '.');
-       if (!subkey)
-               return 0;
-       remote = make_remote(name, subkey - name);
+       remote = make_remote(name, namelen);
        remote->origin = REMOTE_CONFIG;
-       if (!strcmp(subkey, ".mirror"))
+       if (!strcmp(subkey, "mirror"))
                remote->mirror = git_config_bool(key, value);
-       else if (!strcmp(subkey, ".skipdefaultupdate"))
+       else if (!strcmp(subkey, "skipdefaultupdate"))
                remote->skip_default_update = git_config_bool(key, value);
-       else if (!strcmp(subkey, ".skipfetchall"))
+       else if (!strcmp(subkey, "skipfetchall"))
                remote->skip_default_update = git_config_bool(key, value);
-       else if (!strcmp(subkey, ".prune"))
+       else if (!strcmp(subkey, "prune"))
                remote->prune = git_config_bool(key, value);
-       else if (!strcmp(subkey, ".url")) {
+       else if (!strcmp(subkey, "url")) {
                const char *v;
                if (git_config_string(&v, key, value))
                        return -1;
                add_url(remote, v);
-       } else if (!strcmp(subkey, ".pushurl")) {
+       } else if (!strcmp(subkey, "pushurl")) {
                const char *v;
                if (git_config_string(&v, key, value))
                        return -1;
                add_pushurl(remote, v);
-       } else if (!strcmp(subkey, ".push")) {
+       } else if (!strcmp(subkey, "push")) {
                const char *v;
                if (git_config_string(&v, key, value))
                        return -1;
                add_push_refspec(remote, v);
-       } else if (!strcmp(subkey, ".fetch")) {
+       } else if (!strcmp(subkey, "fetch")) {
                const char *v;
                if (git_config_string(&v, key, value))
                        return -1;
                add_fetch_refspec(remote, v);
-       } else if (!strcmp(subkey, ".receivepack")) {
+       } else if (!strcmp(subkey, "receivepack")) {
                const char *v;
                if (git_config_string(&v, key, value))
                        return -1;
                        remote->receivepack = v;
                else
                        error("more than one receivepack given, using the first");
-       } else if (!strcmp(subkey, ".uploadpack")) {
+       } else if (!strcmp(subkey, "uploadpack")) {
                const char *v;
                if (git_config_string(&v, key, value))
                        return -1;
                        remote->uploadpack = v;
                else
                        error("more than one uploadpack given, using the first");
-       } else if (!strcmp(subkey, ".tagopt")) {
+       } else if (!strcmp(subkey, "tagopt")) {
                if (!strcmp(value, "--no-tags"))
                        remote->fetch_tags = -1;
                else if (!strcmp(value, "--tags"))
                        remote->fetch_tags = 2;
-       } else if (!strcmp(subkey, ".proxy")) {
+       } else if (!strcmp(subkey, "proxy")) {
                return git_config_string((const char **)&remote->http_proxy,
                                         key, value);
-       } else if (!strcmp(subkey, ".proxyauthmethod")) {
+       } else if (!strcmp(subkey, "proxyauthmethod")) {
                return git_config_string((const char **)&remote->http_proxy_authmethod,
                                         key, value);
-       } else if (!strcmp(subkey, ".vcs")) {
+       } else if (!strcmp(subkey, "vcs")) {
                return git_config_string(&remote->foreign_vcs, key, value);
        }
        return 0;
@@@ -718,18 -713,9 +713,9 @@@ struct remote *pushremote_get(const cha
        return remote_get_1(name, pushremote_for_branch);
  }
  
- int remote_is_configured(const char *name)
+ int remote_is_configured(struct remote *remote)
  {
-       struct remotes_hash_key lookup;
-       struct hashmap_entry lookup_entry;
-       read_config();
-       init_remotes_hash();
-       lookup.str = name;
-       lookup.len = strlen(name);
-       hashmap_entry_init(&lookup_entry, memhash(name, lookup.len));
-       return hashmap_get(&remotes_hash, &lookup_entry, &lookup) != NULL;
+       return remote && remote->origin;
  }
  
  int for_each_remote(each_remote_fn fn, void *priv)
@@@ -1548,8 -1534,11 +1534,8 @@@ void set_ref_status_for_push(struct re
                }
  
                /*
 -               * Bypass the usual "must fast-forward" check but
 -               * replace it with a weaker "the old value must be
 -               * this value we observed".  If the remote ref has
 -               * moved and is now different from what we expect,
 -               * reject any push.
 +               * If the remote ref has moved and is now different
 +               * from what we expect, reject any push.
                 *
                 * It also is an error if the user told us to check
                 * with the remote-tracking branch to find the value
                        if (ref->expect_old_no_trackback ||
                            oidcmp(&ref->old_oid, &ref->old_oid_expect))
                                reject_reason = REF_STATUS_REJECT_STALE;
 +                      else
 +                              /* If the ref isn't stale then force the update. */
 +                              force_ref_update = 1;
                }
  
                /*
 -               * The usual "must fast-forward" rules.
 +               * If the update isn't already rejected then check
 +               * the usual "must fast-forward" rules.
                 *
                 * Decide whether an individual refspec A:B can be
                 * pushed.  The push will succeed if any of the
                 *     passing the --force argument
                 */
  
 -              else if (!ref->deletion && !is_null_oid(&ref->old_oid)) {
 +              if (!reject_reason && !ref->deletion && !is_null_oid(&ref->old_oid)) {
                        if (starts_with(ref->name, "refs/tags/"))
                                reject_reason = REF_STATUS_REJECT_ALREADY_EXISTS;
                        else if (!has_object_file(&ref->old_oid))
diff --combined t/t5505-remote.sh
index 0dcc752076a9e42b0cff982d7b0f42c63f85dee2,94079a0e63c29fc0366dfa2abf39015c41240ee1..949725e9bcc5b4d6358ed28ca5675b92f9b7c7fa
@@@ -51,11 -51,6 +51,11 @@@ test_expect_success setup 
        git clone one test
  '
  
 +test_expect_success 'add remote whose URL agrees with url.<...>.insteadOf' '
 +      test_config url.git@host.com:team/repo.git.insteadOf myremote &&
 +      git remote add myremote git@host.com:team/repo.git
 +'
 +
  test_expect_success C_LOCALE_OUTPUT 'remote information for the origin' '
        (
                cd test &&
@@@ -144,6 -139,39 +144,39 @@@ test_expect_success 'remove remote prot
        )
  '
  
+ test_expect_success 'remove errors out early when deleting non-existent branch' '
+       (
+               cd test &&
+               echo "fatal: No such remote: foo" >expect &&
+               test_must_fail git remote rm foo 2>actual &&
+               test_i18ncmp expect actual
+       )
+ '
+ test_expect_success 'rename errors out early when deleting non-existent branch' '
+       (
+               cd test &&
+               echo "fatal: No such remote: foo" >expect &&
+               test_must_fail git remote rename foo bar 2>actual &&
+               test_i18ncmp expect actual
+       )
+ '
+ test_expect_success 'add existing foreign_vcs remote' '
+       test_config remote.foo.vcs bar &&
+       echo "fatal: remote foo already exists." >expect &&
+       test_must_fail git remote add foo bar 2>actual &&
+       test_i18ncmp expect actual
+ '
+ test_expect_success 'add existing foreign_vcs remote' '
+       test_config remote.foo.vcs bar &&
+       test_config remote.bar.vcs bar &&
+       echo "fatal: remote bar already exists." >expect &&
+       test_must_fail git remote rename foo bar 2>actual &&
+       test_i18ncmp expect actual
+ '
  cat >test/expect <<EOF
  * remote origin
    Fetch URL: $(pwd)/one