Code

credential-cache: ignore "connection refused" errors
[git.git] / credential.c
index c349b9aac3999ba4dbce16fd82b582cd60d61761..a17eafea582638e3d77f2e37b9d82fe5069798c0 100644 (file)
@@ -22,6 +22,79 @@ void credential_clear(struct credential *c)
        credential_init(c);
 }
 
+int credential_match(const struct credential *want,
+                    const struct credential *have)
+{
+#define CHECK(x) (!want->x || (have->x && !strcmp(want->x, have->x)))
+       return CHECK(protocol) &&
+              CHECK(host) &&
+              CHECK(path) &&
+              CHECK(username);
+#undef CHECK
+}
+
+static int credential_config_callback(const char *var, const char *value,
+                                     void *data)
+{
+       struct credential *c = data;
+       const char *key, *dot;
+
+       key = skip_prefix(var, "credential.");
+       if (!key)
+               return 0;
+
+       if (!value)
+               return config_error_nonbool(var);
+
+       dot = strrchr(key, '.');
+       if (dot) {
+               struct credential want = CREDENTIAL_INIT;
+               char *url = xmemdupz(key, dot - key);
+               int matched;
+
+               credential_from_url(&want, url);
+               matched = credential_match(&want, c);
+
+               credential_clear(&want);
+               free(url);
+
+               if (!matched)
+                       return 0;
+               key = dot + 1;
+       }
+
+       if (!strcmp(key, "helper"))
+               string_list_append(&c->helpers, value);
+       else if (!strcmp(key, "username")) {
+               if (!c->username)
+                       c->username = xstrdup(value);
+       }
+       else if (!strcmp(key, "usehttppath"))
+               c->use_http_path = git_config_bool(var, value);
+
+       return 0;
+}
+
+static int proto_is_http(const char *s)
+{
+       if (!s)
+               return 0;
+       return !strcmp(s, "https") || !strcmp(s, "http");
+}
+
+static void credential_apply_config(struct credential *c)
+{
+       if (c->configured)
+               return;
+       git_config(credential_config_callback, c);
+       c->configured = 1;
+
+       if (!c->use_http_path && proto_is_http(c->protocol)) {
+               free(c->path);
+               c->path = NULL;
+       }
+}
+
 static void credential_describe(struct credential *c, struct strbuf *out)
 {
        if (!c->protocol)
@@ -195,6 +268,8 @@ void credential_fill(struct credential *c)
        if (c->username && c->password)
                return;
 
+       credential_apply_config(c);
+
        for (i = 0; i < c->helpers.nr; i++) {
                credential_do(c, c->helpers.items[i].string, "get");
                if (c->username && c->password)
@@ -215,6 +290,8 @@ void credential_approve(struct credential *c)
        if (!c->username || !c->password)
                return;
 
+       credential_apply_config(c);
+
        for (i = 0; i < c->helpers.nr; i++)
                credential_do(c, c->helpers.items[i].string, "store");
        c->approved = 1;
@@ -224,6 +301,8 @@ void credential_reject(struct credential *c)
 {
        int i;
 
+       credential_apply_config(c);
+
        for (i = 0; i < c->helpers.nr; i++)
                credential_do(c, c->helpers.items[i].string, "erase");