aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2013-07-31 10:42:01 -0700
committerJunio C Hamano <gitster@pobox.com>2013-07-31 14:58:42 -0700
commit836b6fb5a56338dc28165284875b257ccfd6c224 (patch)
treeaca2f31d1d6c4b60d792f3e1ac85fdd43d3e313f
parent3402a8dc485db5ad1df1557ab672b7e25048bc08 (diff)
downloadgit-836b6fb5a56338dc28165284875b257ccfd6c224.tar.gz
git-836b6fb5a56338dc28165284875b257ccfd6c224.tar.xz
config: add generic callback wrapper to parse section.<url>.key
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>
-rw-r--r--urlmatch.c67
-rw-r--r--urlmatch.h18
2 files changed, 85 insertions, 0 deletions
diff --git a/urlmatch.c b/urlmatch.c
index 4f38cc7bc..1db76c89b 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 b67f57f86..b461dfd3d 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 */