git-config-set: support selecting values by non-matching regex

Extend the regex syntax of value_regex so that prepending an exclamation
mark means non-match:

	[core]
		quetzal = "Dodo" for Brainf*ck
		quetzal = "T. Rex" for Malbolge
		quetzal = "cat"

You can match the third line with

	git-config-set --get quetzal '! for '

Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
Signed-off-by: Junio C Hamano <junkio@cox.net>
This commit is contained in:
Johannes Schindelin 2005-11-20 13:24:18 +01:00 committed by Junio C Hamano
parent a6322d079b
commit f98d863d21
4 changed files with 70 additions and 8 deletions

View File

@ -22,7 +22,9 @@ actually the section and the key separated by a dot, and the value will be
escaped.
If you want to set/unset an option which can occor on multiple lines, you
should provide a POSIX regex for the value.
should provide a POSIX regex for the value. If you want to handle the lines
*not* matching the regex, just prepend a single exlamation mark in front
(see EXAMPLES).
This command will fail if
@ -82,6 +84,7 @@ Given a .git/config like this:
command="ssh" for "ssh://kernel.org/"
command="proxy-command" for kernel.org
command="myprotocol-command" for "my://"
command=default-proxy ; for all the rest
you can set the filemode to true with
@ -139,6 +142,19 @@ new one with
% git config-set --replace-all proxy.command ssh
------------
However, if you really only want to replace the line for the default proxy,
i.e. the one without a "for ..." postfix, do something like this:
------------
% git config-set proxy.command ssh '! for '
------------
To actually match only values with an exclamation mark, you have to
------------
% git config-set section.key value '[!]'
------------
Author
------

View File

@ -8,13 +8,15 @@ static char* key = NULL;
static char* value = NULL;
static regex_t* regex = NULL;
static int do_all = 0;
static int do_not_match = 0;
static int seen = 0;
static int show_config(const char* key_, const char* value_)
{
if (!strcmp(key_, key) &&
(regex == NULL ||
!regexec(regex, value_, 0, NULL, 0))) {
(do_not_match ^
!regexec(regex, value_, 0, NULL, 0)))) {
if (do_all) {
printf("%s\n", value_);
return 0;
@ -38,6 +40,11 @@ static int get_value(const char* key_, const char* regex_)
key[i] = tolower(key_[i]);
if (regex_) {
if (regex_[0] == '!') {
do_not_match = 1;
regex_++;
}
regex = (regex_t*)malloc(sizeof(regex_t));
if (regcomp(regex, regex_, REG_EXTENDED)) {
fprintf(stderr, "Invalid pattern: %s\n", regex_);

View File

@ -269,6 +269,7 @@ int git_config(config_fn_t fn)
static struct {
int baselen;
char* key;
int do_not_match;
regex_t* value_regex;
int multi_replace;
off_t offset[MAX_MATCHES];
@ -276,13 +277,19 @@ static struct {
int seen;
} store;
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)));
}
static int store_aux(const char* key, const char* value)
{
switch (store.state) {
case KEY_SEEN:
if (!strcmp(key, store.key) &&
(store.value_regex == NULL ||
!regexec(store.value_regex, value, 0, NULL, 0))) {
if (matches(key, value)) {
if (store.seen == 1 && store.multi_replace == 0) {
fprintf(stderr,
"Warning: %s has multiple values\n",
@ -306,9 +313,7 @@ static int store_aux(const char* key, const char* value)
/* fallthru */
case SECTION_END_SEEN:
case START:
if (!strcmp(key, store.key) &&
(store.value_regex == NULL ||
!regexec(store.value_regex, value, 0, NULL, 0))) {
if (matches(key, value)) {
store.offset[store.seen] = ftell(config_file);
store.state = KEY_SEEN;
store.seen++;
@ -471,6 +476,12 @@ int git_config_set_multivar(const char* key, const char* value,
if (value_regex == NULL)
store.value_regex = NULL;
else {
if (value_regex[0] == '!') {
store.do_not_match = 1;
value_regex++;
} else
store.do_not_match = 0;
store.value_regex = (regex_t*)malloc(sizeof(regex_t));
if (regcomp(store.value_regex, value_regex,
REG_EXTENDED)) {

View File

@ -69,6 +69,28 @@ EOF
test_expect_success 'similar section' 'cmp .git/config expect'
test_expect_success 'replace with non-match' \
'git-config-set core.penguin kingpin !blue'
test_expect_success 'replace with non-match (actually matching)' \
'git-config-set core.penguin "very blue" !kingpin'
cat > expect << EOF
#
# This is the config file
#
[core]
penguin = very blue
Movie = BadPhysics
UPPERCASE = true
penguin = kingpin
[Cores]
WhatEver = Second
EOF
test_expect_success 'non-match result' 'cmp .git/config expect'
cat > .git/config << EOF
[beta] ; silly comment # another comment
noIndent= sillyValue ; 'nother silly comment
@ -173,6 +195,12 @@ EOF
test_expect_success 'multivar' 'cmp .git/config expect'
test_expect_success 'non-match' \
'git-config-set --get nextsection.nonewline !for'
test_expect_success 'non-match value' \
'test wow = $(git-config-set --get nextsection.nonewline !for)'
test_expect_failure 'ambiguous get' \
'git-config-set --get nextsection.nonewline'