All of lore.kernel.org
 help / color / mirror / Atom feed
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

  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

* 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.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.