@matheusbsbs / matheus-bagliano / commits / 82eb249853
Fork 0

credential: use the last matching username in the config

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>

brian m. carlson committed Feb 20, 2020 at 02:24 UTC 82eb249853868582d8ba65e3afc5a7dcaeb620ea
3 files changed +11 -3
credential.c
+8 -1
@@ -71,8 +71,10 @@ static int credential_config_callback(const char *var, const char *value,
71 else
72 string_list_clear(&c->helpers, 0);
73 } else if (!strcmp(key, "username")) {
74 - if (!c->username)
74 + if (!c->username_from_proto) {
75 + free(c->username);
76 c->username = xstrdup(value);
77 + }
78 }
79 else if (!strcmp(key, "usehttppath"))
80 c->use_http_path = git_config_bool(var, value);
@@ -163,6 +165,7 @@ int credential_read(struct credential *c, FILE *fp)
165 if (!strcmp(key, "username")) {
166 free(c->username);
167 c->username = xstrdup(value);
168 + c->username_from_proto = 1;
169 } else if (!strcmp(key, "password")) {
170 free(c->password);
171 c->password = xstrdup(value);
@@ -349,10 +352,14 @@ void credential_from_url(struct credential *c, const char *url)
352 else if (!colon || at <= colon) {
353 /* Case (2) */
354 c->username = url_decode_mem(cp, at - cp);
355 + if (c->username && *c->username)
356 + c->username_from_proto = 1;
357 host = at + 1;
358 } else {
359 /* Case (3) */
360 c->username = url_decode_mem(cp, colon - cp);
361 + if (c->username && *c->username)
362 + c->username_from_proto = 1;
363 c->password = url_decode_mem(colon + 1, at - (colon + 1));
364 host = at + 1;
365 }
credential.h
+2 -1
@@ -208,7 +208,8 @@ struct credential {
208 unsigned approved:1,
209 configured:1,
210 quit:1,
211 - use_http_path:1;
211 + use_http_path:1,
212 + username_from_proto:1;
213
214 char *username;
215 char *password;
t/t0300-credentials.sh
+1 -1
@@ -344,7 +344,7 @@ test_expect_success 'honors username from URL over helper (components)' '
344 EOF
345 '
346
347 -test_expect_failure 'last matching username wins' '
347 +test_expect_success 'last matching username wins' '
348 test_config credential.https://example.com/path.git.username bob &&
349 test_config credential.https://example.com.username alice &&
350 test_config credential.https://example.com.helper "verbatim \"\" bar" &&