Skip to content

Commit 3d8dccd

Browse files
committed
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>
1 parent 1883a0d commit 3d8dccd

File tree

2 files changed

+11
-8
lines changed

2 files changed

+11
-8
lines changed

diff.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1414,7 +1414,7 @@ static const struct funcname_pattern_entry builtin_funcname_pattern[] = {
14141414
{ "pascal",
14151415
"^((procedure|function|constructor|destructor|interface|"
14161416
"implementation|initialization|finalization)[ \t]*.*)$"
1417-
"|"
1417+
"\n"
14181418
"^(.*=[ \t]*(class|record).*)$",
14191419
REG_EXTENDED },
14201420
{ "php", "^[\t ]*((function|class).*)", REG_EXTENDED },

xdiff-interface.c

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -194,26 +194,29 @@ static long ff_regexp(const char *line, long len,
194194
char *line_buffer = xstrndup(line, len); /* make NUL terminated */
195195
struct ff_regs *regs = priv;
196196
regmatch_t pmatch[2];
197-
int result = 0, i;
197+
int i;
198+
int result = -1;
198199

199200
for (i = 0; i < regs->nr; i++) {
200201
struct ff_reg *reg = regs->array + i;
201-
if (reg->negate ^ !!regexec(&reg->re,
202-
line_buffer, 2, pmatch, 0)) {
203-
free(line_buffer);
204-
return -1;
202+
if (!regexec(&reg->re, line_buffer, 2, pmatch, 0)) {
203+
if (reg->negate)
204+
goto fail;
205+
break;
205206
}
206207
}
208+
if (regs->nr <= i)
209+
goto fail;
207210
i = pmatch[1].rm_so >= 0 ? 1 : 0;
208211
line += pmatch[i].rm_so;
209212
result = pmatch[i].rm_eo - pmatch[i].rm_so;
210213
if (result > buffer_size)
211214
result = buffer_size;
212215
else
213-
while (result > 0 && (isspace(line[result - 1]) ||
214-
line[result - 1] == '\n'))
216+
while (result > 0 && (isspace(line[result - 1])))
215217
result--;
216218
memcpy(buffer, line, result);
219+
fail:
217220
free(line_buffer);
218221
return result;
219222
}

0 commit comments

Comments
 (0)