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>
diff --git a/credential.c b/credential.c
index 62be651..5701e32 100644
--- a/credential.c
+++ b/credential.c
@@ -71,8 +71,10 @@
 		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 @@
 		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 @@
 	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;
 	}
diff --git a/credential.h b/credential.h
index 5772d50..fffed4d 100644
--- a/credential.h
+++ b/credential.h
@@ -208,7 +208,8 @@
 	unsigned approved:1,
 		 configured:1,
 		 quit:1,
-		 use_http_path:1;
+		 use_http_path:1,
+		 username_from_proto:1;
 
 	char *username;
 	char *password;
diff --git a/t/t0300-credentials.sh b/t/t0300-credentials.sh
index 4593a0c..8f87599 100755
--- a/t/t0300-credentials.sh
+++ b/t/t0300-credentials.sh
@@ -344,7 +344,7 @@
 	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" &&