Skip to content

Commit 7b90ed5

Browse files
committed
Merge branch 'tr/maint-word-diff-regex-sticky' into maint
The regexp configured with diff.wordregex was incorrectly reused across files. By Thomas Rast (2) and Johannes Sixt (1) * tr/maint-word-diff-regex-sticky: diff: tweak a _copy_ of diff_options with word-diff diff: refactor the word-diff setup from builtin_diff_cmd t4034: diff.*.wordregex should not be "sticky" in --word-diff
2 parents 0584326 + 6440d34 commit 7b90ed5

File tree

2 files changed

+102
-56
lines changed

2 files changed

+102
-56
lines changed

diff.c

Lines changed: 66 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -989,10 +989,74 @@ static void diff_words_flush(struct emit_callback *ecbdata)
989989
diff_words_show(ecbdata->diff_words);
990990
}
991991

992+
static void diff_filespec_load_driver(struct diff_filespec *one)
993+
{
994+
/* Use already-loaded driver */
995+
if (one->driver)
996+
return;
997+
998+
if (S_ISREG(one->mode))
999+
one->driver = userdiff_find_by_path(one->path);
1000+
1001+
/* Fallback to default settings */
1002+
if (!one->driver)
1003+
one->driver = userdiff_find_by_name("default");
1004+
}
1005+
1006+
static const char *userdiff_word_regex(struct diff_filespec *one)
1007+
{
1008+
diff_filespec_load_driver(one);
1009+
return one->driver->word_regex;
1010+
}
1011+
1012+
static void init_diff_words_data(struct emit_callback *ecbdata,
1013+
struct diff_options *orig_opts,
1014+
struct diff_filespec *one,
1015+
struct diff_filespec *two)
1016+
{
1017+
int i;
1018+
struct diff_options *o = xmalloc(sizeof(struct diff_options));
1019+
memcpy(o, orig_opts, sizeof(struct diff_options));
1020+
1021+
ecbdata->diff_words =
1022+
xcalloc(1, sizeof(struct diff_words_data));
1023+
ecbdata->diff_words->type = o->word_diff;
1024+
ecbdata->diff_words->opt = o;
1025+
if (!o->word_regex)
1026+
o->word_regex = userdiff_word_regex(one);
1027+
if (!o->word_regex)
1028+
o->word_regex = userdiff_word_regex(two);
1029+
if (!o->word_regex)
1030+
o->word_regex = diff_word_regex_cfg;
1031+
if (o->word_regex) {
1032+
ecbdata->diff_words->word_regex = (regex_t *)
1033+
xmalloc(sizeof(regex_t));
1034+
if (regcomp(ecbdata->diff_words->word_regex,
1035+
o->word_regex,
1036+
REG_EXTENDED | REG_NEWLINE))
1037+
die ("Invalid regular expression: %s",
1038+
o->word_regex);
1039+
}
1040+
for (i = 0; i < ARRAY_SIZE(diff_words_styles); i++) {
1041+
if (o->word_diff == diff_words_styles[i].type) {
1042+
ecbdata->diff_words->style =
1043+
&diff_words_styles[i];
1044+
break;
1045+
}
1046+
}
1047+
if (want_color(o->use_color)) {
1048+
struct diff_words_style *st = ecbdata->diff_words->style;
1049+
st->old.color = diff_get_color_opt(o, DIFF_FILE_OLD);
1050+
st->new.color = diff_get_color_opt(o, DIFF_FILE_NEW);
1051+
st->ctx.color = diff_get_color_opt(o, DIFF_PLAIN);
1052+
}
1053+
}
1054+
9921055
static void free_diff_words_data(struct emit_callback *ecbdata)
9931056
{
9941057
if (ecbdata->diff_words) {
9951058
diff_words_flush(ecbdata);
1059+
free (ecbdata->diff_words->opt);
9961060
free (ecbdata->diff_words->minus.text.ptr);
9971061
free (ecbdata->diff_words->minus.orig);
9981062
free (ecbdata->diff_words->plus.text.ptr);
@@ -2061,20 +2125,6 @@ static void emit_binary_diff(FILE *file, mmfile_t *one, mmfile_t *two, char *pre
20612125
emit_binary_diff_body(file, two, one, prefix);
20622126
}
20632127

2064-
static void diff_filespec_load_driver(struct diff_filespec *one)
2065-
{
2066-
/* Use already-loaded driver */
2067-
if (one->driver)
2068-
return;
2069-
2070-
if (S_ISREG(one->mode))
2071-
one->driver = userdiff_find_by_path(one->path);
2072-
2073-
/* Fallback to default settings */
2074-
if (!one->driver)
2075-
one->driver = userdiff_find_by_name("default");
2076-
}
2077-
20782128
int diff_filespec_is_binary(struct diff_filespec *one)
20792129
{
20802130
if (one->is_binary == -1) {
@@ -2100,12 +2150,6 @@ static const struct userdiff_funcname *diff_funcname_pattern(struct diff_filespe
21002150
return one->driver->funcname.pattern ? &one->driver->funcname : NULL;
21012151
}
21022152

2103-
static const char *userdiff_word_regex(struct diff_filespec *one)
2104-
{
2105-
diff_filespec_load_driver(one);
2106-
return one->driver->word_regex;
2107-
}
2108-
21092153
void diff_set_mnemonic_prefix(struct diff_options *options, const char *a, const char *b)
21102154
{
21112155
if (!options->a_prefix)
@@ -2292,42 +2336,8 @@ static void builtin_diff(const char *name_a,
22922336
xecfg.ctxlen = strtoul(diffopts + 10, NULL, 10);
22932337
else if (!prefixcmp(diffopts, "-u"))
22942338
xecfg.ctxlen = strtoul(diffopts + 2, NULL, 10);
2295-
if (o->word_diff) {
2296-
int i;
2297-
2298-
ecbdata.diff_words =
2299-
xcalloc(1, sizeof(struct diff_words_data));
2300-
ecbdata.diff_words->type = o->word_diff;
2301-
ecbdata.diff_words->opt = o;
2302-
if (!o->word_regex)
2303-
o->word_regex = userdiff_word_regex(one);
2304-
if (!o->word_regex)
2305-
o->word_regex = userdiff_word_regex(two);
2306-
if (!o->word_regex)
2307-
o->word_regex = diff_word_regex_cfg;
2308-
if (o->word_regex) {
2309-
ecbdata.diff_words->word_regex = (regex_t *)
2310-
xmalloc(sizeof(regex_t));
2311-
if (regcomp(ecbdata.diff_words->word_regex,
2312-
o->word_regex,
2313-
REG_EXTENDED | REG_NEWLINE))
2314-
die ("Invalid regular expression: %s",
2315-
o->word_regex);
2316-
}
2317-
for (i = 0; i < ARRAY_SIZE(diff_words_styles); i++) {
2318-
if (o->word_diff == diff_words_styles[i].type) {
2319-
ecbdata.diff_words->style =
2320-
&diff_words_styles[i];
2321-
break;
2322-
}
2323-
}
2324-
if (want_color(o->use_color)) {
2325-
struct diff_words_style *st = ecbdata.diff_words->style;
2326-
st->old.color = diff_get_color_opt(o, DIFF_FILE_OLD);
2327-
st->new.color = diff_get_color_opt(o, DIFF_FILE_NEW);
2328-
st->ctx.color = diff_get_color_opt(o, DIFF_PLAIN);
2329-
}
2330-
}
2339+
if (o->word_diff)
2340+
init_diff_words_data(&ecbdata, o, one, two);
23312341
xdi_diff_outf(&mf1, &mf2, fn_out_consume, &ecbdata,
23322342
&xpp, &xecfg);
23332343
if (o->word_diff)

t/t4034-diff-words.sh

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
test_description='word diff colors'
44

55
. ./test-lib.sh
6+
. "$TEST_DIRECTORY"/diff-lib.sh
67

78
cat >pre.simple <<-\EOF
89
h(4)
@@ -293,6 +294,10 @@ test_expect_success '--word-diff=none' '
293294
word_diff --word-diff=plain --word-diff=none
294295
'
295296
297+
test_expect_success 'unset default driver' '
298+
test_unconfig diff.wordregex
299+
'
300+
296301
test_language_driver bibtex
297302
test_language_driver cpp
298303
test_language_driver csharp
@@ -348,4 +353,35 @@ test_expect_success 'word-diff with no newline at EOF' '
348353
word_diff --word-diff=plain
349354
'
350355
356+
test_expect_success 'setup history with two files' '
357+
echo "a b; c" >a.tex &&
358+
echo "a b; c" >z.txt &&
359+
git add a.tex z.txt &&
360+
git commit -minitial &&
361+
362+
# modify both
363+
echo "a bx; c" >a.tex &&
364+
echo "a bx; c" >z.txt &&
365+
git commit -mmodified -a
366+
'
367+
368+
test_expect_success 'wordRegex for the first file does not apply to the second' '
369+
echo "*.tex diff=tex" >.gitattributes &&
370+
git config diff.tex.wordRegex "[a-z]+|." &&
371+
cat >expect <<-\EOF &&
372+
diff --git a/a.tex b/a.tex
373+
--- a/a.tex
374+
+++ b/a.tex
375+
@@ -1 +1 @@
376+
a [-b-]{+bx+}; c
377+
diff --git a/z.txt b/z.txt
378+
--- a/z.txt
379+
+++ b/z.txt
380+
@@ -1 +1 @@
381+
a [-b;-]{+bx;+} c
382+
EOF
383+
git diff --word-diff HEAD~ >actual &&
384+
compare_diff_patch expect actual
385+
'
386+
351387
test_done

0 commit comments

Comments
 (0)