@matheusbsbs / matheus-bagliano / commits / 3aa1f7ca37
Fork 0

diff: respect textconv in rewrite diffs

Currently we just skip rewrite diffs for binary files; this patch makes an exception for files which will be textconv'd, and actually performs the textconv before generating the diff. Conceptually, rewrite diffs should be in the exact same format as the a non-rewrite diff, except that we refuse to share any context. Thus it makes very little sense for "git diff" to show a textconv'd diff, but for "git diff -B" to show "Binary files differ". Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jeff King committed Dec 9, 2008 at 03:13 UTC 3aa1f7ca3779f73164b285c070b71abcdd7397c1
2 files changed +59 -13
diff.c
+36 -12
@@ -229,6 +229,8 @@ static void emit_rewrite_diff(const char *name_a,
229 const char *name_b,
230 struct diff_filespec *one,
231 struct diff_filespec *two,
232 + const char *textconv_one,
233 + const char *textconv_two,
234 struct diff_options *o)
235 {
236 int lc_a, lc_b;
@@ -241,6 +243,8 @@ static void emit_rewrite_diff(const char *name_a,
243 const char *reset = diff_get_color(color_diff, DIFF_RESET);
244 static struct strbuf a_name = STRBUF_INIT, b_name = STRBUF_INIT;
245 const char *a_prefix, *b_prefix;
246 + const char *data_one, *data_two;
247 + size_t size_one, size_two;
248
249 if (diff_mnemonic_prefix && DIFF_OPT_TST(o, REVERSE_DIFF)) {
250 a_prefix = o->b_prefix;
@@ -262,8 +266,27 @@ static void emit_rewrite_diff(const char *name_a,
266
267 diff_populate_filespec(one, 0);
268 diff_populate_filespec(two, 0);
265 - lc_a = count_lines(one->data, one->size);
266 - lc_b = count_lines(two->data, two->size);
269 + if (textconv_one) {
270 + data_one = run_textconv(textconv_one, one, &size_one);
271 + if (!data_one)
272 + die("unable to read files to diff");
273 + }
274 + else {
275 + data_one = one->data;
276 + size_one = one->size;
277 + }
278 + if (textconv_two) {
279 + data_two = run_textconv(textconv_two, two, &size_two);
280 + if (!data_two)
281 + die("unable to read files to diff");
282 + }
283 + else {
284 + data_two = two->data;
285 + size_two = two->size;
286 + }
287 +
288 + lc_a = count_lines(data_one, size_one);
289 + lc_b = count_lines(data_two, size_two);
290 fprintf(o->file,
291 "%s--- %s%s%s\n%s+++ %s%s%s\n%s@@ -",
292 metainfo, a_name.buf, name_a_tab, reset,
@@ -273,9 +296,9 @@ static void emit_rewrite_diff(const char *name_a,
296 print_line_count(o->file, lc_b);
297 fprintf(o->file, " @@%s\n", reset);
298 if (lc_a)
276 - copy_file_with_prefix(o->file, '-', one->data, one->size, old, reset);
299 + copy_file_with_prefix(o->file, '-', data_one, size_one, old, reset);
300 if (lc_b)
278 - copy_file_with_prefix(o->file, '+', two->data, two->size, new, reset);
301 + copy_file_with_prefix(o->file, '+', data_two, size_two, new, reset);
302 }
303
304 static int fill_mmfile(mmfile_t *mf, struct diff_filespec *one)
@@ -1334,6 +1357,11 @@ static void builtin_diff(const char *name_a,
1357 const char *a_prefix, *b_prefix;
1358 const char *textconv_one = NULL, *textconv_two = NULL;
1359
1360 + if (DIFF_OPT_TST(o, ALLOW_TEXTCONV)) {
1361 + textconv_one = get_textconv(one);
1362 + textconv_two = get_textconv(two);
1363 + }
1364 +
1365 diff_set_mnemonic_prefix(o, "a/", "b/");
1366 if (DIFF_OPT_TST(o, REVERSE_DIFF)) {
1367 a_prefix = o->b_prefix;
@@ -1377,9 +1405,10 @@ static void builtin_diff(const char *name_a,
1405 if ((one->mode ^ two->mode) & S_IFMT)
1406 goto free_ab_and_return;
1407 if (complete_rewrite &&
1380 - !diff_filespec_is_binary(one) &&
1381 - !diff_filespec_is_binary(two)) {
1382 - emit_rewrite_diff(name_a, name_b, one, two, o);
1408 + (textconv_one || !diff_filespec_is_binary(one)) &&
1409 + (textconv_two || !diff_filespec_is_binary(two))) {
1410 + emit_rewrite_diff(name_a, name_b, one, two,
1411 + textconv_one, textconv_two, o);
1412 o->found_changes = 1;
1413 goto free_ab_and_return;
1414 }
@@ -1388,11 +1417,6 @@ static void builtin_diff(const char *name_a,
1417 if (fill_mmfile(&mf1, one) < 0 || fill_mmfile(&mf2, two) < 0)
1418 die("unable to read files to diff");
1419
1391 - if (DIFF_OPT_TST(o, ALLOW_TEXTCONV)) {
1392 - textconv_one = get_textconv(one);
1393 - textconv_two = get_textconv(two);
1394 - }
1395 -
1420 if (!DIFF_OPT_TST(o, TEXT) &&
1421 ( (diff_filespec_is_binary(one) && !textconv_one) ||
1422 (diff_filespec_is_binary(two) && !textconv_two) )) {
t/t4031-diff-rewrite-binary.sh
+23 -1
@@ -7,6 +7,8 @@ test_description='rewrite diff on binary file'
7 # We must be large enough to meet the MINIMUM_BREAK_SIZE
8 # requirement.
9 make_file() {
10 + # common first line to help identify rewrite versus regular diff
11 + printf "=\n" >file
12 for i in 1 2 3 4 5 6 7 8 9 10
13 do
14 for j in 1 2 3 4 5 6 7 8 9
@@ -16,7 +18,7 @@ make_file() {
18 printf "$1\n"
19 done
20 done
19 - done >file
21 + done >>file
22 }
23
24 test_expect_success 'create binary file with changes' '
@@ -42,4 +44,24 @@ test_expect_success 'rewrite diff can show binary patch' '
44 grep "GIT binary patch" diff
45 '
46
47 +{
48 + echo "#!$SHELL_PATH"
49 + cat >dump <<'EOF'
50 +perl -e '$/ = undef; $_ = <>; s/./ord($&)/ge; print $_' < "$1"
51 +EOF
52 +} >dump
53 +chmod +x dump
54 +
55 +test_expect_success 'setup textconv' '
56 + echo file diff=foo >.gitattributes &&
57 + git config diff.foo.textconv "$PWD"/dump
58 +'
59 +
60 +test_expect_success 'rewrite diff respects textconv' '
61 + git diff -B >diff &&
62 + grep "dissimilarity index" diff &&
63 + grep "^-61" diff &&
64 + grep "^-0" diff
65 +'
66 +
67 test_done