[PATCH 4/3] url-match: generalize configuration collection logic

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxx>
---

 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

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]