From: Junio C Hamano <gitster@pobox.com>
To: git@vger.kernel.org
Cc: "Kyle J. McKay" <mackyle@gmail.com>, Jeff King <peff@peff.net>
Subject: [PATCH 3/3] config: --get-urlmatch
Date: Mon, 29 Jul 2013 15:49:10 -0700 [thread overview]
Message-ID: <1375138150-19520-4-git-send-email-gitster@pobox.com> (raw)
In-Reply-To: <1375138150-19520-1-git-send-email-gitster@pobox.com>
"git config --get-urlmatch $section[.$variable] $url" is a way to
learn what the configured value for $section.$variable is for the
given URL, using the logic introduced by the http.<url>.config
topic. In addition to $section.$variable, entries in the
configuration file(s) that match $section.<urlpattern>.$variable are
looked up and the one with <urlpattern> that matches the given $url
the best is used to answer the query.
This can still be further refactored to remove code from http_options()
in http.c, I think.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
builtin/config.c | 141 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 141 insertions(+)
diff --git a/builtin/config.c b/builtin/config.c
index 12c5073..c1d32ae 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -2,6 +2,7 @@
#include "cache.h"
#include "color.h"
#include "parse-options.h"
+#include "url-match.h"
static const char *const builtin_config_usage[] = {
N_("git config [options]"),
@@ -41,6 +42,7 @@ static int respect_includes = -1;
#define ACTION_SET_ALL (1<<12)
#define ACTION_GET_COLOR (1<<13)
#define ACTION_GET_COLORBOOL (1<<14)
+#define ACTION_GET_URLMATCH (1<<15)
#define TYPE_BOOL (1<<0)
#define TYPE_INT (1<<1)
@@ -57,6 +59,7 @@ static struct option builtin_config_options[] = {
OPT_BIT(0, "get", &actions, N_("get value: name [value-regex]"), ACTION_GET),
OPT_BIT(0, "get-all", &actions, N_("get all values: key [value-regex]"), ACTION_GET_ALL),
OPT_BIT(0, "get-regexp", &actions, N_("get values for regexp: name-regex [value-regex]"), ACTION_GET_REGEXP),
+ OPT_BIT(0, "get-urlmatch", &actions, N_("get value specific for the URL: section[.var] URL"), ACTION_GET_URLMATCH),
OPT_BIT(0, "replace-all", &actions, N_("replace all matching variables: name value [value_regex]"), ACTION_REPLACE_ALL),
OPT_BIT(0, "add", &actions, N_("add a new variable: name value"), ACTION_ADD),
OPT_BIT(0, "unset", &actions, N_("remove a variable: name [value-regex]"), ACTION_UNSET),
@@ -348,6 +351,140 @@ 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;
+ char value_is_null;
+ struct strbuf value;
+};
+
+static int urlmatch_collect(const char *var, const char *value, void *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;
+
+ 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;
+ } else {
+ matched->value_is_null = 1;
+ }
+ return 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 };
+
+ if (!url_normalize(url, &collect.url))
+ die(collect.url.err);
+
+ section_tail = strchr(var, '.');
+ if (section_tail) {
+ collect.section = xmemdupz(var, section_tail - var);
+ collect.key = strrchr(var, '.') + 1;
+ show_keys = 0;
+ } else {
+ collect.section = var;
+ collect.key = NULL;
+ show_keys = 1;
+ }
+
+ git_config_with_options(urlmatch_collect, &collect,
+ given_config_file, respect_includes);
+
+ for_each_string_list_item(item, &collect.vars) {
+ struct urlmatch_item *matched = item->util;
+ struct strbuf key = STRBUF_INIT;
+ struct strbuf buf = STRBUF_INIT;
+
+ strbuf_addstr(&key, collect.section);
+ strbuf_addch(&key, '.');
+ 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(&collect.vars, 1);
+
+ /*
+ * section name may have been copied to replace the dot, in which
+ * case it needs to be freed. key name is either NULL (e.g. 'http'
+ * alone) or points into var (e.g. 'http.savecookies'), and we do
+ * not own the storage.
+ */
+ if (collect.section != var)
+ free((void *)collect.section);
+ return 0;
+}
+
int cmd_config(int argc, const char **argv, const char *prefix)
{
int nongit = !startup_info->have_repository;
@@ -499,6 +636,10 @@ int cmd_config(int argc, const char **argv, const char *prefix)
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_argc(argc, 1, 2);
if (argc == 2)
--
1.8.4-rc0-137-g17832d4
next prev parent reply other threads:[~2013-07-29 22:49 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-07-24 19:07 [PATCH] test-url-normalize.c: Fix gcc errors and sparse warnings Ramsay Jones
2013-07-24 19:35 ` Kyle J. McKay
2013-07-24 20:39 ` Junio C Hamano
2013-07-29 22:49 ` [PATCH 0/3] "git config --get-urlmatch $section.$key $url" Junio C Hamano
2013-07-29 22:49 ` [PATCH 1/3] url-match: split out URL matching logic out of http.c Junio C Hamano
2013-07-29 22:49 ` [PATCH 2/3] builtin/config: refactor collect_config() Junio C Hamano
2013-07-29 22:49 ` Junio C Hamano [this message]
2013-07-30 0:37 ` [PATCH 3/3] config: --get-urlmatch Jeff King
2013-07-30 1:33 ` Junio C Hamano
2013-07-30 8:14 ` Jeff King
2013-07-30 13:52 ` Junio C Hamano
2013-07-30 19:14 ` Kyle J. McKay
2013-07-30 2:03 ` [PATCH 4/3] url-match: generalize configuration collection logic Junio C Hamano
2013-07-30 2:13 ` [PATCH 5/3] revert most of the http_options() change Junio C Hamano
2013-07-30 19:14 ` Kyle J. McKay
2013-07-30 19:41 ` Kyle J. McKay
2013-07-30 21:09 ` Junio C Hamano
2013-07-31 17:59 ` [PATCH 0/3] "git config --get-urlmatch $section.$key $url" Ramsay Jones
2013-07-31 19:31 ` Junio C Hamano
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: http://vger.kernel.org/majordomo-info.html
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1375138150-19520-4-git-send-email-gitster@pobox.com \
--to=gitster@pobox.com \
--cc=git@vger.kernel.org \
--cc=mackyle@gmail.com \
--cc=peff@peff.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://80x24.org/mirrors/git.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).