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