Commit 91c1833a by Carlos Martín Nieto

Merge pull request #3199 from ethomson/crlf

CRLF
parents 0b6ed4f9 146d0d08

Too many changes to show.

To preserve performance only 1000 of 1000+ files are displayed.

......@@ -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;
}
......
......@@ -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);
......
......@@ -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(
......
......@@ -20,6 +20,19 @@ fixture_path(const char *base, const char *fixture_name)
return _path;
}
static const char *
fixture_basename(const char *fixture_name)
{
const char *p;
for (p = fixture_name; *p; p++) {
if (p[0] == '/' && p[1] && p[1] != '/')
fixture_name = p+1;
}
return fixture_name;
}
#ifdef CLAR_FIXTURE_PATH
const char *cl_fixture(const char *fixture_name)
{
......@@ -33,6 +46,6 @@ void cl_fixture_sandbox(const char *fixture_name)
void cl_fixture_cleanup(const char *fixture_name)
{
fs_rm(fixture_path(_clar_path, fixture_name));
fs_rm(fixture_path(_clar_path, fixture_basename(fixture_name)));
}
#endif
......@@ -1054,14 +1054,20 @@ void test_core_buffer__lf_and_crlf_conversions(void)
git_buf_sets(&src, "crlf\r\ncrlf\r\ncrlf\r\ncrlf\r\n");
cl_git_fail_with(GIT_PASSTHROUGH, git_buf_text_lf_to_crlf(&tgt, &src));
cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src));
check_buf("crlf\r\ncrlf\r\ncrlf\r\ncrlf\r\n", tgt);
git_buf_sets(&src, "crlf\r\ncrlf\r\ncrlf\r\ncrlf\r\n");
cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src));
check_buf("crlf\ncrlf\ncrlf\ncrlf\n", tgt);
git_buf_sets(&src, "\r\ncrlf\r\ncrlf\r\ncrlf\r\ncrlf\r\ncrlf");
cl_git_fail_with(GIT_PASSTHROUGH, git_buf_text_lf_to_crlf(&tgt, &src));
cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src));
check_buf("\r\ncrlf\r\ncrlf\r\ncrlf\r\ncrlf\r\ncrlf", tgt);
git_buf_sets(&src, "\r\ncrlf\r\ncrlf\r\ncrlf\r\ncrlf\r\ncrlf");
cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src));
check_buf("\ncrlf\ncrlf\ncrlf\ncrlf\ncrlf", tgt);
......@@ -1070,7 +1076,11 @@ void test_core_buffer__lf_and_crlf_conversions(void)
git_buf_sets(&src, "\nlf\nlf\ncrlf\r\nlf\nlf\ncrlf\r\n");
cl_git_fail_with(GIT_PASSTHROUGH, git_buf_text_lf_to_crlf(&tgt, &src));
cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src));
check_buf("\r\nlf\r\nlf\r\ncrlf\r\nlf\r\nlf\r\ncrlf\r\n", tgt);
git_buf_sets(&src, "\nlf\nlf\ncrlf\r\nlf\nlf\ncrlf\r\n");
cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src));
check_buf("\nlf\nlf\ncrlf\nlf\nlf\ncrlf\n", tgt);
......@@ -1078,7 +1088,9 @@ void test_core_buffer__lf_and_crlf_conversions(void)
git_buf_sets(&src, "\ncrlf\r\ncrlf\r\nlf\ncrlf\r\ncrlf");
cl_git_fail_with(GIT_PASSTHROUGH, git_buf_text_lf_to_crlf(&tgt, &src));
cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src));
check_buf("\r\ncrlf\r\ncrlf\r\nlf\r\ncrlf\r\ncrlf", tgt);
cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src));
check_buf("\ncrlf\ncrlf\nlf\ncrlf\ncrlf", tgt);
......@@ -1086,7 +1098,11 @@ void test_core_buffer__lf_and_crlf_conversions(void)
git_buf_sets(&src, "\rcrlf\r\nlf\nlf\ncr\rcrlf\r\nlf\ncr\r");
cl_git_fail_with(GIT_PASSTHROUGH, git_buf_text_lf_to_crlf(&tgt, &src));
cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src));
check_buf("\rcrlf\r\nlf\r\nlf\r\ncr\rcrlf\r\nlf\r\ncr\r", tgt);
git_buf_sets(&src, "\rcrlf\r\nlf\nlf\ncr\rcrlf\r\nlf\ncr\r");
cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src));
check_buf("\rcrlf\nlf\nlf\ncr\rcrlf\nlf\ncr\r", tgt);
......@@ -1102,7 +1118,9 @@ void test_core_buffer__lf_and_crlf_conversions(void)
/* blob correspondence tests */
git_buf_sets(&src, ALL_CRLF_TEXT_RAW);
cl_git_fail_with(GIT_PASSTHROUGH, git_buf_text_lf_to_crlf(&tgt, &src));
cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src));
check_buf(ALL_CRLF_TEXT_AS_CRLF, tgt);
git_buf_sets(&src, ALL_CRLF_TEXT_RAW);
cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src));
check_buf(ALL_CRLF_TEXT_AS_LF, tgt);
git_buf_free(&src);
......@@ -1111,20 +1129,25 @@ void test_core_buffer__lf_and_crlf_conversions(void)
git_buf_sets(&src, ALL_LF_TEXT_RAW);
cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src));
check_buf(ALL_LF_TEXT_AS_CRLF, tgt);
git_buf_sets(&src, ALL_LF_TEXT_RAW);
cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src));
check_buf(ALL_LF_TEXT_AS_LF, tgt);
git_buf_free(&src);
git_buf_free(&tgt);
git_buf_sets(&src, MORE_CRLF_TEXT_RAW);
cl_git_fail_with(GIT_PASSTHROUGH, git_buf_text_lf_to_crlf(&tgt, &src));
cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src));
check_buf(MORE_CRLF_TEXT_AS_CRLF, tgt);
git_buf_sets(&src, MORE_CRLF_TEXT_RAW);
cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src));
check_buf(MORE_CRLF_TEXT_AS_LF, tgt);
git_buf_free(&src);
git_buf_free(&tgt);
git_buf_sets(&src, MORE_LF_TEXT_RAW);
cl_git_fail_with(GIT_PASSTHROUGH, git_buf_text_lf_to_crlf(&tgt, &src));
cl_git_pass(git_buf_text_lf_to_crlf(&tgt, &src));
check_buf(MORE_LF_TEXT_AS_CRLF, tgt);
git_buf_sets(&src, MORE_LF_TEXT_RAW);
cl_git_pass(git_buf_text_crlf_to_lf(&tgt, &src));
check_buf(MORE_LF_TEXT_AS_LF, tgt);
git_buf_free(&src);
......
......@@ -38,11 +38,7 @@ void test_filter_crlf__to_worktree(void)
cl_git_pass(git_filter_list_apply_to_data(&out, fl, &in));
#ifdef GIT_WIN32
cl_assert_equal_s("Some text\r\nRight here\r\n", out.ptr);
#else
cl_assert_equal_s("Some text\nRight here\n", out.ptr);
#endif
git_filter_list_free(fl);
git_buf_free(&out);
......
#!/usr/bin/env bash
set -e
if [ "$1" == "" -o "$2" == "" ]; then
echo "usage: $0 crlfrepo directory [tempdir]"
exit 1
fi
input=$1
output=$2
tempdir=$3
set -u
create_repo() {
local input=$1
local output=$2
local tempdir=$3
local systype=$4
local autocrlf=$5
local attr=$6
local worktree="${output}/${systype}/autocrlf_${autocrlf}"
if [ "$attr" != "" ]; then
local attrdir=`echo $attr | sed -e "s/ /,/g" | sed -e "s/=/_/g"`
worktree="${worktree},${attrdir}"
fi
if [ "$tempdir" = "" ]; then
local gitdir="${worktree}/.git"
else
local gitdir="${tempdir}/generate_crlf_${RANDOM}"
fi
echo "Creating ${worktree}"
mkdir -p "${worktree}"
git clone --no-checkout --quiet --bare "${input}/.gitted" "${gitdir}"
git --work-tree="${worktree}" --git-dir="${gitdir}" config core.autocrlf ${autocrlf}
if [ "$attr" != "" ]; then
echo "* ${attr}" >> "${worktree}/.gitattributes"
fi
git --work-tree="${worktree}" --git-dir="${gitdir}" checkout HEAD
if [ "$attr" != "" ]; then
rm "${worktree}/.gitattributes"
fi
if [ "$tempdir" != "" ]; then
rm -rf "${gitdir}"
fi
}
if [[ `uname -s` == MINGW* ]]; then
systype="windows"
else
systype="posix"
fi
for autocrlf in true false input; do
for attr in "" text text=auto -text crlf -crlf eol=lf eol=crlf \
"text eol=lf" "text eol=crlf" \
"text=auto eol=lf" "text=auto eol=crlf"; do
create_repo "${input}" "${output}" "${tempdir}" \
"${systype}" "${autocrlf}" "${attr}"
done
done
044bcd5c9bf5ebdd51e514a9a36457018f06f6e1
5afb6a14a864e30787857dd92af837e8cdd2cb1b
a234455d62297f1856c4603686150c59fcb0aafe
⚽The rest is ASCII01.
The rest is ASCII02.
The rest is ASCII03.
The rest is ASCII04.
The rest is ASCII05.
The rest is ASCII06.
The rest is ASCII07.
The rest is ASCII08.
The rest is ASCII09.
The rest is ASCII10.
The rest is ASCII11.
The rest is ASCII12.
The rest is ASCII13.
The rest is ASCII14.
The rest is ASCII15.
The rest is ASCII16.
The rest is ASCII17.
The rest is ASCII18.
The rest is ASCII19.
The rest is ASCII20.
The rest is ASCII21.
The rest is ASCII22.
⚽The rest is ASCII01.
The rest is ASCII02.
The rest is ASCII03.
The rest is ASCII04.
The rest is ASCII05.
The rest is ASCII06.
The rest is ASCII07.
The rest is ASCII08.
The rest is ASCII09.
The rest is ASCII10.
The rest is ASCII11.
The rest is ASCII12.
The rest is ASCII13.
The rest is ASCII14.
The rest is ASCII15.
The rest is ASCII16.
The rest is ASCII17.
The rest is ASCII18.
The rest is ASCII19.
The rest is ASCII20.
The rest is ASCII21.
The rest is ASCII22.
one
two three
four
\ No newline at end of file
⚽The rest is ASCII01.
The rest is ASCII02.
The rest is ASCII03.
The rest is ASCII04.
The rest is ASCII05.
The rest is ASCII06.
The rest is ASCII07.
The rest is ASCII08.
The rest is ASCII09.
The rest is ASCII10.
The rest is ASCII11.
The rest is ASCII12.
The rest is ASCII13.
The rest is ASCII14.
The rest is ASCII15.
The rest is ASCII16.
The rest is ASCII17.
The rest is ASCII18.
The rest is ASCII19.
The rest is ASCII20.
The rest is ASCII21.
The rest is ASCII22.
⚽The rest is ASCII01.
The rest is ASCII02.
The rest is ASCII03.
The rest is ASCII04.
The rest is ASCII05.
The rest is ASCII06.
The rest is ASCII07.
The rest is ASCII08.
The rest is ASCII09.
The rest is ASCII10.
The rest is ASCII11.
The rest is ASCII12.
The rest is ASCII13.
The rest is ASCII14.
The rest is ASCII15.
The rest is ASCII16.
The rest is ASCII17.
The rest is ASCII18.
The rest is ASCII19.
The rest is ASCII20.
The rest is ASCII21.
The rest is ASCII22.
one
two three
four
\ No newline at end of file
⚽The rest is ASCII01.
The rest is ASCII02.
The rest is ASCII03.
The rest is ASCII04.
The rest is ASCII05.
The rest is ASCII06.
The rest is ASCII07.
The rest is ASCII08.
The rest is ASCII09.
The rest is ASCII10.
The rest is ASCII11.
The rest is ASCII12.
The rest is ASCII13.
The rest is ASCII14.
The rest is ASCII15.
The rest is ASCII16.
The rest is ASCII17.
The rest is ASCII18.
The rest is ASCII19.
The rest is ASCII20.
The rest is ASCII21.
The rest is ASCII22.
⚽The rest is ASCII01.
The rest is ASCII02.
The rest is ASCII03.
The rest is ASCII04.
The rest is ASCII05.
The rest is ASCII06.
The rest is ASCII07.
The rest is ASCII08.
The rest is ASCII09.
The rest is ASCII10.
The rest is ASCII11.
The rest is ASCII12.
The rest is ASCII13.
The rest is ASCII14.
The rest is ASCII15.
The rest is ASCII16.
The rest is ASCII17.
The rest is ASCII18.
The rest is ASCII19.
The rest is ASCII20.
The rest is ASCII21.
The rest is ASCII22.
one
two three
four
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment