From 7c978a068f0575a90570e4579c71a5f641bdfad3 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Mon, 23 May 2011 16:16:41 -0400 Subject: combine-diff: split header printing into its own function This is a pretty big logical chunk, so it makes the function a bit more readable to have it split out. In addition, it will make it easier to add an alternate code path for binary diffs in a future patch. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- combine-diff.c | 135 +++++++++++++++++++++++++++++++-------------------------- 1 file changed, 74 insertions(+), 61 deletions(-) diff --git a/combine-diff.c b/combine-diff.c index 655fa89d8a..309dc6c272 100644 --- a/combine-diff.c +++ b/combine-diff.c @@ -681,6 +681,78 @@ static void dump_quoted_path(const char *head, puts(buf.buf); } +static void show_combined_header(struct combine_diff_path *elem, + int num_parent, + int dense, + struct rev_info *rev, + int mode_differs) +{ + struct diff_options *opt = &rev->diffopt; + int abbrev = DIFF_OPT_TST(opt, FULL_INDEX) ? 40 : DEFAULT_ABBREV; + const char *a_prefix = opt->a_prefix ? opt->a_prefix : "a/"; + const char *b_prefix = opt->b_prefix ? opt->b_prefix : "b/"; + int use_color = DIFF_OPT_TST(opt, COLOR_DIFF); + const char *c_meta = diff_get_color(use_color, DIFF_METAINFO); + const char *c_reset = diff_get_color(use_color, DIFF_RESET); + const char *abb; + int added = 0; + int deleted = 0; + int i; + + if (rev->loginfo && !rev->no_commit_id) + show_log(rev); + + dump_quoted_path(dense ? "diff --cc " : "diff --combined ", + "", elem->path, c_meta, c_reset); + printf("%sindex ", c_meta); + for (i = 0; i < num_parent; i++) { + abb = find_unique_abbrev(elem->parent[i].sha1, + abbrev); + printf("%s%s", i ? "," : "", abb); + } + abb = find_unique_abbrev(elem->sha1, abbrev); + printf("..%s%s\n", abb, c_reset); + + if (mode_differs) { + deleted = !elem->mode; + + /* We say it was added if nobody had it */ + added = !deleted; + for (i = 0; added && i < num_parent; i++) + if (elem->parent[i].status != + DIFF_STATUS_ADDED) + added = 0; + if (added) + printf("%snew file mode %06o", + c_meta, elem->mode); + else { + if (deleted) + printf("%sdeleted file ", c_meta); + printf("mode "); + for (i = 0; i < num_parent; i++) { + printf("%s%06o", i ? "," : "", + elem->parent[i].mode); + } + if (elem->mode) + printf("..%06o", elem->mode); + } + printf("%s\n", c_reset); + } + + if (added) + dump_quoted_path("--- ", "", "/dev/null", + c_meta, c_reset); + else + dump_quoted_path("--- ", a_prefix, elem->path, + c_meta, c_reset); + if (deleted) + dump_quoted_path("+++ ", "", "/dev/null", + c_meta, c_reset); + else + dump_quoted_path("+++ ", b_prefix, elem->path, + c_meta, c_reset); +} + static void show_patch_diff(struct combine_diff_path *elem, int num_parent, int dense, struct rev_info *rev) { @@ -692,13 +764,9 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent, int mode_differs = 0; int i, show_hunks; int working_tree_file = is_null_sha1(elem->sha1); - int abbrev = DIFF_OPT_TST(opt, FULL_INDEX) ? 40 : DEFAULT_ABBREV; - const char *a_prefix, *b_prefix; mmfile_t result_file; context = opt->context; - a_prefix = opt->a_prefix ? opt->a_prefix : "a/"; - b_prefix = opt->b_prefix ? opt->b_prefix : "b/"; /* Read the result of merge first */ if (!working_tree_file) @@ -832,63 +900,8 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent, show_hunks = make_hunks(sline, cnt, num_parent, dense); if (show_hunks || mode_differs || working_tree_file) { - const char *abb; - int use_color = DIFF_OPT_TST(opt, COLOR_DIFF); - const char *c_meta = diff_get_color(use_color, DIFF_METAINFO); - const char *c_reset = diff_get_color(use_color, DIFF_RESET); - int added = 0; - int deleted = 0; - - if (rev->loginfo && !rev->no_commit_id) - show_log(rev); - dump_quoted_path(dense ? "diff --cc " : "diff --combined ", - "", elem->path, c_meta, c_reset); - printf("%sindex ", c_meta); - for (i = 0; i < num_parent; i++) { - abb = find_unique_abbrev(elem->parent[i].sha1, - abbrev); - printf("%s%s", i ? "," : "", abb); - } - abb = find_unique_abbrev(elem->sha1, abbrev); - printf("..%s%s\n", abb, c_reset); - - if (mode_differs) { - deleted = !elem->mode; - - /* We say it was added if nobody had it */ - added = !deleted; - for (i = 0; added && i < num_parent; i++) - if (elem->parent[i].status != - DIFF_STATUS_ADDED) - added = 0; - if (added) - printf("%snew file mode %06o", - c_meta, elem->mode); - else { - if (deleted) - printf("%sdeleted file ", c_meta); - printf("mode "); - for (i = 0; i < num_parent; i++) { - printf("%s%06o", i ? "," : "", - elem->parent[i].mode); - } - if (elem->mode) - printf("..%06o", elem->mode); - } - printf("%s\n", c_reset); - } - if (added) - dump_quoted_path("--- ", "", "/dev/null", - c_meta, c_reset); - else - dump_quoted_path("--- ", a_prefix, elem->path, - c_meta, c_reset); - if (deleted) - dump_quoted_path("+++ ", "", "/dev/null", - c_meta, c_reset); - else - dump_quoted_path("+++ ", b_prefix, elem->path, - c_meta, c_reset); + show_combined_header(elem, num_parent, dense, rev, + mode_differs); dump_sline(sline, cnt, num_parent, DIFF_OPT_TST(opt, COLOR_DIFF), result_deleted); } -- cgit v1.2.3 From c95b99bb5d5f3aed88f8154371a813ebd0d2fa1d Mon Sep 17 00:00:00 2001 From: Jeff King Date: Mon, 23 May 2011 16:16:59 -0400 Subject: combine-diff: calculate mode_differs earlier One loop combined both the patch generation and checking whether there was any mode change to report. Let's factor that into two separate loops, as we may care about the mode change even if we are not generating patches (e.g., because we are showing a binary diff, which will come in a future patch). Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- combine-diff.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/combine-diff.c b/combine-diff.c index 309dc6c272..2183184eed 100644 --- a/combine-diff.c +++ b/combine-diff.c @@ -845,6 +845,13 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent, close(fd); } + for (i = 0; i < num_parent; i++) { + if (elem->parent[i].mode != elem->mode) { + mode_differs = 1; + break; + } + } + for (cnt = 0, cp = result; cp < result + result_size; cp++) { if (*cp == '\n') cnt++; @@ -893,8 +900,6 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent, elem->parent[i].mode, &result_file, sline, cnt, i, num_parent, result_deleted); - if (elem->parent[i].mode != elem->mode) - mode_differs = 1; } show_hunks = make_hunks(sline, cnt, num_parent, dense); -- cgit v1.2.3 From 4d5f34719970274990cded2201957eb2262bca10 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Mon, 23 May 2011 16:27:34 -0400 Subject: combine-diff: handle binary files as binary The combined diff code path is totally different from the regular diff code path, and didn't handle binary files at all. The results of a combined diff on a binary file could range from annoying (since we spewed binary garbage, possibly upsetting the user's terminal), to wrong (embedded NULs caused us to show incorrect diffs, with lines truncated at the NUL character), to potential security problems (embedded NULs could interfere with "-z" output, possibly defeating policy hooks which parse diff output). Instead, we consider a combined diff to be binary if any of the input blobs is binary. To show a binary combined diff, we indicate "Binary blobs differ"; the "index" meta line will show which parents had which blob. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- combine-diff.c | 37 ++++++++++++- t/t4048-diff-combined-binary.sh | 113 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 148 insertions(+), 2 deletions(-) create mode 100755 t/t4048-diff-combined-binary.sh diff --git a/combine-diff.c b/combine-diff.c index 2183184eed..94a207f477 100644 --- a/combine-diff.c +++ b/combine-diff.c @@ -7,6 +7,7 @@ #include "xdiff-interface.h" #include "log-tree.h" #include "refs.h" +#include "userdiff.h" static struct combine_diff_path *intersect_paths(struct combine_diff_path *curr, int n, int num_parent) { @@ -685,7 +686,8 @@ static void show_combined_header(struct combine_diff_path *elem, int num_parent, int dense, struct rev_info *rev, - int mode_differs) + int mode_differs, + int show_file_header) { struct diff_options *opt = &rev->diffopt; int abbrev = DIFF_OPT_TST(opt, FULL_INDEX) ? 40 : DEFAULT_ABBREV; @@ -739,6 +741,9 @@ static void show_combined_header(struct combine_diff_path *elem, printf("%s\n", c_reset); } + if (!show_file_header) + return; + if (added) dump_quoted_path("--- ", "", "/dev/null", c_meta, c_reset); @@ -765,8 +770,13 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent, int i, show_hunks; int working_tree_file = is_null_sha1(elem->sha1); mmfile_t result_file; + struct userdiff_driver *userdiff; + int is_binary; context = opt->context; + userdiff = userdiff_find_by_path(elem->path); + if (!userdiff) + userdiff = userdiff_find_by_name("default"); /* Read the result of merge first */ if (!working_tree_file) @@ -852,6 +862,29 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent, } } + if (userdiff->binary != -1) + is_binary = userdiff->binary; + else { + is_binary = buffer_is_binary(result, result_size); + for (i = 0; !is_binary && i < num_parent; i++) { + char *buf; + unsigned long size; + buf = grab_blob(elem->parent[i].sha1, + elem->parent[i].mode, + &size); + if (buffer_is_binary(buf, size)) + is_binary = 1; + free(buf); + } + } + if (is_binary) { + show_combined_header(elem, num_parent, dense, rev, + mode_differs, 0); + printf("Binary files differ\n"); + free(result); + return; + } + for (cnt = 0, cp = result; cp < result + result_size; cp++) { if (*cp == '\n') cnt++; @@ -906,7 +939,7 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent, if (show_hunks || mode_differs || working_tree_file) { show_combined_header(elem, num_parent, dense, rev, - mode_differs); + mode_differs, 1); dump_sline(sline, cnt, num_parent, DIFF_OPT_TST(opt, COLOR_DIFF), result_deleted); } diff --git a/t/t4048-diff-combined-binary.sh b/t/t4048-diff-combined-binary.sh new file mode 100755 index 0000000000..a943994b07 --- /dev/null +++ b/t/t4048-diff-combined-binary.sh @@ -0,0 +1,113 @@ +#!/bin/sh + +test_description='combined and merge diff handle binary files and textconv' +. ./test-lib.sh + +test_expect_success 'setup binary merge conflict' ' + echo oneQ1 | q_to_nul >binary && + git add binary && + git commit -m one && + echo twoQ2 | q_to_nul >binary && + git commit -a -m two && + git checkout -b branch-binary HEAD^ && + echo threeQ3 | q_to_nul >binary && + git commit -a -m three && + test_must_fail git merge master && + echo resolvedQhooray | q_to_nul >binary && + git commit -a -m resolved +' + +cat >expect <<'EOF' +resolved + +diff --git a/binary b/binary +index 7ea6ded..9563691 100644 +Binary files a/binary and b/binary differ +resolved + +diff --git a/binary b/binary +index 6197570..9563691 100644 +Binary files a/binary and b/binary differ +EOF +test_expect_success 'diff -m indicates binary-ness' ' + git show --format=%s -m >actual && + test_cmp expect actual +' + +cat >expect <<'EOF' +resolved + +diff --combined binary +index 7ea6ded,6197570..9563691 +Binary files differ +EOF +test_expect_success 'diff -c indicates binary-ness' ' + git show --format=%s -c >actual && + test_cmp expect actual +' + +cat >expect <<'EOF' +resolved + +diff --cc binary +index 7ea6ded,6197570..9563691 +Binary files differ +EOF +test_expect_success 'diff --cc indicates binary-ness' ' + git show --format=%s --cc >actual && + test_cmp expect actual +' + +test_expect_success 'setup non-binary with binary attribute' ' + git checkout master && + test_commit one text && + test_commit two text && + git checkout -b branch-text HEAD^ && + test_commit three text && + test_must_fail git merge master && + test_commit resolved text && + echo text -diff >.gitattributes +' + +cat >expect <<'EOF' +resolved + +diff --git a/text b/text +index 2bdf67a..2ab19ae 100644 +Binary files a/text and b/text differ +resolved + +diff --git a/text b/text +index f719efd..2ab19ae 100644 +Binary files a/text and b/text differ +EOF +test_expect_success 'diff -m respects binary attribute' ' + git show --format=%s -m >actual && + test_cmp expect actual +' + +cat >expect <<'EOF' +resolved + +diff --combined text +index 2bdf67a,f719efd..2ab19ae +Binary files differ +EOF +test_expect_success 'diff -c respects binary attribute' ' + git show --format=%s -c >actual && + test_cmp expect actual +' + +cat >expect <<'EOF' +resolved + +diff --cc text +index 2bdf67a,f719efd..2ab19ae +Binary files differ +EOF +test_expect_success 'diff --cc respects binary attribute' ' + git show --format=%s --cc >actual && + test_cmp expect actual +' + +test_done -- cgit v1.2.3 From 3813e69031d2df2702f50b9649fa2e40ea11e558 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Mon, 23 May 2011 16:30:14 -0400 Subject: refactor get_textconv to not require diff_filespec This function actually does two things: 1. Load the userdiff driver for the filespec. 2. Decide whether the driver has a textconv component, and initialize the textconv cache if applicable. Only part (1) requires the filespec object, and some callers may not have a filespec at all. So let's split them it into two functions, and put part (2) with the userdiff code, which is a better fit. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- diff.c | 14 +------------- userdiff.c | 17 +++++++++++++++++ userdiff.h | 2 ++ 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/diff.c b/diff.c index ba5f7aa217..3f538f5803 100644 --- a/diff.c +++ b/diff.c @@ -1976,19 +1976,7 @@ struct userdiff_driver *get_textconv(struct diff_filespec *one) return NULL; diff_filespec_load_driver(one); - if (!one->driver->textconv) - return NULL; - - if (one->driver->textconv_want_cache && !one->driver->textconv_cache) { - struct notes_cache *c = xmalloc(sizeof(*c)); - struct strbuf name = STRBUF_INIT; - - strbuf_addf(&name, "textconv/%s", one->driver->name); - notes_cache_init(c, name.buf, one->driver->textconv); - one->driver->textconv_cache = c; - } - - return one->driver; + return userdiff_get_textconv(one->driver); } static void builtin_diff(const char *name_a, diff --git a/userdiff.c b/userdiff.c index 1ff47977d5..5d62e795a2 100644 --- a/userdiff.c +++ b/userdiff.c @@ -267,3 +267,20 @@ struct userdiff_driver *userdiff_find_by_path(const char *path) return NULL; return userdiff_find_by_name(check.value); } + +struct userdiff_driver *userdiff_get_textconv(struct userdiff_driver *driver) +{ + if (!driver->textconv) + return NULL; + + if (driver->textconv_want_cache && !driver->textconv_cache) { + struct notes_cache *c = xmalloc(sizeof(*c)); + struct strbuf name = STRBUF_INIT; + + strbuf_addf(&name, "textconv/%s", driver->name); + notes_cache_init(c, name.buf, driver->textconv); + driver->textconv_cache = c; + } + + return driver; +} diff --git a/userdiff.h b/userdiff.h index 942d594950..4a7e78ffbc 100644 --- a/userdiff.h +++ b/userdiff.h @@ -23,4 +23,6 @@ int userdiff_config(const char *k, const char *v); struct userdiff_driver *userdiff_find_by_name(const char *name); struct userdiff_driver *userdiff_find_by_path(const char *path); +struct userdiff_driver *userdiff_get_textconv(struct userdiff_driver *driver); + #endif /* USERDIFF */ -- cgit v1.2.3 From 0508fe533dfe1b890f6a2d31ca42ba25466e8ff5 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Mon, 23 May 2011 16:31:05 -0400 Subject: combine-diff: respect textconv attributes When doing a combined diff, we did not respect textconv attributes at all. This generally lead to us printing "Binary files differ" when we could show a combined diff of the converted text. This patch converts file contents according to textconv attributes. The implementation is slightly ugly; because the textconv code is tightly linked with the diff_filespec code, we temporarily create a diff_filespec during conversion. In practice, though, this should not create a performance problem. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- combine-diff.c | 41 +++++++++++++---- t/t4048-diff-combined-binary.sh | 99 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 131 insertions(+), 9 deletions(-) diff --git a/combine-diff.c b/combine-diff.c index 94a207f477..be67cfcd45 100644 --- a/combine-diff.c +++ b/combine-diff.c @@ -93,7 +93,9 @@ struct sline { unsigned long *p_lno; }; -static char *grab_blob(const unsigned char *sha1, unsigned int mode, unsigned long *size) +static char *grab_blob(const unsigned char *sha1, unsigned int mode, + unsigned long *size, struct userdiff_driver *textconv, + const char *path) { char *blob; enum object_type type; @@ -106,6 +108,11 @@ static char *grab_blob(const unsigned char *sha1, unsigned int mode, unsigned lo /* deleted blob */ *size = 0; return xcalloc(1, 1); + } else if (textconv) { + struct diff_filespec *df = alloc_filespec(path); + fill_filespec(df, sha1, mode); + *size = fill_textconv(textconv, df, &blob); + free_filespec(df); } else { blob = read_sha1_file(sha1, &type, size); if (type != OBJ_BLOB) @@ -205,7 +212,9 @@ static void consume_line(void *state_, char *line, unsigned long len) static void combine_diff(const unsigned char *parent, unsigned int mode, mmfile_t *result_file, struct sline *sline, unsigned int cnt, int n, - int num_parent, int result_deleted) + int num_parent, int result_deleted, + struct userdiff_driver *textconv, + const char *path) { unsigned int p_lno, lno; unsigned long nmask = (1UL << n); @@ -218,7 +227,7 @@ static void combine_diff(const unsigned char *parent, unsigned int mode, if (result_deleted) return; /* result deleted */ - parent_file.ptr = grab_blob(parent, mode, &sz); + parent_file.ptr = grab_blob(parent, mode, &sz, textconv, path); parent_file.size = sz; memset(&xpp, 0, sizeof(xpp)); xpp.flags = 0; @@ -771,16 +780,20 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent, int working_tree_file = is_null_sha1(elem->sha1); mmfile_t result_file; struct userdiff_driver *userdiff; + struct userdiff_driver *textconv = NULL; int is_binary; context = opt->context; userdiff = userdiff_find_by_path(elem->path); if (!userdiff) userdiff = userdiff_find_by_name("default"); + if (DIFF_OPT_TST(opt, ALLOW_TEXTCONV)) + textconv = userdiff_get_textconv(userdiff); /* Read the result of merge first */ if (!working_tree_file) - result = grab_blob(elem->sha1, elem->mode, &result_size); + result = grab_blob(elem->sha1, elem->mode, &result_size, + textconv, elem->path); else { /* Used by diff-tree to read from the working tree */ struct stat st; @@ -803,9 +816,16 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent, } else if (S_ISDIR(st.st_mode)) { unsigned char sha1[20]; if (resolve_gitlink_ref(elem->path, "HEAD", sha1) < 0) - result = grab_blob(elem->sha1, elem->mode, &result_size); + result = grab_blob(elem->sha1, elem->mode, + &result_size, NULL, NULL); else - result = grab_blob(sha1, elem->mode, &result_size); + result = grab_blob(sha1, elem->mode, + &result_size, NULL, NULL); + } else if (textconv) { + struct diff_filespec *df = alloc_filespec(elem->path); + fill_filespec(df, null_sha1, st.st_mode); + result_size = fill_textconv(textconv, df, &result); + free_filespec(df); } else if (0 <= (fd = open(elem->path, O_RDONLY))) { size_t len = xsize_t(st.st_size); ssize_t done; @@ -862,7 +882,9 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent, } } - if (userdiff->binary != -1) + if (textconv) + is_binary = 0; + else if (userdiff->binary != -1) is_binary = userdiff->binary; else { is_binary = buffer_is_binary(result, result_size); @@ -871,7 +893,7 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent, unsigned long size; buf = grab_blob(elem->parent[i].sha1, elem->parent[i].mode, - &size); + &size, NULL, NULL); if (buffer_is_binary(buf, size)) is_binary = 1; free(buf); @@ -932,7 +954,8 @@ static void show_patch_diff(struct combine_diff_path *elem, int num_parent, combine_diff(elem->parent[i].sha1, elem->parent[i].mode, &result_file, sline, - cnt, i, num_parent, result_deleted); + cnt, i, num_parent, result_deleted, + textconv, elem->path); } show_hunks = make_hunks(sline, cnt, num_parent, dense); diff --git a/t/t4048-diff-combined-binary.sh b/t/t4048-diff-combined-binary.sh index a943994b07..87a8949500 100755 --- a/t/t4048-diff-combined-binary.sh +++ b/t/t4048-diff-combined-binary.sh @@ -110,4 +110,103 @@ test_expect_success 'diff --cc respects binary attribute' ' test_cmp expect actual ' +test_expect_success 'setup textconv attribute' ' + echo "text diff=upcase" >.gitattributes && + git config diff.upcase.textconv "tr a-z A-Z <" +' + +cat >expect <<'EOF' +resolved + +diff --git a/text b/text +index 2bdf67a..2ab19ae 100644 +--- a/text ++++ b/text +@@ -1 +1 @@ +-THREE ++RESOLVED +resolved + +diff --git a/text b/text +index f719efd..2ab19ae 100644 +--- a/text ++++ b/text +@@ -1 +1 @@ +-TWO ++RESOLVED +EOF +test_expect_success 'diff -m respects textconv attribute' ' + git show --format=%s -m >actual && + test_cmp expect actual +' + +cat >expect <<'EOF' +resolved + +diff --combined text +index 2bdf67a,f719efd..2ab19ae +--- a/text ++++ b/text +@@@ -1,1 -1,1 +1,1 @@@ +- THREE + -TWO +++RESOLVED +EOF +test_expect_success 'diff -c respects textconv attribute' ' + git show --format=%s -c >actual && + test_cmp expect actual +' + +cat >expect <<'EOF' +resolved + +diff --cc text +index 2bdf67a,f719efd..2ab19ae +--- a/text ++++ b/text +@@@ -1,1 -1,1 +1,1 @@@ +- THREE + -TWO +++RESOLVED +EOF +test_expect_success 'diff --cc respects textconv attribute' ' + git show --format=%s --cc >actual && + test_cmp expect actual +' + +cat >expect <<'EOF' +diff --combined text +index 2bdf67a,f719efd..2ab19ae +--- a/text ++++ b/text +@@@ -1,1 -1,1 +1,1 @@@ +- three + -two +++resolved +EOF +test_expect_success 'diff-tree plumbing does not respect textconv' ' + git diff-tree HEAD -c -p >full && + tail -n +2 full >actual && + test_cmp expect actual +' + +cat >expect <<'EOF' +diff --cc text +index 2bdf67a,f719efd..0000000 +--- a/text ++++ b/text +@@@ -1,1 -1,1 +1,5 @@@ +++<<<<<<< HEAD + +THREE +++======= ++ TWO +++>>>>>>> MASTER +EOF +test_expect_success 'diff --cc respects textconv on worktree file' ' + git reset --hard HEAD^ && + test_must_fail git merge master && + git diff >actual && + test_cmp expect actual +' + test_done -- cgit v1.2.3