From: Jeff King <peff@peff.net>
To: Junio C Hamano <gitster@pobox.com>
Cc: Tanay Abhra <tanayabh@gmail.com>,
git@vger.kernel.org, Ramkumar Ramachandra <artagnon@gmail.com>,
Matthieu Moy <Matthieu.Moy@grenoble-inp.fr>
Subject: Re: [PATCH] make config --add behave correctly for empty and NULL values
Date: Tue, 19 Aug 2014 02:20:00 -0400 [thread overview]
Message-ID: <20140819062000.GA7805@peff.net> (raw)
In-Reply-To: <xmqqmwb1vwvs.fsf@gitster.dls.corp.google.com>
On Mon, Aug 18, 2014 at 11:03:51PM -0700, Junio C Hamano wrote:
> We already have some code paths that use ((void *)1) as a special
> pointer value, so in that sense I would say it is not the end of the
> world if you added a new one.
No, but if you use it to replace the regexp, you end up having to check
for it in the code paths that regfree() the result. I think a separate
bit is nicer for that reason.
> At the end-user level (i.e. people who write callers to
> set-multivar-in-file function), I actually like your idea of inventing
> our own string syntax and parse it at the place where we strip '!' out
> and remember that the pattern's match status needs to be negated.
I thought at first that "!" by itself might be fine, but that is
actually a valid regex. And we may feed user input directly to the
function, so we have to be careful not to get too clever.
> For example, instead of "a^" (to which
> I cannot say with confidence that no implementation would match the
> not-at-the-beginning caret literally), I would not mind if we taught
> set-multivar-in-file that we use "!*" as a mark to tell "this
> pattern never matches",
That would work, but I think CONFIG_REGEX_NONE or similar is a bit less
cryptic, and not any harder to implement.
Here is the patch I wrote, for reference (I also think breaking the
"matches" function into a series of conditionals, as you showed, is way
more readable):
diff --git a/builtin/config.c b/builtin/config.c
index b9e7dce..7bba516 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -586,7 +586,8 @@ 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, "a^", 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 fcb511d..dcf3a2a 100644
--- a/cache.h
+++ b/cache.h
@@ -1281,6 +1281,8 @@ extern int update_server_info(int);
#define CONFIG_INVALID_PATTERN 6
#define CONFIG_GENERIC_ERROR 7
+#define CONFIG_REGEX_NONE ((void *)1)
+
struct git_config_source {
unsigned int use_stdin:1;
const char *file;
diff --git a/config.c b/config.c
index 67a7729..1199faf 100644
--- a/config.c
+++ b/config.c
@@ -1229,6 +1229,7 @@ static struct {
static int matches(const char *key, const char *value)
{
return !strcmp(key, store.key) &&
+ store.value_regex != CONFIG_REGEX_NONE &&
(store.value_regex == NULL ||
(store.do_not_match ^
(value && !regexec(store.value_regex, value, 0, NULL, 0))));
@@ -1493,6 +1494,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.
@@ -1576,6 +1579,8 @@ int git_config_set_multivar_in_file(const char *config_filename,
if (value_regex == NULL)
store.value_regex = NULL;
+ else if (value_regex == CONFIG_REGEX_NONE)
+ store.value_regex = CONFIG_REGEX_NONE;
else {
if (value_regex[0] == '!') {
store.do_not_match = 1;
@@ -1607,7 +1612,8 @@ int git_config_set_multivar_in_file(const char *config_filename,
if (git_config_from_file(store_aux, config_filename, NULL)) {
error("invalid config file %s", config_filename);
free(store.key);
- if (store.value_regex != NULL) {
+ if (store.value_regex != NULL &&
+ store.value_regex != CONFIG_REGEX_NONE) {
regfree(store.value_regex);
free(store.value_regex);
}
@@ -1616,7 +1622,8 @@ int git_config_set_multivar_in_file(const char *config_filename,
}
free(store.key);
- if (store.value_regex != NULL) {
+ if (store.value_regex != NULL &&
+ store.value_regex != CONFIG_REGEX_NONE) {
regfree(store.value_regex);
free(store.value_regex);
}
next prev parent reply other threads:[~2014-08-19 6:20 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 [this message]
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 ` [PATCH v2 2/2] make config --add behave correctly " Tanay Abhra
2014-09-12 8:15 ` 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=20140819062000.GA7805@peff.net \
--to=peff@peff.net \
--cc=Matthieu.Moy@grenoble-inp.fr \
--cc=artagnon@gmail.com \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=tanayabh@gmail.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).