diff --git a/src/crlf.c b/src/crlf.c index b5d1dbf32..2fe8a5f55 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); }