diff --git a/cache.h b/cache.h
index ff4a7c2..5db89f9 100644
--- a/cache.h
+++ b/cache.h
@@ -1043,6 +1043,7 @@ extern void trace_argv_printf(const char **argv, const char *format, ...);
extern int convert_to_git(const char *path, const char *src, size_t len,
struct strbuf *dst, enum safe_crlf checksafe);
extern int convert_to_working_tree(const char *path, const char *src, size_t len, struct strbuf *dst);
+extern int renormalize_buffer(const char *path, const char *src, size_t len, struct strbuf *dst);
/* add */
/*diff --git a/convert.c b/convert.c
index e41a31e..e1561a9 100644
--- a/convert.c
+++ b/convert.c
@@ -693,7 +693,7 @@ static int git_path_check_ident(const char *path, struct git_attr_check *check)
return !!ATTR_TRUE(value);
}
-enum action determine_action(enum action text_attr, enum eol eol_attr) {
+static enum action determine_action(enum action text_attr, enum eol eol_attr) {
if (text_attr == CRLF_BINARY)
return CRLF_BINARY;
if (eol_attr == EOL_LF)@@ -773,3 +773,12 @@ int convert_to_working_tree(const char *path, const char *src, size_t len, struc
}
return ret | apply_filter(path, src, len, dst, filter);
}
+
+int renormalize_buffer(const char *path, const char *src, size_t len, struct strbuf *dst) {
+ int ret = convert_to_working_tree(path, src, len, dst);
+ if (ret) {
+ src = dst->buf;
+ len = dst->len;
+ }
+ return ret | convert_to_git(path, src, len, dst, 0);
+}diff --git a/ll-merge.c b/ll-merge.c
index 3764a1a..bdaa580 100644
--- a/ll-merge.c
+++ b/ll-merge.c
@@ -321,6 +321,15 @@ static int git_path_check_merge(const char *path, struct git_attr_check check[2]
return git_checkattr(path, 2, check);
}
+static void normalize_file(mmfile_t *mm, const char *path) {
+ struct strbuf strbuf = STRBUF_INIT;
+ if (renormalize_buffer(path, mm->ptr, mm->size, &strbuf)) {
+ free(mm->ptr);
+ mm->size = strbuf.len;
+ mm->ptr = strbuf_detach(&strbuf, NULL);
+ }
+}
+
int ll_merge(mmbuffer_t *result_buf,
const char *path,
mmfile_t *ancestor, const char *ancestor_label,@@ -334,6 +343,9 @@ int ll_merge(mmbuffer_t *result_buf,
const struct ll_merge_driver *driver;
int virtual_ancestor = flag & 01;
+ normalize_file(ancestor, path);
+ normalize_file(ours, path);
+ normalize_file(theirs, path);
if (!git_path_check_merge(path, check)) {
ll_driver_name = check[0].value;
if (check[1].value) {diff --git a/t/t6038-merge-text-auto.sh b/t/t6038-merge-text-auto.sh
new file mode 100755
index 0000000..44e6003
--- /dev/null
+++ b/t/t6038-merge-text-auto.sh
@@ -0,0 +1,58 @@
+#!/bin/sh
+
+test_description='CRLF merge conflict across text=auto change'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+ git config core.autocrlf false &&
+ echo first line | append_cr >file &&
+ git add file &&
+ git commit -m "Initial" &&
+ git tag initial &&
+ git branch side &&
+ echo "* text=auto" >.gitattributes &&
+ touch file &&
+ git add .gitattributes file &&
+ git commit -m "normalize file" &&
+ echo same line | append_cr >>file &&
+ git add file &&
+ git commit -m "add line from a" &&
+ git tag a &&
+ git rm .gitattributes &&
+ rm file &&
+ git checkout file &&
+ git commit -m "remove .gitattributes" &&
+ git tag c &&
+ git checkout side &&
+ echo same line | append_cr >>file &&
+ git commit -m "add line from b" file &&
+ git tag b &&
+ git checkout master
+'
+
+test_expect_success 'Check merging after setting text=auto' '
+ git reset --hard a &&
+ git merge b &&
+ cat file | remove_cr >file.temp &&
+ test_cmp file file.temp
+'
+
+test_expect_success 'Check merging addition of text=auto' '
+ git reset --hard b &&
+ git merge a &&
+ cat file | remove_cr >file.temp &&
+ test_cmp file file.temp
+'
+
+test_expect_failure 'Test delete/normalize conflict' '
+ git checkout side &&
+ git reset --hard initial &&
+ git rm file &&
+ git commit -m "remove file" &&
+ git checkout master &&
+ git reset --hard a^ &&
+ git merge side
+'
+
+test_done
--
1.7.1.575.g383de