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