Skip to content

Commit edb7e82

Browse files
committed
Merge branch 'bc/maint-diff-hunk-header-fix' into maint
* bc/maint-diff-hunk-header-fix: t4018-diff-funcname: test syntax of builtin xfuncname patterns diff hunk pattern: fix misconverted "\{" tex macro introducers diff: use extended regexp to find hunk headers diff.*.xfuncname which uses "extended" regex's for hunk header selection diff.c: associate a flag with each pattern and use it for compiling regex diff.c: return pattern entry pointer rather than just the hunk header pattern Conflicts: Documentation/gitattributes.txt
2 parents e9a06f1 + e3bf5e4 commit edb7e82

File tree

5 files changed

+72
-49
lines changed

5 files changed

+72
-49
lines changed

Documentation/gitattributes.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -288,13 +288,13 @@ for paths.
288288
*.tex diff=tex
289289
------------------------
290290

291-
Then, you would define a "diff.tex.funcname" configuration to
291+
Then, you would define a "diff.tex.xfuncname" configuration to
292292
specify a regular expression that matches a line that you would
293293
want to appear as the hunk header "TEXT", like this:
294294

295295
------------------------
296296
[diff "tex"]
297-
funcname = "^\\(\\\\\\(sub\\)*section{.*\\)$"
297+
xfuncname = "^(\\\\(sub)*section\\{.*)$"
298298
------------------------
299299

300300
Note. A single level of backslashes are eaten by the

diff.c

Lines changed: 55 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -94,32 +94,37 @@ static int parse_lldiff_command(const char *var, const char *ep, const char *val
9494
* to define a customized regexp to find the beginning of a function to
9595
* be used for hunk header lines of "diff -p" style output.
9696
*/
97-
static struct funcname_pattern {
97+
struct funcname_pattern_entry {
9898
char *name;
9999
char *pattern;
100-
struct funcname_pattern *next;
100+
int cflags;
101+
};
102+
static struct funcname_pattern_list {
103+
struct funcname_pattern_list *next;
104+
struct funcname_pattern_entry e;
101105
} *funcname_pattern_list;
102106

103-
static int parse_funcname_pattern(const char *var, const char *ep, const char *value)
107+
static int parse_funcname_pattern(const char *var, const char *ep, const char *value, int cflags)
104108
{
105109
const char *name;
106110
int namelen;
107-
struct funcname_pattern *pp;
111+
struct funcname_pattern_list *pp;
108112

109113
name = var + 5; /* "diff." */
110114
namelen = ep - name;
111115

112116
for (pp = funcname_pattern_list; pp; pp = pp->next)
113-
if (!strncmp(pp->name, name, namelen) && !pp->name[namelen])
117+
if (!strncmp(pp->e.name, name, namelen) && !pp->e.name[namelen])
114118
break;
115119
if (!pp) {
116120
pp = xcalloc(1, sizeof(*pp));
117-
pp->name = xmemdupz(name, namelen);
121+
pp->e.name = xmemdupz(name, namelen);
118122
pp->next = funcname_pattern_list;
119123
funcname_pattern_list = pp;
120124
}
121-
free(pp->pattern);
122-
pp->pattern = xstrdup(value);
125+
free(pp->e.pattern);
126+
pp->e.pattern = xstrdup(value);
127+
pp->e.cflags = cflags;
123128
return 0;
124129
}
125130

@@ -182,7 +187,13 @@ int git_diff_basic_config(const char *var, const char *value, void *cb)
182187
if (!strcmp(ep, ".funcname")) {
183188
if (!value)
184189
return config_error_nonbool(var);
185-
return parse_funcname_pattern(var, ep, value);
190+
return parse_funcname_pattern(var, ep, value,
191+
0);
192+
} else if (!strcmp(ep, ".xfuncname")) {
193+
if (!value)
194+
return config_error_nonbool(var);
195+
return parse_funcname_pattern(var, ep, value,
196+
REG_EXTENDED);
186197
}
187198
}
188199
}
@@ -1377,39 +1388,40 @@ int diff_filespec_is_binary(struct diff_filespec *one)
13771388
return one->is_binary;
13781389
}
13791390

1380-
static const char *funcname_pattern(const char *ident)
1391+
static const struct funcname_pattern_entry *funcname_pattern(const char *ident)
13811392
{
1382-
struct funcname_pattern *pp;
1393+
struct funcname_pattern_list *pp;
13831394

13841395
for (pp = funcname_pattern_list; pp; pp = pp->next)
1385-
if (!strcmp(ident, pp->name))
1386-
return pp->pattern;
1396+
if (!strcmp(ident, pp->e.name))
1397+
return &pp->e;
13871398
return NULL;
13881399
}
13891400

1390-
static struct builtin_funcname_pattern {
1391-
const char *name;
1392-
const char *pattern;
1393-
} builtin_funcname_pattern[] = {
1394-
{ "java", "!^[ ]*\\(catch\\|do\\|for\\|if\\|instanceof\\|"
1395-
"new\\|return\\|switch\\|throw\\|while\\)\n"
1396-
"^[ ]*\\(\\([ ]*"
1397-
"[A-Za-z_][A-Za-z_0-9]*\\)\\{2,\\}"
1398-
"[ ]*([^;]*\\)$" },
1399-
{ "pascal", "^\\(\\(procedure\\|function\\|constructor\\|"
1400-
"destructor\\|interface\\|implementation\\|"
1401-
"initialization\\|finalization\\)[ \t]*.*\\)$"
1402-
"\\|"
1403-
"^\\(.*=[ \t]*\\(class\\|record\\).*\\)$"
1404-
},
1405-
{ "bibtex", "\\(@[a-zA-Z]\\{1,\\}[ \t]*{\\{0,1\\}[ \t]*[^ \t\"@',\\#}{~%]*\\).*$" },
1406-
{ "tex", "^\\(\\\\\\(\\(sub\\)*section\\|chapter\\|part\\)\\*\\{0,1\\}{.*\\)$" },
1407-
{ "ruby", "^\\s*\\(\\(class\\|module\\|def\\)\\s.*\\)$" },
1401+
static const struct funcname_pattern_entry builtin_funcname_pattern[] = {
1402+
{ "java",
1403+
"!^[ \t]*(catch|do|for|if|instanceof|new|return|switch|throw|while)\n"
1404+
"^[ \t]*(([ \t]*[A-Za-z_][A-Za-z_0-9]*){2,}[ \t]*\\([^;]*)$",
1405+
REG_EXTENDED },
1406+
{ "pascal",
1407+
"^((procedure|function|constructor|destructor|interface|"
1408+
"implementation|initialization|finalization)[ \t]*.*)$"
1409+
"|"
1410+
"^(.*=[ \t]*(class|record).*)$",
1411+
REG_EXTENDED },
1412+
{ "bibtex", "(@[a-zA-Z]{1,}[ \t]*\\{{0,1}[ \t]*[^ \t\"@',\\#}{~%]*).*$",
1413+
REG_EXTENDED },
1414+
{ "tex",
1415+
"^(\\\\((sub)*section|chapter|part)\\*{0,1}\\{.*)$",
1416+
REG_EXTENDED },
1417+
{ "ruby", "^[ \t]*((class|module|def)[ \t].*)$",
1418+
REG_EXTENDED },
14081419
};
14091420

1410-
static const char *diff_funcname_pattern(struct diff_filespec *one)
1421+
static const struct funcname_pattern_entry *diff_funcname_pattern(struct diff_filespec *one)
14111422
{
1412-
const char *ident, *pattern;
1423+
const char *ident;
1424+
const struct funcname_pattern_entry *pe;
14131425
int i;
14141426

14151427
diff_filespec_check_attr(one);
@@ -1424,17 +1436,17 @@ static const char *diff_funcname_pattern(struct diff_filespec *one)
14241436
return funcname_pattern("default");
14251437

14261438
/* Look up custom "funcname.$ident" regexp from config. */
1427-
pattern = funcname_pattern(ident);
1428-
if (pattern)
1429-
return pattern;
1439+
pe = funcname_pattern(ident);
1440+
if (pe)
1441+
return pe;
14301442

14311443
/*
14321444
* And define built-in fallback patterns here. Note that
14331445
* these can be overridden by the user's config settings.
14341446
*/
14351447
for (i = 0; i < ARRAY_SIZE(builtin_funcname_pattern); i++)
14361448
if (!strcmp(ident, builtin_funcname_pattern[i].name))
1437-
return builtin_funcname_pattern[i].pattern;
1449+
return &builtin_funcname_pattern[i];
14381450

14391451
return NULL;
14401452
}
@@ -1512,11 +1524,11 @@ static void builtin_diff(const char *name_a,
15121524
xdemitconf_t xecfg;
15131525
xdemitcb_t ecb;
15141526
struct emit_callback ecbdata;
1515-
const char *funcname_pattern;
1527+
const struct funcname_pattern_entry *pe;
15161528

1517-
funcname_pattern = diff_funcname_pattern(one);
1518-
if (!funcname_pattern)
1519-
funcname_pattern = diff_funcname_pattern(two);
1529+
pe = diff_funcname_pattern(one);
1530+
if (!pe)
1531+
pe = diff_funcname_pattern(two);
15201532

15211533
memset(&xecfg, 0, sizeof(xecfg));
15221534
memset(&ecbdata, 0, sizeof(ecbdata));
@@ -1528,8 +1540,8 @@ static void builtin_diff(const char *name_a,
15281540
xpp.flags = XDF_NEED_MINIMAL | o->xdl_opts;
15291541
xecfg.ctxlen = o->context;
15301542
xecfg.flags = XDL_EMIT_FUNCNAMES;
1531-
if (funcname_pattern)
1532-
xdiff_set_find_func(&xecfg, funcname_pattern);
1543+
if (pe)
1544+
xdiff_set_find_func(&xecfg, pe->pattern, pe->cflags);
15331545
if (!diffopts)
15341546
;
15351547
else if (!prefixcmp(diffopts, "--unified="))

t/t4018-diff-funcname.sh

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,18 @@ EOF
3232

3333
sed 's/beer\\/beer,\\/' < Beer.java > Beer-correct.java
3434

35+
builtin_patterns="bibtex java pascal ruby tex"
36+
for p in $builtin_patterns
37+
do
38+
test_expect_success "builtin $p pattern compiles" '
39+
echo "*.java diff=$p" > .gitattributes &&
40+
! ( git diff --no-index Beer.java Beer-correct.java 2>&1 |
41+
grep "fatal" > /dev/null )
42+
'
43+
done
44+
3545
test_expect_success 'default behaviour' '
46+
rm -f .gitattributes &&
3647
git diff --no-index Beer.java Beer-correct.java |
3748
grep "^@@.*@@ public class Beer"
3849
'
@@ -58,7 +69,7 @@ test_expect_success 'last regexp must not be negated' '
5869
'
5970

6071
test_expect_success 'alternation in pattern' '
61-
git config diff.java.funcname "^[ ]*\\(\\(public\\|static\\).*\\)$"
72+
git config diff.java.xfuncname "^[ ]*((public|static).*)$" &&
6273
git diff --no-index Beer.java Beer-correct.java |
6374
grep "^@@.*@@ public static void main("
6475
'

xdiff-interface.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ static long ff_regexp(const char *line, long len,
206206
return result;
207207
}
208208

209-
void xdiff_set_find_func(xdemitconf_t *xecfg, const char *value)
209+
void xdiff_set_find_func(xdemitconf_t *xecfg, const char *value, int cflags)
210210
{
211211
int i;
212212
struct ff_regs *regs;
@@ -231,7 +231,7 @@ void xdiff_set_find_func(xdemitconf_t *xecfg, const char *value)
231231
expression = buffer = xstrndup(value, ep - value);
232232
else
233233
expression = value;
234-
if (regcomp(&reg->re, expression, 0))
234+
if (regcomp(&reg->re, expression, cflags))
235235
die("Invalid regexp to look for hunk header: %s", expression);
236236
free(buffer);
237237
value = ep + 1;

xdiff-interface.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,6 @@ int parse_hunk_header(char *line, int len,
2121
int read_mmfile(mmfile_t *ptr, const char *filename);
2222
int buffer_is_binary(const char *ptr, unsigned long size);
2323

24-
extern void xdiff_set_find_func(xdemitconf_t *xecfg, const char *line);
24+
extern void xdiff_set_find_func(xdemitconf_t *xecfg, const char *line, int cflags);
2525

2626
#endif

0 commit comments

Comments
 (0)