From: Junio C Hamano Date: Mon, 9 Sep 2013 21:50:32 +0000 (-0700) Subject: Merge branch 'jc/url-match' X-Git-Tag: v1.8.5-rc0~164 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/a0a08d48d068551ea819847743d8f5a178b9f8ba Merge branch 'jc/url-match' Allow section..var configuration variables to be treated as a "virtual" section.var given a URL, and use the mechanism to enhance http.* configuration variables. This is a reroll of Kyle J. McKay's work. * jc/url-match: builtin/config.c: compilation fix config: "git config --get-urlmatch" parses section..key builtin/config: refactor collect_config() config: parse http.. using urlmatch config: add generic callback wrapper to parse section..key config: add helper to normalize and match URLs http.c: fix parsing of http.sslCertPasswordProtected variable --- a0a08d48d068551ea819847743d8f5a178b9f8ba diff --cc Documentation/git-config.txt index 2dbe486eb1,b48e2ecc1c..e9917b89a9 --- a/Documentation/git-config.txt +++ b/Documentation/git-config.txt @@@ -95,14 -96,21 +96,22 @@@ OPTION in which section and variable names are lowercased, but subsection names are not. + --get-urlmatch name URL:: + When given a two-part name section.key, the value for + section..key whose part matches the best to the + given URL is returned (if no such key exists, the value for + section.key is used as a fallback). When given just the + section as name, do so for all the keys in the section and + list them. + --global:: - For writing options: write to global ~/.gitconfig file rather than - the repository .git/config, write to $XDG_CONFIG_HOME/git/config file - if this file exists and the ~/.gitconfig file doesn't. + For writing options: write to global `~/.gitconfig` file + rather than the repository `.git/config`, write to + `$XDG_CONFIG_HOME/git/config` file if this file exists and the + `~/.gitconfig` file doesn't. + -For reading options: read only from global ~/.gitconfig and from -$XDG_CONFIG_HOME/git/config rather than from all available files. +For reading options: read only from global `~/.gitconfig` and from +`$XDG_CONFIG_HOME/git/config` rather than from all available files. + See also <>. diff --cc builtin/config.c index 4ab9e9a550,ae199e9f75..fc8d8820cb --- a/builtin/config.c +++ b/builtin/config.c @@@ -358,12 -351,97 +361,103 @@@ static int get_colorbool(int print return get_colorbool_found ? 0 : 1; } +static void check_blob_write(void) +{ + if (given_config_blob) + die("writing config blobs is not supported"); +} + + struct urlmatch_current_candidate_value { + char value_is_null; + struct strbuf value; + }; + + static int urlmatch_collect_fn(const char *var, const char *value, void *cb) + { + struct string_list *values = cb; + struct string_list_item *item = string_list_insert(values, var); + struct urlmatch_current_candidate_value *matched = item->util; + + if (!matched) { + matched = xmalloc(sizeof(*matched)); + strbuf_init(&matched->value, 0); + item->util = matched; + } else { + strbuf_reset(&matched->value); + } + + if (value) { + strbuf_addstr(&matched->value, value); + matched->value_is_null = 0; + } else { + matched->value_is_null = 1; + } + return 0; + } + + static char *dup_downcase(const char *string) + { + char *result; + size_t len, i; + + len = strlen(string); + result = xmalloc(len + 1); + for (i = 0; i < len; i++) + result[i] = tolower(string[i]); + result[i] = '\0'; + return result; + } + + static int get_urlmatch(const char *var, const char *url) + { + char *section_tail; + struct string_list_item *item; + struct urlmatch_config config = { STRING_LIST_INIT_DUP }; + struct string_list values = STRING_LIST_INIT_DUP; + + config.collect_fn = urlmatch_collect_fn; + config.cascade_fn = NULL; + config.cb = &values; + + if (!url_normalize(url, &config.url)) + die("%s", config.url.err); + + config.section = dup_downcase(var); + section_tail = strchr(config.section, '.'); + if (section_tail) { + *section_tail = '\0'; + config.key = section_tail + 1; + show_keys = 0; + } else { + config.key = NULL; + show_keys = 1; + } + + git_config_with_options(urlmatch_config_entry, &config, - given_config_file, respect_includes); ++ given_config_file, NULL, respect_includes); + + for_each_string_list_item(item, &values) { + struct urlmatch_current_candidate_value *matched = item->util; + struct strbuf key = STRBUF_INIT; + struct strbuf buf = STRBUF_INIT; + + strbuf_addstr(&key, item->string); + format_config(&buf, key.buf, + matched->value_is_null ? NULL : matched->value.buf); + fwrite(buf.buf, 1, buf.len, stdout); + strbuf_release(&key); + strbuf_release(&buf); + + strbuf_release(&matched->value); + } + string_list_clear(&config.vars, 1); + string_list_clear(&values, 1); + free(config.url.url); + + free((void *)config.section); + return 0; + } + int cmd_config(int argc, const char **argv, const char *prefix) { int nongit = !startup_info->have_repository; @@@ -523,8 -593,11 +617,12 @@@ check_argc(argc, 1, 2); return get_value(argv[0], argv[1]); } + else if (actions == ACTION_GET_URLMATCH) { + check_argc(argc, 2, 2); + return get_urlmatch(argv[0], argv[1]); + } else if (actions == ACTION_UNSET) { + check_blob_write(); check_argc(argc, 1, 2); if (argc == 2) return git_config_set_multivar_in_file(given_config_file,