diff options
| author | Carlos Martín Nieto <cmn@dwim.me> | 2015-06-22 19:44:05 +0200 |
|---|---|---|
| committer | Carlos Martín Nieto <cmn@dwim.me> | 2015-06-22 19:44:05 +0200 |
| commit | 91c1833af1bdc0680b42e9f2934665330f826c18 (patch) | |
| tree | a04f4b4a65f6b9a107c3b5a1e4be31ac7a6ba407 /src | |
| parent | 0b6ed4f96c7253b97a86f7e88ba4d69888c72382 (diff) | |
| parent | 146d0d084ea06527038e27549a8d4724d4fe5022 (diff) | |
| download | libgit2-91c1833af1bdc0680b42e9f2934665330f826c18.tar.gz | |
Merge pull request #3199 from ethomson/crlf
CRLF
Diffstat (limited to 'src')
| -rw-r--r-- | src/buf_text.c | 10 | ||||
| -rw-r--r-- | src/buf_text.h | 3 | ||||
| -rw-r--r-- | src/crlf.c | 56 |
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( |
