Skip to content

Commit

Permalink
Merge branch 'tr/maint-word-diff-regex-sticky' into maint
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Junio C Hamano committed Apr 26, 2012
2 parents 0584326 + 6440d34 commit 7b90ed5
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 56 deletions.
122 changes: 66 additions & 56 deletions diff.c
Original file line number Diff line number Diff line change
Expand Up @@ -989,10 +989,74 @@ static void diff_words_flush(struct emit_callback *ecbdata)
diff_words_show(ecbdata->diff_words);
}

static void diff_filespec_load_driver(struct diff_filespec *one)
{
/* Use already-loaded driver */
if (one->driver)
return;

if (S_ISREG(one->mode))
one->driver = userdiff_find_by_path(one->path);

/* Fallback to default settings */
if (!one->driver)
one->driver = userdiff_find_by_name("default");
}

static const char *userdiff_word_regex(struct diff_filespec *one)
{
diff_filespec_load_driver(one);
return one->driver->word_regex;
}

static void init_diff_words_data(struct emit_callback *ecbdata,
struct diff_options *orig_opts,
struct diff_filespec *one,
struct diff_filespec *two)
{
int i;
struct diff_options *o = xmalloc(sizeof(struct diff_options));
memcpy(o, orig_opts, sizeof(struct diff_options));

ecbdata->diff_words =
xcalloc(1, sizeof(struct diff_words_data));
ecbdata->diff_words->type = o->word_diff;
ecbdata->diff_words->opt = o;
if (!o->word_regex)
o->word_regex = userdiff_word_regex(one);
if (!o->word_regex)
o->word_regex = userdiff_word_regex(two);
if (!o->word_regex)
o->word_regex = diff_word_regex_cfg;
if (o->word_regex) {
ecbdata->diff_words->word_regex = (regex_t *)
xmalloc(sizeof(regex_t));
if (regcomp(ecbdata->diff_words->word_regex,
o->word_regex,
REG_EXTENDED | REG_NEWLINE))
die ("Invalid regular expression: %s",
o->word_regex);
}
for (i = 0; i < ARRAY_SIZE(diff_words_styles); i++) {
if (o->word_diff == diff_words_styles[i].type) {
ecbdata->diff_words->style =
&diff_words_styles[i];
break;
}
}
if (want_color(o->use_color)) {
struct diff_words_style *st = ecbdata->diff_words->style;
st->old.color = diff_get_color_opt(o, DIFF_FILE_OLD);
st->new.color = diff_get_color_opt(o, DIFF_FILE_NEW);
st->ctx.color = diff_get_color_opt(o, DIFF_PLAIN);
}
}

static void free_diff_words_data(struct emit_callback *ecbdata)
{
if (ecbdata->diff_words) {
diff_words_flush(ecbdata);
free (ecbdata->diff_words->opt);
free (ecbdata->diff_words->minus.text.ptr);
free (ecbdata->diff_words->minus.orig);
free (ecbdata->diff_words->plus.text.ptr);
Expand Down Expand Up @@ -2061,20 +2125,6 @@ static void emit_binary_diff(FILE *file, mmfile_t *one, mmfile_t *two, char *pre
emit_binary_diff_body(file, two, one, prefix);
}

static void diff_filespec_load_driver(struct diff_filespec *one)
{
/* Use already-loaded driver */
if (one->driver)
return;

if (S_ISREG(one->mode))
one->driver = userdiff_find_by_path(one->path);

/* Fallback to default settings */
if (!one->driver)
one->driver = userdiff_find_by_name("default");
}

int diff_filespec_is_binary(struct diff_filespec *one)
{
if (one->is_binary == -1) {
Expand All @@ -2100,12 +2150,6 @@ static const struct userdiff_funcname *diff_funcname_pattern(struct diff_filespe
return one->driver->funcname.pattern ? &one->driver->funcname : NULL;
}

static const char *userdiff_word_regex(struct diff_filespec *one)
{
diff_filespec_load_driver(one);
return one->driver->word_regex;
}

void diff_set_mnemonic_prefix(struct diff_options *options, const char *a, const char *b)
{
if (!options->a_prefix)
Expand Down Expand Up @@ -2292,42 +2336,8 @@ static void builtin_diff(const char *name_a,
xecfg.ctxlen = strtoul(diffopts + 10, NULL, 10);
else if (!prefixcmp(diffopts, "-u"))
xecfg.ctxlen = strtoul(diffopts + 2, NULL, 10);
if (o->word_diff) {
int i;

ecbdata.diff_words =
xcalloc(1, sizeof(struct diff_words_data));
ecbdata.diff_words->type = o->word_diff;
ecbdata.diff_words->opt = o;
if (!o->word_regex)
o->word_regex = userdiff_word_regex(one);
if (!o->word_regex)
o->word_regex = userdiff_word_regex(two);
if (!o->word_regex)
o->word_regex = diff_word_regex_cfg;
if (o->word_regex) {
ecbdata.diff_words->word_regex = (regex_t *)
xmalloc(sizeof(regex_t));
if (regcomp(ecbdata.diff_words->word_regex,
o->word_regex,
REG_EXTENDED | REG_NEWLINE))
die ("Invalid regular expression: %s",
o->word_regex);
}
for (i = 0; i < ARRAY_SIZE(diff_words_styles); i++) {
if (o->word_diff == diff_words_styles[i].type) {
ecbdata.diff_words->style =
&diff_words_styles[i];
break;
}
}
if (want_color(o->use_color)) {
struct diff_words_style *st = ecbdata.diff_words->style;
st->old.color = diff_get_color_opt(o, DIFF_FILE_OLD);
st->new.color = diff_get_color_opt(o, DIFF_FILE_NEW);
st->ctx.color = diff_get_color_opt(o, DIFF_PLAIN);
}
}
if (o->word_diff)
init_diff_words_data(&ecbdata, o, one, two);
xdi_diff_outf(&mf1, &mf2, fn_out_consume, &ecbdata,
&xpp, &xecfg);
if (o->word_diff)
Expand Down
36 changes: 36 additions & 0 deletions t/t4034-diff-words.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
test_description='word diff colors'

. ./test-lib.sh
. "$TEST_DIRECTORY"/diff-lib.sh

cat >pre.simple <<-\EOF
h(4)
Expand Down Expand Up @@ -293,6 +294,10 @@ test_expect_success '--word-diff=none' '
word_diff --word-diff=plain --word-diff=none
'
test_expect_success 'unset default driver' '
test_unconfig diff.wordregex
'
test_language_driver bibtex
test_language_driver cpp
test_language_driver csharp
Expand Down Expand Up @@ -348,4 +353,35 @@ test_expect_success 'word-diff with no newline at EOF' '
word_diff --word-diff=plain
'
test_expect_success 'setup history with two files' '
echo "a b; c" >a.tex &&
echo "a b; c" >z.txt &&
git add a.tex z.txt &&
git commit -minitial &&

# modify both
echo "a bx; c" >a.tex &&
echo "a bx; c" >z.txt &&
git commit -mmodified -a
'
test_expect_success 'wordRegex for the first file does not apply to the second' '
echo "*.tex diff=tex" >.gitattributes &&
git config diff.tex.wordRegex "[a-z]+|." &&
cat >expect <<-\EOF &&
diff --git a/a.tex b/a.tex
--- a/a.tex
+++ b/a.tex
@@ -1 +1 @@
a [-b-]{+bx+}; c
diff --git a/z.txt b/z.txt
--- a/z.txt
+++ b/z.txt
@@ -1 +1 @@
a [-b;-]{+bx;+} c
EOF
git diff --word-diff HEAD~ >actual &&
compare_diff_patch expect actual
'
test_done

0 comments on commit 7b90ed5

Please sign in to comment.