Commit 47e9a6cb0573aa2190ddabadb94c0a89ae14ba52

Edward Thomson 2015-06-08T15:58:54

crlf: use statistics to control to workdir filter Use statistics (like core git) to control the behavior of the to workdir CRLF filter.

diff --git a/src/crlf.c b/src/crlf.c
index b5d1dbf..2fe8a5f 100644
--- a/src/crlf.c
+++ b/src/crlf.c
@@ -224,16 +224,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 +241,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);
 }