summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/git-config-set.txt18
-rw-r--r--config-set.c9
-rw-r--r--config.c23
-rw-r--r--t/t1300-config-set.sh28
4 files changed, 70 insertions, 8 deletions
diff --git a/Documentation/git-config-set.txt b/Documentation/git-config-set.txt
index c707fbcf99..bfbd42147a 100644
--- a/Documentation/git-config-set.txt
+++ b/Documentation/git-config-set.txt
@@ -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
------
diff --git a/config-set.c b/config-set.c
index 90a28b381f..5f654f7aff 100644
--- a/config-set.c
+++ b/config-set.c
@@ -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_);
diff --git a/config.c b/config.c
index 697d79f536..5d237c862d 100644
--- a/config.c
+++ b/config.c
@@ -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)) {
diff --git a/t/t1300-config-set.sh b/t/t1300-config-set.sh
index 717bf4de79..59b6c4c85d 100644
--- a/t/t1300-config-set.sh
+++ b/t/t1300-config-set.sh
@@ -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'