summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCarlos Martín Nieto <cmn@dwim.me>2015-06-22 19:44:05 +0200
committerCarlos Martín Nieto <cmn@dwim.me>2015-06-22 19:44:05 +0200
commit91c1833af1bdc0680b42e9f2934665330f826c18 (patch)
treea04f4b4a65f6b9a107c3b5a1e4be31ac7a6ba407 /src
parent0b6ed4f96c7253b97a86f7e88ba4d69888c72382 (diff)
parent146d0d084ea06527038e27549a8d4724d4fe5022 (diff)
downloadlibgit2-91c1833af1bdc0680b42e9f2934665330f826c18.tar.gz
Merge pull request #3199 from ethomson/crlf
CRLF
Diffstat (limited to 'src')
-rw-r--r--src/buf_text.c10
-rw-r--r--src/buf_text.h3
-rw-r--r--src/crlf.c56
3 files changed, 44 insertions, 25 deletions
diff --git a/src/buf_text.c b/src/buf_text.c
index 864e39cab..7e6779d2d 100644
--- a/src/buf_text.c
+++ b/src/buf_text.c
@@ -131,17 +131,15 @@ 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;
- /* if we find mixed line endings, bail */
- if (next > start && next[-1] == '\r') {
- git_buf_free(tgt);
- return GIT_PASSTHROUGH;
- }
+ /* if we find mixed line endings, carry on */
+ if (copylen && next[-1] == '\r')
+ copylen--;
GITERR_CHECK_ALLOC_ADD(&alloclen, copylen, 3);
if (git_buf_grow_by(tgt, alloclen) < 0)
return -1;
- if (next > scan) {
+ if (copylen) {
memcpy(tgt->ptr + tgt->size, scan, copylen);
tgt->size += copylen;
}
diff --git a/src/buf_text.h b/src/buf_text.h
index e753a0244..c9c55af89 100644
--- a/src/buf_text.h
+++ b/src/buf_text.h
@@ -58,8 +58,7 @@ extern void git_buf_text_unescape(git_buf *buf);
/**
* Replace all \r\n with \n.
*
- * @return 0 on success, -1 on memory error, GIT_PASSTHROUGH if the
- * source buffer has mixed line endings.
+ * @return 0 on success, -1 on memory error
*/
extern int git_buf_text_crlf_to_lf(git_buf *tgt, const git_buf *src);
diff --git a/src/crlf.c b/src/crlf.c
index b5d1dbf32..f391137c1 100644
--- a/src/crlf.c
+++ b/src/crlf.c
@@ -193,28 +193,29 @@ static const char *line_ending(struct crlf_attrs *ca)
case GIT_CRLF_CRLF:
return "\r\n";
+ case GIT_CRLF_GUESS:
+ if (ca->auto_crlf == GIT_AUTO_CRLF_FALSE)
+ return "\n";
+ break;
+
case GIT_CRLF_AUTO:
case GIT_CRLF_TEXT:
- case GIT_CRLF_GUESS:
break;
default:
goto line_ending_error;
}
- switch (ca->eol) {
- case GIT_EOL_UNSET:
- return GIT_EOL_NATIVE == GIT_EOL_CRLF ? "\r\n" : "\n";
-
- case GIT_EOL_CRLF:
+ if (ca->auto_crlf == GIT_AUTO_CRLF_TRUE)
return "\r\n";
-
- case GIT_EOL_LF:
+ else if (ca->auto_crlf == GIT_AUTO_CRLF_INPUT)
return "\n";
-
- default:
- goto line_ending_error;
- }
+ else if (ca->eol == GIT_EOL_UNSET)
+ return GIT_EOL_NATIVE == GIT_EOL_CRLF ? "\r\n" : "\n";
+ else if (ca->eol == GIT_EOL_LF)
+ return "\n";
+ else if (ca->eol == GIT_EOL_CRLF)
+ return "\r\n";
line_ending_error:
giterr_set(GITERR_INVALID, "Invalid input to line ending filter");
@@ -224,16 +225,14 @@ line_ending_error:
static int crlf_apply_to_workdir(
struct crlf_attrs *ca, git_buf *to, const git_buf *from)
{
+ git_buf_text_stats stats;
const char *workdir_ending = NULL;
+ bool is_binary;
/* Empty file? Nothing to do. */
if (git_buf_len(from) == 0)
return 0;
- /* Don't filter binary files */
- if (git_buf_text_is_binary(from))
- return GIT_PASSTHROUGH;
-
/* Determine proper line ending */
workdir_ending = line_ending(ca);
if (!workdir_ending)
@@ -243,6 +242,29 @@ static int crlf_apply_to_workdir(
if (strcmp(workdir_ending, "\r\n") != 0)
return GIT_PASSTHROUGH;
+ /* If there are no LFs, or all LFs are part of a CRLF, nothing to do */
+ is_binary = git_buf_text_gather_stats(&stats, from, false);
+
+ if (stats.lf == 0 || stats.lf == stats.crlf)
+ return GIT_PASSTHROUGH;
+
+ if (ca->crlf_action == GIT_CRLF_AUTO ||
+ ca->crlf_action == GIT_CRLF_GUESS) {
+
+ /* If we have any existing CR or CRLF line endings, do nothing */
+ if (ca->crlf_action == GIT_CRLF_GUESS &&
+ stats.cr > 0 && stats.crlf > 0)
+ return GIT_PASSTHROUGH;
+
+ /* If we have bare CR characters, do nothing */
+ if (stats.cr != stats.crlf)
+ return GIT_PASSTHROUGH;
+
+ /* Don't filter binary files */
+ if (is_binary)
+ return GIT_PASSTHROUGH;
+ }
+
return git_buf_text_lf_to_crlf(to, from);
}
@@ -278,7 +300,7 @@ static int crlf_check(
return GIT_PASSTHROUGH;
if (ca.crlf_action == GIT_CRLF_GUESS ||
- (ca.crlf_action == GIT_CRLF_AUTO &&
+ ((ca.crlf_action == GIT_CRLF_AUTO || ca.crlf_action == GIT_CRLF_TEXT) &&
git_filter_source_mode(src) == GIT_FILTER_SMUDGE)) {
error = git_repository__cvar(