]> git.ipfire.org Git - thirdparty/git.git/commitdiff
credential: use the last matching username in the config
authorbrian m. carlson <bk2204@github.com>
Thu, 20 Feb 2020 02:24:12 +0000 (02:24 +0000)
committerJunio C Hamano <gitster@pobox.com>
Thu, 20 Feb 2020 21:05:43 +0000 (13:05 -0800)
Everywhere else in the codebase, we use the rule that the last matching
configuration option is the one that takes effect.  This is helpful
because it allows more specific configuration settings (e.g., per-repo
configuration) to override less specific settings (e.g., per-user
configuration).

However, in the credential code, we didn't honor this setting, and
instead picked the first setting we had, and stuck with it.  This was
likely to ensure we picked the value from the URL, which we want to
honor over the configuration.

It's possible to do both, though, so let's check if the value is the one
we've gotten over our protocol connection, which if present will have
come from the URL, and keep it if so.  Otherwise, let's overwrite the
value with the latest version we've got from the configuration, so we
keep the last configuration value.

Signed-off-by: brian m. carlson <bk2204@github.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
credential.c
credential.h
t/t0300-credentials.sh

index 62be651b03b55ee4d478706e51ea8606b10739f0..5701e3279202ad4d7ebec0e6db5da04ff23b7623 100644 (file)
@@ -71,8 +71,10 @@ static int credential_config_callback(const char *var, const char *value,
                else
                        string_list_clear(&c->helpers, 0);
        } else if (!strcmp(key, "username")) {
-               if (!c->username)
+               if (!c->username_from_proto) {
+                       free(c->username);
                        c->username = xstrdup(value);
+               }
        }
        else if (!strcmp(key, "usehttppath"))
                c->use_http_path = git_config_bool(var, value);
@@ -163,6 +165,7 @@ int credential_read(struct credential *c, FILE *fp)
                if (!strcmp(key, "username")) {
                        free(c->username);
                        c->username = xstrdup(value);
+                       c->username_from_proto = 1;
                } else if (!strcmp(key, "password")) {
                        free(c->password);
                        c->password = xstrdup(value);
@@ -349,10 +352,14 @@ void credential_from_url(struct credential *c, const char *url)
        else if (!colon || at <= colon) {
                /* Case (2) */
                c->username = url_decode_mem(cp, at - cp);
+               if (c->username && *c->username)
+                       c->username_from_proto = 1;
                host = at + 1;
        } else {
                /* Case (3) */
                c->username = url_decode_mem(cp, colon - cp);
+               if (c->username && *c->username)
+                       c->username_from_proto = 1;
                c->password = url_decode_mem(colon + 1, at - (colon + 1));
                host = at + 1;
        }
index 5772d5057727ac277fdcd9bfbe2b2b974f8f960a..fffed4d9348d1b3b48a68244d5c8c62b07fced10 100644 (file)
@@ -208,7 +208,8 @@ struct credential {
        unsigned approved:1,
                 configured:1,
                 quit:1,
-                use_http_path:1;
+                use_http_path:1,
+                username_from_proto:1;
 
        char *username;
        char *password;
index 4593a0cd3d5d5db13450eaac637bed9afb425006..8f8759905663369908c3ee0721831c266806cfeb 100755 (executable)
@@ -344,7 +344,7 @@ test_expect_success 'honors username from URL over helper (components)' '
        EOF
 '
 
-test_expect_failure 'last matching username wins' '
+test_expect_success 'last matching username wins' '
        test_config credential.https://example.com/path.git.username bob &&
        test_config credential.https://example.com.username alice &&
        test_config credential.https://example.com.helper "verbatim \"\" bar" &&