crlf: use statistics to control to workdir filter Use statistics (like core git) to control the behavior of the to workdir CRLF filter.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
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);
}