[prev in list] [next in list] [prev in thread] [next in thread] 

List:       git
Subject:    [PATCH v6 3/6] config: add generic callback wrapper to parse section.<url>.key
From:       Junio C Hamano <gitster () pobox ! com>
Date:       2013-07-31 19:26:05
Message-ID: 1375298768-7740-4-git-send-email-gitster () pobox ! com
[Download RAW message or body]

Existing configuration parsing functions (e.g. http_options() in
http.c) know how to parse two-level configuration variable names.
We would like to exploit them and parse something like this:

	[http]
		sslVerify = true
	[http "https://weak.example.com"]
		sslVerify = false

and pretend as if http.sslVerify were set to false when talking to
"https://weak.example.com/path".

Introduce `urlmatch_config_entry()` wrapper that:

 - is called with the target URL (e.g. "https://weak.example.com/path"),
   and the two-level variable parser (e.g. `http_options`);

 - uses `url_normalize()` and `match_urls()` to see if configuration
   data matches the target URL; and

 - calls the traditional two-level configuration variable parser
   only for the configuration data whose <url> part matches the
   target URL (and if there are multiple matches, only do so if the
   current match is a better match than the ones previously seen).

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 urlmatch.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 urlmatch.h | 18 +++++++++++++++++
 2 files changed, 85 insertions(+)

diff --git a/urlmatch.c b/urlmatch.c
index e1b03ee..073fdd3 100644
--- a/urlmatch.c
+++ b/urlmatch.c
@@ -466,3 +466,70 @@ 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) {
+		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, replace it with this one. */
+	}
+
+	matched->matched_len = matched_len;
+	matched->user_matched = user_matched;
+	strbuf_addstr(&synthkey, collect->section);
+	strbuf_addch(&synthkey, '.');
+	strbuf_addstr(&synthkey, key);
+	retval = collect->collect_fn(synthkey.buf, value, collect->cb);
+
+	strbuf_release(&synthkey);
+	return retval;
+}
diff --git a/urlmatch.h b/urlmatch.h
index b67f57f..b461dfd 100644
--- a/urlmatch.h
+++ b/urlmatch.h
@@ -33,4 +33,22 @@ 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;
+};
+
+struct urlmatch_config {
+	struct string_list vars;
+	struct url_info url;
+	const char *section;
+	const char *key;
+
+	void *cb;
+	int (*collect_fn)(const char *var, const char *value, void *cb);
+	int (*cascade_fn)(const char *var, const char *value, void *cb);
+};
+
+extern int urlmatch_config_entry(const char *var, const char *value, void *cb);
+
 #endif /* URL_MATCH_H */
-- 
1.8.4-rc0-153-g9820077

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


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic