git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 3/3] credential: allow wildcard patterns when matching config

From
brian m. carlson <sandals@crustytoothpaste.net>
Date
Feb 14, 2020, 22:59 UTC
Message-ID
<20200214225929.541306-4-sandals@crustytoothpaste.net>
In-Reply-To
<20200214225929.541306-1-sandals@crustytoothpaste.net>
From: brian m. carlson <bk2204@github.com>

In some cases, a user will want to use a specific credential helper for a wildcard pattern, such as https://*.corp.example.com. Use the urlmatch code to match a pattern for a URL to allow this behavior.

Since we are handling URLs using urlmatch, remove the custom code to match URLs, since it is no longer needed.

Signed-off-by: brian m. carlson <bk2204@github.com>
---
 Documentation/gitcredentials.txt |  4 +++-
 credential.c                     | 41 +++++++++++++++++---------------
 t/t0300-credentials.sh           | 20 ++++++++++++++++
 3 files changed, 45 insertions(+), 20 deletions(-)
diff --git a/Documentation/gitcredentials.txt b/Documentation/gitcredentials.txt
index ea759fdee5..12cb032352 100644
--- a/Documentation/gitcredentials.txt
+++ b/Documentation/gitcredentials.txt
@@ -131,7 +131,9 @@ context would not match:
 because the hostnames differ. Nor would it match `foo.example.com`; Git
 compares hostnames exactly, without considering whether two hosts are part of
 the same domain. Likewise, a config entry for `http://example.com` would not
-match: Git compares the protocols exactly.
+match: Git compares the protocols exactly.  However, you may use wildcards in
+the domain name and other pattern matching techniques as with the `http.<url>.*`
+options.
 
 If the "pattern" URL does include a path component, then this too must match
 exactly: the context `https://example.com/bar/baz.git` will match a config
diff --git a/credential.c b/credential.c
index 62be651b03..08904e247f 100644
--- a/credential.c
+++ b/credential.c
@@ -6,6 +6,7 @@
 #include "url.h"
 #include "prompt.h"
 #include "sigchain.h"
+#include "urlmatch.h"
 
 void credential_init(struct credential *c)
 {
@@ -40,7 +41,7 @@ static int credential_config_callback(const char *var, const char *value,
 				      void *data)
 {
 	struct credential *c = data;
-	const char *key, *dot;
+	const char *key;
 
 	if (!skip_prefix(var, "credential.", &key))
 		return 0;
@@ -48,23 +49,6 @@ static int credential_config_callback(const char *var, const char *value,
 	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")) {
 		if (*value)
 			string_list_append(&c->helpers, value);
@@ -87,11 +71,30 @@ static int proto_is_http(const char *s)
 	return !strcmp(s, "https") || !strcmp(s, "http");
 }
 
+static void credential_describe(struct credential *c, struct strbuf *out);
+
 static void credential_apply_config(struct credential *c)
 {
+	char *normalized_url;
+	struct urlmatch_config config = { STRING_LIST_INIT_DUP };
+	struct strbuf url = STRBUF_INIT;
+
 	if (c->configured)
 		return;
-	git_config(credential_config_callback, c);
+
+	config.section = "credential";
+	config.key = NULL;
+	config.collect_fn = credential_config_callback;
+	config.cascade_fn = git_default_config;
+	config.cb = c;
+
+	credential_describe(c, &url);
+	normalized_url = url_normalize(url.buf, &config.url);
+
+	git_config(urlmatch_config_entry, &config);
+	free(normalized_url);
+	strbuf_release(&url);
+
 	c->configured = 1;
 
 	if (!c->use_http_path && proto_is_http(c->protocol)) {
diff --git a/t/t0300-credentials.sh b/t/t0300-credentials.sh
index 82eaaea0f4..516b3268f9 100755
--- a/t/t0300-credentials.sh
+++ b/t/t0300-credentials.sh
@@ -289,6 +289,26 @@ test_expect_success 'http paths can be part of context' '
 	EOF
 '
 
+test_expect_success 'context uses urlmatch' '
+	test_config "credential.https://*.org.useHttpPath" true &&
+	check fill "verbatim foo bar" <<-\EOF
+	protocol=https
+	host=example.org
+	path=foo.git
+	--
+	protocol=https
+	host=example.org
+	path=foo.git
+	username=foo
+	password=bar
+	--
+	verbatim: get
+	verbatim: protocol=https
+	verbatim: host=example.org
+	verbatim: path=foo.git
+	EOF
+'
+
 test_expect_success 'helpers can abort the process' '
 	test_must_fail git \
 		-c credential.helper="!f() { echo quit=1; }; f" \
Previous: brian m. carlsonNext: Jeff King
Message 4 of 8 in “Wildcard matching for credentials”
  1. 0/3 Wildcard matching for credentialsbrian m. carlson, Feb 14, 2020
  2. 1/3 mailmap: add an additional email address for brian m. carlsonbrian m. carlson, Feb 14, 2020
  3. 2/3 t1300: add test for urlmatch with multiple wildcardsbrian m. carlson, Feb 14, 2020
  4. 3/3 credential: allow wildcard patterns when matching configbrian m. carlson, Feb 14, 2020
  5. Jeff KingFeb 16, 2020
  6. brian m. carlsonFeb 16, 2020
  7. Taylor BlauFeb 14, 2020
  8. brian m. carlsonFeb 15, 2020

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.