From: Jeff King <peff@peff.net>
To: Whit Armstrong <armstrong.whit@gmail.com>
Cc: Junio C Hamano <gitster@pobox.com>, git@vger.kernel.org
Subject: [PATCH 11/16] config: add --literal-match option
Date: Wed, 12 Mar 2008 17:40:19 -0400 [thread overview]
Message-ID: <20080312214019.GL26286@coredump.intra.peff.net> (raw)
In-Reply-To: <cover.1205356737.git.peff@peff.net>
When limiting the values to be set (or returned), the user
previously had the option of specifying a regex. In some
cases, however, they may want to find a literal value. The
option --literal-match converts any matching regex into a
literal string comparison.
Signed-off-by: Jeff King <peff@peff.net>
---
I think this is a nice addition regardless, but it is used by the next
patch.
The patch is about twice as long as it needs to be since getting and
setting in builtin-config follow two almost-the-same parallel codepaths.
I suspect this could be cleaned up, but I didn't look too closely.
Documentation/git-config.txt | 7 ++++
builtin-config.c | 50 +++++++++++++++++++++++--------
builtin-remote.c | 2 +-
cache.h | 2 +-
config.c | 67 ++++++++++++++++++++++++++++--------------
t/t1300-repo-config.sh | 13 ++++++++
6 files changed, 104 insertions(+), 37 deletions(-)
diff --git a/Documentation/git-config.txt b/Documentation/git-config.txt
index fa16171..5dc1af2 100644
--- a/Documentation/git-config.txt
+++ b/Documentation/git-config.txt
@@ -152,6 +152,13 @@ See also <<FILES>>.
output. The optional `default` parameter is used instead, if
there is no color configured for `name`.
+--literal-match::
+
+ Some invocations of git-config will limit their actions based on
+ matching a config value to a regular expression. If this option
+ is used, then any such matches are done as a string comparison
+ rather than as a regular expression match.
+
[[FILES]]
FILES
-----
diff --git a/builtin-config.c b/builtin-config.c
index 2b9a426..ed318dc 100644
--- a/builtin-config.c
+++ b/builtin-config.c
@@ -8,6 +8,7 @@ static const char git_config_set_usage[] =
static char *key;
static regex_t *key_regexp;
static regex_t *regexp;
+const char *value_match;
static int show_keys;
static int use_key_regexp;
static int do_all;
@@ -17,6 +18,7 @@ static char delim = '=';
static char key_delim = ' ';
static char term = '\n';
static enum { T_RAW, T_INT, T_BOOL } type = T_RAW;
+static int literal_match = 0;
static int show_all_config(const char *key_, const char *value_)
{
@@ -40,6 +42,9 @@ static int show_config(const char* key_, const char* value_)
if (regexp != NULL &&
(do_not_match ^ !!regexec(regexp, (value_?value_:""), 0, NULL, 0)))
return 0;
+ if (value_match != NULL &&
+ do_not_match ^ !!strcmp(value_match, (value_ ? value_ : "")))
+ return 0;
if (show_keys) {
if (value_)
@@ -66,7 +71,7 @@ static int show_config(const char* key_, const char* value_)
return 0;
}
-static int get_value(const char* key_, const char* regex_)
+static int get_value(const char* key_, const char* match_)
{
int ret = -1;
char *tl;
@@ -99,18 +104,28 @@ static int get_value(const char* key_, const char* regex_)
}
}
- if (regex_) {
- if (regex_[0] == '!') {
+ if (match_ && literal_match) {
+ value_match = match_;
+ do_not_match = 0;
+ regexp = NULL;
+ }
+ else if(match_) {
+ value_match = NULL;
+ if (match_[0] == '!') {
do_not_match = 1;
- regex_++;
+ match_++;
}
regexp = (regex_t*)xmalloc(sizeof(regex_t));
- if (regcomp(regexp, regex_, REG_EXTENDED)) {
- fprintf(stderr, "Invalid pattern: %s\n", regex_);
+ if (regcomp(regexp, match_, REG_EXTENDED)) {
+ fprintf(stderr, "Invalid pattern: %s\n", match_);
goto free_strings;
}
}
+ else {
+ value_match = NULL;
+ regexp = NULL;
+ }
if (do_all && system_wide)
git_config_from_file(show_config, system_wide);
@@ -339,6 +354,8 @@ int cmd_config(int argc, const char **argv, const char *prefix)
return get_color(argc-2, argv+2);
} else if (!strcmp(argv[1], "--get-colorbool")) {
return get_colorbool(argc-2, argv+2);
+ } else if (!strcmp(argv[1], "--literal-match")) {
+ literal_match = 1;
} else
break;
argc--;
@@ -352,7 +369,8 @@ int cmd_config(int argc, const char **argv, const char *prefix)
if (!strcmp(argv[1], "--unset"))
return git_config_set(argv[2], NULL);
else if (!strcmp(argv[1], "--unset-all"))
- return git_config_set_multivar(argv[2], NULL, NULL, 1);
+ return git_config_set_multivar(argv[2], NULL, NULL,
+ literal_match, 1);
else if (!strcmp(argv[1], "--get"))
return get_value(argv[2], NULL);
else if (!strcmp(argv[1], "--get-all")) {
@@ -369,9 +387,11 @@ int cmd_config(int argc, const char **argv, const char *prefix)
}
case 4:
if (!strcmp(argv[1], "--unset"))
- return git_config_set_multivar(argv[2], NULL, argv[3], 0);
+ return git_config_set_multivar(argv[2], NULL, argv[3],
+ literal_match, 0);
else if (!strcmp(argv[1], "--unset-all"))
- return git_config_set_multivar(argv[2], NULL, argv[3], 1);
+ return git_config_set_multivar(argv[2], NULL, argv[3],
+ literal_match, 1);
else if (!strcmp(argv[1], "--get"))
return get_value(argv[2], argv[3]);
else if (!strcmp(argv[1], "--get-all")) {
@@ -384,18 +404,22 @@ int cmd_config(int argc, const char **argv, const char *prefix)
return get_value(argv[2], argv[3]);
} else if (!strcmp(argv[1], "--add")) {
value = normalize_value(argv[2], argv[3]);
- return git_config_set_multivar(argv[2], value, "^$", 0);
+ return git_config_set_multivar(argv[2], value, "^$",
+ 0, 0);
} else if (!strcmp(argv[1], "--replace-all")) {
value = normalize_value(argv[2], argv[3]);
- return git_config_set_multivar(argv[2], value, NULL, 1);
+ return git_config_set_multivar(argv[2], value, NULL,
+ 0, 1);
} else {
value = normalize_value(argv[1], argv[2]);
- return git_config_set_multivar(argv[1], value, argv[3], 0);
+ return git_config_set_multivar(argv[1], value, argv[3],
+ literal_match, 0);
}
case 5:
if (!strcmp(argv[1], "--replace-all")) {
value = normalize_value(argv[2], argv[3]);
- return git_config_set_multivar(argv[2], value, argv[4], 1);
+ return git_config_set_multivar(argv[2], value, argv[4],
+ literal_match, 1);
}
case 1:
default:
diff --git a/builtin-remote.c b/builtin-remote.c
index 24e6929..4eae74b 100644
--- a/builtin-remote.c
+++ b/builtin-remote.c
@@ -107,7 +107,7 @@ static int add(int argc, const char **argv)
else
strbuf_addf(&buf2, "refs/heads/%s:refs/remotes/%s/%s",
item->path, name, item->path);
- if (git_config_set_multivar(buf.buf, buf2.buf, "^$", 0))
+ if (git_config_set_multivar(buf.buf, buf2.buf, "^$", 0, 0))
return 1;
}
diff --git a/cache.h b/cache.h
index 2a1e7ec..30830b0 100644
--- a/cache.h
+++ b/cache.h
@@ -695,7 +695,7 @@ extern unsigned long git_config_ulong(const char *, const char *);
extern int git_config_bool(const char *, const char *);
extern int git_config_string(const char **, const char *, const char *);
extern int git_config_set(const char *, const char *);
-extern int git_config_set_multivar(const char *, const char *, const char *, int);
+extern int git_config_set_multivar(const char *, const char *, const char *, int, int);
extern int git_config_rename_section(const char *, const char *);
extern const char *git_etc_gitconfig(void);
extern int check_repository_format_version(const char *var, const char *value);
diff --git a/config.c b/config.c
index 0624494..862b0e6 100644
--- a/config.c
+++ b/config.c
@@ -575,7 +575,15 @@ static struct {
int baselen;
char* key;
int do_not_match;
- regex_t* value_regex;
+ enum {
+ VALUE_NONE,
+ VALUE_REGEX,
+ VALUE_STRING,
+ } value_type;
+ union {
+ regex_t* regex;
+ const char *string;
+ } value;
int multi_replace;
size_t offset[MAX_MATCHES];
enum { START, SECTION_SEEN, SECTION_END_SEEN, KEY_SEEN } state;
@@ -584,10 +592,19 @@ static struct {
static int matches(const char* key, const char* value)
{
- return !strcmp(key, store.key) &&
- (store.value_regex == NULL ||
- (store.do_not_match ^
- !regexec(store.value_regex, value, 0, NULL, 0)));
+ if (strcmp(key, store.key))
+ return 0;
+ switch(store.value_type) {
+ case VALUE_NONE:
+ return 1;
+ case VALUE_REGEX:
+ return store.do_not_match ^
+ !regexec(store.value.regex, value, 0, NULL, 0);
+ case VALUE_STRING:
+ return store.do_not_match ^
+ !strcmp(value, store.value.string);
+ }
+ die("bug in config.c:matches");
}
static int store_aux(const char* key, const char* value)
@@ -764,12 +781,12 @@ contline:
int git_config_set(const char* key, const char* value)
{
- return git_config_set_multivar(key, value, NULL, 0);
+ return git_config_set_multivar(key, value, NULL, 0, 0);
}
/*
* If value==NULL, unset in (remove from) config,
- * if value_regex!=NULL, disregard key/value pairs where value does not match.
+ * if value_match!=NULL, disregard key/value pairs where value does not match.
* if multi_replace==0, nothing, or only one matching key/value is replaced,
* else all matching key/values (regardless how many) are removed,
* before the new pair is written.
@@ -791,7 +808,7 @@ int git_config_set(const char* key, const char* value)
*
*/
int git_config_set_multivar(const char* key, const char* value,
- const char* value_regex, int multi_replace)
+ const char* value_match, int literal_match, int multi_replace)
{
int i, dot;
int fd = -1, in_fd;
@@ -892,21 +909,27 @@ int git_config_set_multivar(const char* key, const char* value,
size_t contents_sz, copy_begin, copy_end;
int i, new_line = 0;
- if (value_regex == NULL)
- store.value_regex = NULL;
+ if (value_match == NULL)
+ store.value_type = VALUE_NONE;
+ else if(literal_match) {
+ store.value_type = VALUE_STRING;
+ store.do_not_match = 0;
+ store.value.string = value_match;
+ }
else {
- if (value_regex[0] == '!') {
+ store.value_type = VALUE_REGEX;
+ if (value_match[0] == '!') {
store.do_not_match = 1;
- value_regex++;
+ value_match++;
} else
store.do_not_match = 0;
- store.value_regex = (regex_t*)xmalloc(sizeof(regex_t));
- if (regcomp(store.value_regex, value_regex,
+ store.value.regex = (regex_t*)xmalloc(sizeof(regex_t));
+ if (regcomp(store.value.regex, value_match,
REG_EXTENDED)) {
fprintf(stderr, "Invalid pattern: %s\n",
- value_regex);
- free(store.value_regex);
+ value_match);
+ free(store.value.regex);
ret = 6;
goto out_free;
}
@@ -925,18 +948,18 @@ int git_config_set_multivar(const char* key, const char* value,
if (git_config_from_file(store_aux, config_filename)) {
fprintf(stderr, "invalid config file\n");
free(store.key);
- if (store.value_regex != NULL) {
- regfree(store.value_regex);
- free(store.value_regex);
+ if (store.value_type == VALUE_REGEX) {
+ regfree(store.value.regex);
+ free(store.value.regex);
}
ret = 3;
goto out_free;
}
free(store.key);
- if (store.value_regex != NULL) {
- regfree(store.value_regex);
- free(store.value_regex);
+ if (store.value_type == VALUE_REGEX) {
+ regfree(store.value.regex);
+ free(store.value.regex);
}
/* if nothing to unset, or too many matches, error out */
diff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh
index b36a901..6c5ccdd 100755
--- a/t/t1300-repo-config.sh
+++ b/t/t1300-repo-config.sh
@@ -682,4 +682,17 @@ test_expect_success 'symlinked configuration' '
'
+test_expect_success 'literal matching works' '
+
+ git config literal.key1 value &&
+ git config literal.key2 va..e &&
+ git config --get-regexp "literal..*" va..e >output &&
+ grep key1 output &&
+ grep key2 output &&
+ git config --literal-match --get-regexp "literal..*" va..e >output &&
+ ! grep key1 output &&
+ grep key2 output
+
+'
+
test_done
--
1.5.4.4.543.g30fdd.dirty
next prev parent reply other threads:[~2008-03-12 21:41 UTC|newest]
Thread overview: 59+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <cover.1205356737.git.peff@peff.net>
2008-03-12 21:29 ` [PATCH 01/16] tr portability fixes Jeff King
2008-03-13 7:32 ` Johannes Sixt
2008-03-13 13:06 ` Jeff King
2008-03-12 21:30 ` [PATCH 02/16] t0050: perl portability fix Jeff King
2008-03-13 7:38 ` Johannes Sixt
2008-03-12 21:31 ` [PATCH 03/16] more tr portability test script fixes Jeff King
2008-03-13 8:28 ` Frank Lichtenheld
2008-03-13 13:09 ` Jeff King
2008-03-18 22:23 ` Alex Riesen
2008-03-18 22:24 ` [PATCH] Add test-tr: poor-man tr for the test suite Alex Riesen
2008-03-18 22:24 ` [PATCH] Use test-tr in " Alex Riesen
2008-03-18 22:44 ` [PATCH 03/16] more tr portability test script fixes Jeff King
2008-03-18 23:24 ` Alex Riesen
2008-03-19 21:40 ` Junio C Hamano
2008-03-19 22:56 ` Alex Riesen
2008-03-12 21:32 ` [PATCH 04/16] grep portability fix: don't use "-e" or "-q" Jeff King
2008-03-12 22:10 ` Junio C Hamano
2008-03-12 22:45 ` Junio C Hamano
2008-03-12 21:34 ` [PATCH 05/16] remove use of "tail -n 1" and "tail -1" Jeff King
2008-03-12 21:36 ` [PATCH 06/16] add test_cmp function for test scripts Jeff King
2008-03-12 22:12 ` Junio C Hamano
2008-03-13 12:08 ` Jeff King
2008-03-13 20:48 ` Junio C Hamano
2008-03-12 21:37 ` [PATCH 07/16] t4020: don't use grep -a Jeff King
2008-03-12 21:37 ` [PATCH 08/16] t4200: use cut instead of sed Jeff King
2008-03-13 4:52 ` Junio C Hamano
2008-03-13 12:59 ` Jeff King
2008-03-13 18:00 ` Junio C Hamano
2008-03-14 21:40 ` Jeff King
2008-03-12 21:38 ` [PATCH 09/16] t6000lib: tr portability fix Jeff King
2008-03-14 20:47 ` [PATCH] t/t6000lib.sh: tr portability fix fix Brandon Casey
2008-03-14 20:54 ` Jeff King
2008-03-14 21:00 ` Brandon Casey
2008-03-14 21:26 ` Brandon Casey
2008-03-14 21:45 ` Jeff King
2008-03-14 22:06 ` Brandon Casey
2008-03-12 21:39 ` [PATCH 10/16] add NO_EXTERNAL_GREP build option Jeff King
2008-03-12 22:30 ` Junio C Hamano
2008-03-13 12:10 ` Jeff King
2008-03-13 7:50 ` Johannes Sixt
2008-03-13 12:41 ` Jeff King
2008-03-13 13:59 ` Johannes Sixt
2008-03-13 14:04 ` Jeff King
2008-03-13 14:09 ` Johannes Sixt
2008-03-13 7:56 ` Junio C Hamano
2008-03-12 21:40 ` Jeff King [this message]
2008-03-12 21:46 ` [PATCH 11/16] config: add --literal-match option Jakub Narebski
2008-03-13 13:24 ` Jeff King
2008-03-12 22:34 ` Junio C Hamano
2008-03-13 12:42 ` Jeff King
2008-03-12 21:40 ` [PATCH 12/16] git-submodule: avoid sed input with no newline Jeff King
2008-03-12 22:41 ` Junio C Hamano
2008-03-13 12:46 ` Jeff King
2008-03-12 21:41 ` [PATCH 13/16] filter-branch: don't use xargs -0 Jeff King
2008-03-12 21:41 ` [PATCH 14/16] filter-branch: use $SHELL_PATH instead of 'sh' Jeff King
2008-03-12 21:42 ` [PATCH 15/16] t9112: add missing #!/bin/sh header Jeff King
2008-03-12 21:42 ` [PATCH 16/16] t7505: use SHELL_PATH in hook Jeff King
2008-03-13 7:11 ` Adam Piatyszek
2008-03-13 13:00 ` Jeff King
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=20080312214019.GL26286@coredump.intra.peff.net \
--to=peff@peff.net \
--cc=armstrong.whit@gmail.com \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
/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 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 NNTP newsgroup(s).