summaryrefslogtreecommitdiff
path: root/xdiff-interface.c
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2008-09-20 07:52:11 (GMT)
committerJunio C Hamano <gitster@pobox.com>2008-09-20 07:52:11 (GMT)
commit3d8dccd74aa29a9019c4e8b52e75a40189e6f5cb (patch)
tree909f000e201535f714e52bef7cf142ddb25a62eb /xdiff-interface.c
parent1883a0d3b7ad7c9de1ac790bda6f1a6181237439 (diff)
downloadgit-3d8dccd74aa29a9019c4e8b52e75a40189e6f5cb.zip
git-3d8dccd74aa29a9019c4e8b52e75a40189e6f5cb.tar.gz
git-3d8dccd74aa29a9019c4e8b52e75a40189e6f5cb.tar.bz2
diff: fix "multiple regexp" semantics to find hunk header comment
When multiple regular expressions are concatenated with "\n", they were traditionally AND'ed together, and only a line that matches _all_ of them is taken as a match. This however is unwieldy when multiple regexp feature is used to specify alternatives. This fixes the semantics to take the first match. A nagative pattern, if matches, makes the line to fail as before. A match with a positive pattern will be the final match, and what it captures in $1 is used as the hunk header comment. We could write alternatives using "|" in ERE, but the machinery can only use captured $1 as the hunk header comment (or $0 if there is no match in $1), so you cannot write: "junk ( A | B ) | garbage ( C | D )" and expect both "junk" and "garbage" to get stripped with the existing code. With this fix, you can write it as: "junk ( A | B ) \n garbage ( C | D )" and the way capture works would match the user expectation more naturally. Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'xdiff-interface.c')
-rw-r--r--xdiff-interface.c17
1 files changed, 10 insertions, 7 deletions
diff --git a/xdiff-interface.c b/xdiff-interface.c
index 7f1a7d3..6c6bb19 100644
--- a/xdiff-interface.c
+++ b/xdiff-interface.c
@@ -194,26 +194,29 @@ static long ff_regexp(const char *line, long len,
char *line_buffer = xstrndup(line, len); /* make NUL terminated */
struct ff_regs *regs = priv;
regmatch_t pmatch[2];
- int result = 0, i;
+ int i;
+ int result = -1;
for (i = 0; i < regs->nr; i++) {
struct ff_reg *reg = regs->array + i;
- if (reg->negate ^ !!regexec(&reg->re,
- line_buffer, 2, pmatch, 0)) {
- free(line_buffer);
- return -1;
+ if (!regexec(&reg->re, line_buffer, 2, pmatch, 0)) {
+ if (reg->negate)
+ goto fail;
+ break;
}
}
+ if (regs->nr <= i)
+ goto fail;
i = pmatch[1].rm_so >= 0 ? 1 : 0;
line += pmatch[i].rm_so;
result = pmatch[i].rm_eo - pmatch[i].rm_so;
if (result > buffer_size)
result = buffer_size;
else
- while (result > 0 && (isspace(line[result - 1]) ||
- line[result - 1] == '\n'))
+ while (result > 0 && (isspace(line[result - 1])))
result--;
memcpy(buffer, line, result);
+ fail:
free(line_buffer);
return result;
}