git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
From: Junio C Hamano <gitster@pobox.com>
To: git@vger.kernel.org
Cc: "Kyle J. McKay" <mackyle@gmail.com>, Jeff King <peff@peff.net>
Subject: [PATCH 4/3] url-match: generalize configuration collection logic
Date: Mon, 29 Jul 2013 19:03:43 -0700	[thread overview]
Message-ID: <7v7gg8ztvk.fsf_-_@alter.siamese.dyndns.org> (raw)
In-Reply-To: <1375138150-19520-1-git-send-email-gitster@pobox.com> (Junio C. Hamano's message of "Mon, 29 Jul 2013 15:49:07 -0700")

Instead of always collecting the found value in the strbuf in the
string list item for each found key, allow a set of callback
functions to be specified by the user to be called back at strategic
places.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---

 builtin/config.c | 117 +++++++++++++++++--------------------------------------
 url-match.c      |  75 +++++++++++++++++++++++++++++++++++
 url-match.h      |  22 +++++++++++
 3 files changed, 133 insertions(+), 81 deletions(-)

diff --git a/builtin/config.c b/builtin/config.c
index c1d32ae..173c18f 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -351,79 +351,17 @@ static int get_colorbool(int print)
 		return get_colorbool_found ? 0 : 1;
 }
 
-struct urlmatch_collect {
-	struct string_list vars;
-	struct url_info url;
-	const char *section;
-	const char *key;
-};
-
-struct urlmatch_item {
-	size_t max_matched_len;
-	char user_matched;
+struct urlmatch_config_item {
+	struct urlmatch_item match;
 	char value_is_null;
 	struct strbuf value;
 };
 
-static int urlmatch_collect(const char *var, const char *value, void *cb)
+static int urlmatch_collect_fn(const char *var, const char *value,
+			       void *cb, void *matched_cb)
 {
-	struct string_list_item *item;
-	struct urlmatch_collect *collect = cb;
-	struct urlmatch_item *matched;
-	struct url_info *url = &collect->url;
-	const char *key, *dot;
-	size_t matchlen = 0;
-	int usermatch = 0;
-
-	key = skip_prefix(var, collect->section);
-	if (!key || *(key++) != '.')
-		return 0; /* not interested */
-	dot = strrchr(key, '.');
-	if (dot) {
-		char *config_url, *norm_url;
-		struct url_info norm_info;
-		int matchlen;
-
-		config_url = xmemdupz(key, dot - key);
-		norm_url = url_normalize(config_url, &norm_info);
-		free(config_url);
-		if (!norm_url)
-			return 0;
-		matchlen = match_urls(url, &norm_info, &usermatch);
-		free(norm_url);
-		if (!matchlen)
-			return 0;
-		key = dot + 1;
-	}
-
-	if (collect->key && strcmp(key, collect->key))
-		return 0;
+	struct urlmatch_config_item *matched = matched_cb;
 
-	item = string_list_insert(&collect->vars, key);
-	if (!item->util) {
-		matched = xcalloc(1, sizeof(*matched));
-		item->util = matched;
-		strbuf_init(&matched->value, 0);
-	} else {
-		matched = item->util;
-		/*
-		 * Is our match shorter?  Is our match the same
-		 * length, and without user while the current
-		 * candidate is with user?  Then we cannot use it.
-		 */
-		if (matchlen < matched->max_matched_len ||
-		    ((matchlen == matched->max_matched_len) &&
-		     (!usermatch && matched->user_matched)))
-			return 0;
-		/*
-		 * Otherwise, release the old one and replace
-		 * with ours.
-		 */
-		strbuf_release(&matched->value);
-	}
-
-	matched->max_matched_len = matchlen;
-	matched->user_matched = usermatch;
 	if (value) {
 		strbuf_addstr(&matched->value, value);
 		matched->value_is_null = 0;
@@ -433,35 +371,52 @@ static int urlmatch_collect(const char *var, const char *value, void *cb)
 	return 0;
 }
 
+static void *urlmatch_alloc_fn(const char *var, const char *value, void *cb)
+{
+	return xcalloc(1, sizeof(struct urlmatch_config_item));
+}
+
+static void urlmatch_clear_fn(void *matched_cb)
+{
+	struct urlmatch_config_item *matched = matched_cb;
+	strbuf_init(&matched->value, 0);
+}
+
 static int get_urlmatch(const char *var, const char *url)
 {
 	const char *section_tail;
 	struct string_list_item *item;
-	struct urlmatch_collect collect = { STRING_LIST_INIT_DUP };
+	struct urlmatch_config config = { STRING_LIST_INIT_DUP };
+
+	config.fn = urlmatch_collect_fn;
+	config.cascade_fn = NULL;
+	config.item_alloc = urlmatch_alloc_fn;
+	config.item_clear = urlmatch_clear_fn;
+	config.cb = NULL;
 
-	if (!url_normalize(url, &collect.url))
-		die(collect.url.err);
+	if (!url_normalize(url, &config.url))
+		die(config.url.err);
 
 	section_tail = strchr(var, '.');
 	if (section_tail) {
-		collect.section = xmemdupz(var, section_tail - var);
-		collect.key = strrchr(var, '.') + 1;
+		config.section = xmemdupz(var, section_tail - var);
+		config.key = strrchr(var, '.') + 1;
 		show_keys = 0;
 	} else {
-		collect.section = var;
-		collect.key = NULL;
+		config.section = var;
+		config.key = NULL;
 		show_keys = 1;
 	}
 
-	git_config_with_options(urlmatch_collect, &collect,
+	git_config_with_options(urlmatch_config_entry, &config,
 				given_config_file, respect_includes);
 
-	for_each_string_list_item(item, &collect.vars) {
-		struct urlmatch_item *matched = item->util;
+	for_each_string_list_item(item, &config.vars) {
+		struct urlmatch_config_item *matched = item->util;
 		struct strbuf key = STRBUF_INIT;
 		struct strbuf buf = STRBUF_INIT;
 
-		strbuf_addstr(&key, collect.section);
+		strbuf_addstr(&key, config.section);
 		strbuf_addch(&key, '.');
 		strbuf_addstr(&key, item->string);
 		format_config(&buf, key.buf,
@@ -472,7 +427,7 @@ static int get_urlmatch(const char *var, const char *url)
 
 		strbuf_release(&matched->value);
 	}
-	string_list_clear(&collect.vars, 1);
+	string_list_clear(&config.vars, 1);
 
 	/*
 	 * section name may have been copied to replace the dot, in which
@@ -480,8 +435,8 @@ static int get_urlmatch(const char *var, const char *url)
 	 * alone) or points into var (e.g. 'http.savecookies'), and we do
 	 * not own the storage.
 	 */
-	if (collect.section != var)
-		free((void *)collect.section);
+	if (config.section != var)
+		free((void *)config.section);
 	return 0;
 }
 
diff --git a/url-match.c b/url-match.c
index 424a0a0..290ba40 100644
--- a/url-match.c
+++ b/url-match.c
@@ -466,3 +466,78 @@ int match_urls(const struct url_info *url,
 		*exactusermatch = usermatched;
 	return pathmatchlen;
 }
+
+int urlmatch_config_entry(const char *var, const char *value, void *cb)
+{
+	struct string_list_item *item;
+	struct urlmatch_config *collect = cb;
+	struct urlmatch_item *matched;
+	struct url_info *url = &collect->url;
+	const char *key, *dot;
+	struct strbuf synthkey = STRBUF_INIT;
+	size_t matched_len = 0;
+	int user_matched = 0;
+	int retval;
+
+	key = skip_prefix(var, collect->section);
+	if (!key || *(key++) != '.') {
+		if (collect->cascade_fn)
+			return collect->cascade_fn(var, value, cb);
+		return 0; /* not interested */
+	}
+	dot = strrchr(key, '.');
+	if (dot) {
+		char *config_url, *norm_url;
+		struct url_info norm_info;
+
+		config_url = xmemdupz(key, dot - key);
+		norm_url = url_normalize(config_url, &norm_info);
+		free(config_url);
+		if (!norm_url)
+			return 0;
+		matched_len = match_urls(url, &norm_info, &user_matched);
+		free(norm_url);
+		if (!matched_len)
+			return 0;
+		key = dot + 1;
+	}
+
+	if (collect->key && strcmp(key, collect->key))
+		return 0;
+
+	item = string_list_insert(&collect->vars, key);
+	if (!item->util) {
+		if (collect->item_alloc)
+			matched = collect->item_alloc(var, value, cb);
+		else
+			matched = xcalloc(1, sizeof(*matched));
+		item->util = matched;
+	} else {
+		matched = item->util;
+		/*
+		 * Is our match shorter?  Is our match the same
+		 * length, and without user while the current
+		 * candidate is with user?  Then we cannot use it.
+		 */
+		if (matched_len < matched->matched_len ||
+		    ((matched_len == matched->matched_len) &&
+		     (!user_matched && matched->user_matched)))
+			return 0;
+		/*
+		 * Otherwise, clear the old one and replace it
+		 * with this one.
+		 */
+		if (collect->item_clear)
+			collect->item_clear(matched);
+	}
+
+	matched->matched_len = matched_len;
+	matched->user_matched = user_matched;
+	strbuf_addstr(&synthkey, collect->section);
+	strbuf_addch(&synthkey, '.');
+	strbuf_addstr(&synthkey, key);
+	retval = collect->fn(synthkey.buf, value, collect->cb, matched);
+
+	strbuf_release(&synthkey);
+	return retval;
+}
diff --git a/url-match.h b/url-match.h
index e9cecd3..c3a5783 100644
--- a/url-match.h
+++ b/url-match.h
@@ -1,4 +1,5 @@
 #ifndef URL_MATCH_H
+#include "string-list.h"
 
 struct url_info {
 	/* normalized url on success, must be freed, otherwise NULL */
@@ -32,4 +33,25 @@ struct url_info {
 extern char *url_normalize(const char *, struct url_info *);
 extern int match_urls(const struct url_info *url, const struct url_info *url_prefix, int *exactusermatch);
 
+struct urlmatch_item {
+	size_t matched_len;
+	char user_matched;
+	/* possibly more */
+};
+
+struct urlmatch_config {
+	struct string_list vars;
+	struct url_info url;
+	const char *section;
+	const char *key;
+
+	void *cb;
+	int (*fn)(const char *var, const char *value, void *cb, void *matched);
+	int (*cascade_fn)(const char *var, const char *value, void *cb);
+	void *(*item_alloc)(const char *var, const char *value, void *cb);
+	void (*item_clear)(void *);
+};
+
+extern int urlmatch_config_entry(const char *var, const char *value, void *cb);
+
 #endif /* URL_MATCH_H */
-- 
1.8.4-rc0-137-g17832d4

  parent reply	other threads:[~2013-07-30  2:03 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-07-24 19:07 [PATCH] test-url-normalize.c: Fix gcc errors and sparse warnings Ramsay Jones
2013-07-24 19:35 ` Kyle J. McKay
2013-07-24 20:39   ` Junio C Hamano
2013-07-29 22:49     ` [PATCH 0/3] "git config --get-urlmatch $section.$key $url" Junio C Hamano
2013-07-29 22:49       ` [PATCH 1/3] url-match: split out URL matching logic out of http.c Junio C Hamano
2013-07-29 22:49       ` [PATCH 2/3] builtin/config: refactor collect_config() Junio C Hamano
2013-07-29 22:49       ` [PATCH 3/3] config: --get-urlmatch Junio C Hamano
2013-07-30  0:37         ` Jeff King
2013-07-30  1:33           ` Junio C Hamano
2013-07-30  8:14             ` Jeff King
2013-07-30 13:52               ` Junio C Hamano
2013-07-30 19:14         ` Kyle J. McKay
2013-07-30  2:03       ` Junio C Hamano [this message]
2013-07-30  2:13         ` [PATCH 5/3] revert most of the http_options() change Junio C Hamano
2013-07-30 19:14           ` Kyle J. McKay
2013-07-30 19:41             ` Kyle J. McKay
2013-07-30 21:09               ` Junio C Hamano
2013-07-31 17:59       ` [PATCH 0/3] "git config --get-urlmatch $section.$key $url" Ramsay Jones
2013-07-31 19:31         ` Junio C Hamano

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: http://vger.kernel.org/majordomo-info.html

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=7v7gg8ztvk.fsf_-_@alter.siamese.dyndns.org \
    --to=gitster@pobox.com \
    --cc=git@vger.kernel.org \
    --cc=mackyle@gmail.com \
    --cc=peff@peff.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).