From: Tanay Abhra <tanayabh@gmail.com>
To: Junio C Hamano <gitster@pobox.com>, Jeff King <peff@peff.net>
Cc: git@vger.kernel.org, Ramkumar Ramachandra <artagnon@gmail.com>,
Matthieu Moy <Matthieu.Moy@grenoble-inp.fr>
Subject: [PATCH v2 2/2] make config --add behave correctly for empty and NULL values
Date: Fri, 12 Sep 2014 12:55:21 +0530 [thread overview]
Message-ID: <54129FE1.6020303@gmail.com> (raw)
In-Reply-To: <54129F66.9080905@gmail.com>
The problem lies with the regexp used for simulating --add in
`git_config_set_multivar_in_file()`, "^$", which in ideal case should
not match with any string but is true for empty strings. Instead use a
sentinel value CONFIG_REGEX_NONE to say "we do not want to replace any
existing entry" and use it in the implementation of "git config --add".
For removing the segfault add a check for NULL values in `matches()` in
config.c.
Helped-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Tanay Abhra <tanayabh@gmail.com>
---
builtin/config.c | 2 +-
cache.h | 2 ++
config.c | 21 +++++++++++++++++----
t/t1303-wacky-config.sh | 2 +-
4 files changed, 21 insertions(+), 6 deletions(-)
diff --git a/builtin/config.c b/builtin/config.c
index aba7135..195664b 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -611,7 +611,7 @@ int cmd_config(int argc, const char **argv, const char *prefix)
check_argc(argc, 2, 2);
value = normalize_value(argv[0], argv[1]);
return git_config_set_multivar_in_file(given_config_source.file,
- argv[0], value, "^$", 0);
+ argv[0], value, CONFIG_REGEX_NONE, 0);
}
else if (actions == ACTION_REPLACE_ALL) {
check_write();
diff --git a/cache.h b/cache.h
index dfa1a56..a09217d 100644
--- a/cache.h
+++ b/cache.h
@@ -1284,6 +1284,8 @@ extern int update_server_info(int);
#define CONFIG_INVALID_PATTERN 6
#define CONFIG_GENERIC_ERROR 7
+extern const char CONFIG_REGEX_NONE[];
+
struct git_config_source {
unsigned int use_stdin:1;
const char *file;
diff --git a/config.c b/config.c
index 83c913a..20476e0 100644
--- a/config.c
+++ b/config.c
@@ -46,6 +46,8 @@ static int zlib_compression_seen;
*/
static struct config_set the_config_set;
+const char CONFIG_REGEX_NONE[] = "a^";
+
static int config_file_fgetc(struct config_source *conf)
{
return fgetc(conf->u.file);
@@ -1607,14 +1609,20 @@ static struct {
unsigned int offset_alloc;
enum { START, SECTION_SEEN, SECTION_END_SEEN, KEY_SEEN } state;
int seen;
+ unsigned value_never_matches:1;
} 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)));
+ if (strcmp(key, store.key))
+ return 0; /* not ours */
+ if (!store.value_regex)
+ return 1; /* always matches */
+ if (store.value_never_matches)
+ return 0; /* never matches */
+
+ return store.do_not_match ^
+ (value && !regexec(store.value_regex, value, 0, NULL, 0));
}
static int store_aux(const char *key, const char *value, void *cb)
@@ -1876,6 +1884,8 @@ out_free_ret_1:
/*
* If value==NULL, unset in (remove from) config,
* if value_regex!=NULL, disregard key/value pairs where value does not match.
+ * if value_regex==CONFIG_REGEX_NONE, do not match any existing values
+ * (only add a new one)
* 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.
@@ -1966,6 +1976,9 @@ int git_config_set_multivar_in_file(const char *config_filename,
} else
store.do_not_match = 0;
+ if (value_regex == CONFIG_REGEX_NONE)
+ store.value_never_matches = 1;
+
store.value_regex = (regex_t*)xmalloc(sizeof(regex_t));
if (regcomp(store.value_regex, value_regex,
REG_EXTENDED)) {
diff --git a/t/t1303-wacky-config.sh b/t/t1303-wacky-config.sh
index e5c0f07..3b92083 100755
--- a/t/t1303-wacky-config.sh
+++ b/t/t1303-wacky-config.sh
@@ -111,7 +111,7 @@ test_expect_success 'unset many entries' '
test_must_fail git config section.key
'
-test_expect_failure '--add appends new value after existing empty value' '
+test_expect_success '--add appends new value after existing empty value' '
cat >expect <<-\EOF &&
--
1.9.0.GIT
next prev parent reply other threads:[~2014-09-12 7:25 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-08-18 10:17 [PATCH] make config --add behave correctly for empty and NULL values Tanay Abhra
2014-08-18 12:33 ` Matthieu Moy
2014-08-18 18:18 ` Junio C Hamano
2014-08-19 5:17 ` Jeff King
2014-08-19 6:03 ` Junio C Hamano
2014-08-19 6:20 ` Jeff King
2014-09-11 23:35 ` Junio C Hamano
2014-09-12 2:29 ` Jeff King
2014-09-12 7:23 ` [PATCH v2 1/2] document irregular config --add behaviour " Tanay Abhra
2014-09-12 7:25 ` Tanay Abhra [this message]
2014-09-12 8:15 ` [PATCH v2 2/2] make config --add behave correctly " Matthieu Moy
2014-09-12 17:29 ` 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=54129FE1.6020303@gmail.com \
--to=tanayabh@gmail.com \
--cc=Matthieu.Moy@grenoble-inp.fr \
--cc=artagnon@gmail.com \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.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 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).