summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Martín Nieto <cmn@dwim.me>2014-06-19 11:45:46 +0200
committerCarlos Martín Nieto <cmn@dwim.me>2014-06-23 22:27:12 +0200
commit5a76ad35aaf709503dfc939464715666919180f8 (patch)
tree21a04047450efad085963790e081540cfb1e3614
parent1589aa0c4d48fb130d8a5db28c45cd3d173cde6d (diff)
downloadlibgit2-cmn/mixed-eol-passthrough.tar.gz
crlf: pass-through mixed EOL buffers from LF->CRLFcmn/mixed-eol-passthrough
When checking out files, we're performing conversion into the user's native line endings, but we only want to do it for files which have consistent line endings. Refuse to perform the conversion for mixed-EOL files. The CRLF->LF filter is left as-is, as that conversion is considered to be normalization by git and should force a conversion of the line endings.
-rw-r--r--src/buf_text.c14
-rw-r--r--src/buf_text.h5
-rw-r--r--tests/checkout/crlf.c10
-rw-r--r--tests/core/buffer.c26
4 files changed, 22 insertions, 33 deletions
diff --git a/src/buf_text.c b/src/buf_text.c
index 631feb3f8..8d2b141b2 100644
--- a/src/buf_text.c
+++ b/src/buf_text.c
@@ -123,9 +123,13 @@ int git_buf_text_lf_to_crlf(git_buf *tgt, const git_buf *src)
for (; next; scan = next + 1, next = memchr(scan, '\n', end - scan)) {
size_t copylen = next - scan;
- /* don't convert existing \r\n to \r\r\n */
- size_t extralen = (next > start && next[-1] == '\r') ? 1 : 2;
- size_t needsize = tgt->size + copylen + extralen + 1;
+ size_t needsize = tgt->size + copylen + 2 + 1;
+
+ /* if we find mixed line endings, bail */
+ if (next > start && next[-1] == '\r') {
+ git_buf_free(tgt);
+ return GIT_PASSTHROUGH;
+ }
if (tgt->asize < needsize && git_buf_grow(tgt, needsize) < 0)
return -1;
@@ -134,8 +138,8 @@ int git_buf_text_lf_to_crlf(git_buf *tgt, const git_buf *src)
memcpy(tgt->ptr + tgt->size, scan, copylen);
tgt->size += copylen;
}
- if (extralen == 2)
- tgt->ptr[tgt->size++] = '\r';
+
+ tgt->ptr[tgt->size++] = '\r';
tgt->ptr[tgt->size++] = '\n';
}
diff --git a/src/buf_text.h b/src/buf_text.h
index 3ac9d1443..e753a0244 100644
--- a/src/buf_text.h
+++ b/src/buf_text.h
@@ -56,9 +56,10 @@ GIT_INLINE(int) git_buf_text_puts_escape_regex(git_buf *buf, const char *string)
extern void git_buf_text_unescape(git_buf *buf);
/**
- * Replace all \r\n with \n. Does not modify \r without trailing \n.
+ * Replace all \r\n with \n.
*
- * @return 0 on success, -1 on memory error
+ * @return 0 on success, -1 on memory error, GIT_PASSTHROUGH if the
+ * source buffer has mixed line endings.
*/
extern int git_buf_text_crlf_to_lf(git_buf *tgt, const git_buf *src);
diff --git a/tests/checkout/crlf.c b/tests/checkout/crlf.c
index 6b2c1b122..2c84a77f3 100644
--- a/tests/checkout/crlf.c
+++ b/tests/checkout/crlf.c
@@ -79,10 +79,7 @@ void test_checkout_crlf__more_lf_autocrlf_true(void)
git_checkout_head(g_repo, &opts);
- if (GIT_EOL_NATIVE == GIT_EOL_LF)
- check_file_contents("./crlf/more-lf", MORE_LF_TEXT_RAW);
- else
- check_file_contents("./crlf/more-lf", MORE_LF_TEXT_AS_CRLF);
+ check_file_contents("./crlf/more-lf", MORE_LF_TEXT_RAW);
}
void test_checkout_crlf__more_crlf_autocrlf_true(void)
@@ -94,10 +91,7 @@ void test_checkout_crlf__more_crlf_autocrlf_true(void)
git_checkout_head(g_repo, &opts);
- if (GIT_EOL_NATIVE == GIT_EOL_LF)
- check_file_contents("./crlf/more-crlf", MORE_CRLF_TEXT_RAW);
- else
- check_file_contents("./crlf/more-crlf", MORE_CRLF_TEXT_AS_CRLF);
+ check_file_contents("./crlf/more-crlf", MORE_CRLF_TEXT_RAW);
}
void test_checkout_crlf__all_crlf_autocrlf_true(void)
diff --git a/tests/core/buffer.c b/tests/core/buffer.c
index da5ec605c..8310deae1 100644
--- a/tests/core/buffer.c
+++ b/tests/core/buffer.c
@@ -1034,18 +1034,14 @@ void test_core_buffer__lf_and_crlf_conversions(void)
git_buf_sets(&src, "crlf\r\ncrlf\r\ncrlf\r\ncrlf\r\n");
- cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src));
- check_buf("crlf\r\ncrlf\r\ncrlf\r\ncrlf\r\n", tgt);
- check_buf(src.ptr, tgt);
+ cl_git_fail_with(GIT_PASSTHROUGH, git_buf_text_lf_to_crlf(&tgt, &src));
cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src));
check_buf("crlf\ncrlf\ncrlf\ncrlf\n", tgt);
git_buf_sets(&src, "\r\ncrlf\r\ncrlf\r\ncrlf\r\ncrlf\r\ncrlf");
- cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src));
- check_buf("\r\ncrlf\r\ncrlf\r\ncrlf\r\ncrlf\r\ncrlf", tgt);
- check_buf(src.ptr, tgt);
+ cl_git_fail_with(GIT_PASSTHROUGH, git_buf_text_lf_to_crlf(&tgt, &src));
cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src));
check_buf("\ncrlf\ncrlf\ncrlf\ncrlf\ncrlf", tgt);
@@ -1054,8 +1050,7 @@ void test_core_buffer__lf_and_crlf_conversions(void)
git_buf_sets(&src, "\nlf\nlf\ncrlf\r\nlf\nlf\ncrlf\r\n");
- cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src));
- check_buf("\r\nlf\r\nlf\r\ncrlf\r\nlf\r\nlf\r\ncrlf\r\n", tgt);
+ cl_git_fail_with(GIT_PASSTHROUGH, git_buf_text_lf_to_crlf(&tgt, &src));
cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src));
check_buf("\nlf\nlf\ncrlf\nlf\nlf\ncrlf\n", tgt);
@@ -1063,8 +1058,7 @@ void test_core_buffer__lf_and_crlf_conversions(void)
git_buf_sets(&src, "\ncrlf\r\ncrlf\r\nlf\ncrlf\r\ncrlf");
- cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src));
- check_buf("\r\ncrlf\r\ncrlf\r\nlf\r\ncrlf\r\ncrlf", tgt);
+ cl_git_fail_with(GIT_PASSTHROUGH, git_buf_text_lf_to_crlf(&tgt, &src));
cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src));
check_buf("\ncrlf\ncrlf\nlf\ncrlf\ncrlf", tgt);
@@ -1072,8 +1066,7 @@ void test_core_buffer__lf_and_crlf_conversions(void)
git_buf_sets(&src, "\rcrlf\r\nlf\nlf\ncr\rcrlf\r\nlf\ncr\r");
- cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src));
- check_buf("\rcrlf\r\nlf\r\nlf\r\ncr\rcrlf\r\nlf\r\ncr\r", tgt);
+ cl_git_fail_with(GIT_PASSTHROUGH, git_buf_text_lf_to_crlf(&tgt, &src));
cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src));
check_buf("\rcrlf\nlf\nlf\ncr\rcrlf\nlf\ncr\r", tgt);
@@ -1089,8 +1082,7 @@ void test_core_buffer__lf_and_crlf_conversions(void)
/* blob correspondence tests */
git_buf_sets(&src, ALL_CRLF_TEXT_RAW);
- cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src));
- check_buf(ALL_CRLF_TEXT_AS_CRLF, tgt);
+ cl_git_fail_with(GIT_PASSTHROUGH, git_buf_text_lf_to_crlf(&tgt, &src));
cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src));
check_buf(ALL_CRLF_TEXT_AS_LF, tgt);
git_buf_free(&src);
@@ -1105,16 +1097,14 @@ void test_core_buffer__lf_and_crlf_conversions(void)
git_buf_free(&tgt);
git_buf_sets(&src, MORE_CRLF_TEXT_RAW);
- cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src));
- check_buf(MORE_CRLF_TEXT_AS_CRLF, tgt);
+ cl_git_fail_with(GIT_PASSTHROUGH, git_buf_text_lf_to_crlf(&tgt, &src));
cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src));
check_buf(MORE_CRLF_TEXT_AS_LF, tgt);
git_buf_free(&src);
git_buf_free(&tgt);
git_buf_sets(&src, MORE_LF_TEXT_RAW);
- cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src));
- check_buf(MORE_LF_TEXT_AS_CRLF, tgt);
+ cl_git_fail_with(GIT_PASSTHROUGH, git_buf_text_lf_to_crlf(&tgt, &src));
cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src));
check_buf(MORE_LF_TEXT_AS_LF, tgt);
git_buf_free(&src);