summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 4392da4)
raw | patch | inline | side by side (parent: 4392da4)
author | Junio C Hamano <junkio@cox.net> | |
Fri, 20 Apr 2007 05:37:19 +0000 (22:37 -0700) | ||
committer | Junio C Hamano <junkio@cox.net> | |
Fri, 20 Apr 2007 05:37:44 +0000 (22:37 -0700) |
This updates the semantics of 'crlf' so that .gitattributes file
can say "this is text, even though it may look funny".
Setting the `crlf` attribute on a path is meant to mark the path
as a "text" file. 'core.autocrlf' conversion takes place
without guessing the content type by inspection.
Unsetting the `crlf` attribute on a path is meant to mark the
path as a "binary" file. The path never goes through line
endings conversion upon checkin/checkout.
Unspecified `crlf` attribute tells git to apply the
`core.autocrlf` conversion when the file content looks like
text.
Setting the `crlf` attribut to string value "input" is similar
to setting the attribute to `true`, but also forces git to act
as if `core.autocrlf` is set to `input` for the path.
Signed-off-by: Junio C Hamano <junkio@cox.net>
can say "this is text, even though it may look funny".
Setting the `crlf` attribute on a path is meant to mark the path
as a "text" file. 'core.autocrlf' conversion takes place
without guessing the content type by inspection.
Unsetting the `crlf` attribute on a path is meant to mark the
path as a "binary" file. The path never goes through line
endings conversion upon checkin/checkout.
Unspecified `crlf` attribute tells git to apply the
`core.autocrlf` conversion when the file content looks like
text.
Setting the `crlf` attribut to string value "input" is similar
to setting the attribute to `true`, but also forces git to act
as if `core.autocrlf` is set to `input` for the path.
Signed-off-by: Junio C Hamano <junkio@cox.net>
convert.c | patch | blob | history | |
t/t0020-crlf.sh | patch | blob | history |
diff --git a/convert.c b/convert.c
index a5f60c7c6b729efbc7b98b1f5ac098cbf1bf9728..da64253a16e51881decd3e31d5763892f4847e5f 100644 (file)
--- a/convert.c
+++ b/convert.c
* translation when the "auto_crlf" option is set.
*/
+#define CRLF_GUESS (-1)
+#define CRLF_BINARY 0
+#define CRLF_TEXT 1
+#define CRLF_INPUT 2
+
struct text_stat {
/* CR, LF and CRLF counts */
unsigned cr, lf, crlf;
return 0;
}
-static int crlf_to_git(const char *path, char **bufp, unsigned long *sizep, int guess)
+static int crlf_to_git(const char *path, char **bufp, unsigned long *sizep, int action)
{
char *buffer, *nbuf;
unsigned long size, nsize;
struct text_stat stats;
- if (guess && !auto_crlf)
+ if ((action == CRLF_BINARY) || (action == CRLF_GUESS && !auto_crlf))
return 0;
size = *sizep;
if (!stats.cr)
return 0;
- if (guess) {
+ if (action == CRLF_GUESS) {
/*
* We're currently not going to even try to convert stuff
* that has bare CR characters. Does anybody do that crazy
@@ -119,7 +124,12 @@ static int crlf_to_git(const char *path, char **bufp, unsigned long *sizep, int
*bufp = nbuf;
*sizep = nsize;
- if (guess) {
+ if (action == CRLF_GUESS) {
+ /*
+ * If we guessed, we already know we rejected a file with
+ * lone CR, and we can strip a CR without looking at what
+ * follow it.
+ */
do {
unsigned char c = *buffer++;
if (c != '\r')
@@ -136,24 +146,15 @@ static int crlf_to_git(const char *path, char **bufp, unsigned long *sizep, int
return 1;
}
-static int autocrlf_to_git(const char *path, char **bufp, unsigned long *sizep)
-{
- return crlf_to_git(path, bufp, sizep, 1);
-}
-
-static int forcecrlf_to_git(const char *path, char **bufp, unsigned long *sizep)
-{
- return crlf_to_git(path, bufp, sizep, 0);
-}
-
-static int crlf_to_working_tree(const char *path, char **bufp, unsigned long *sizep, int guess)
+static int crlf_to_worktree(const char *path, char **bufp, unsigned long *sizep, int action)
{
char *buffer, *nbuf;
unsigned long size, nsize;
struct text_stat stats;
unsigned char last;
- if (guess && auto_crlf <= 0)
+ if ((action == CRLF_BINARY) || (action == CRLF_INPUT) ||
+ (action == CRLF_GUESS && auto_crlf <= 0))
return 0;
size = *sizep;
@@ -171,7 +172,7 @@ static int crlf_to_working_tree(const char *path, char **bufp, unsigned long *si
if (stats.lf == stats.crlf)
return 0;
- if (guess) {
+ if (action == CRLF_GUESS) {
/* If we have any bare CR characters, we're not going to touch it */
if (stats.cr != stats.crlf)
return 0;
@@ -200,16 +201,6 @@ static int crlf_to_working_tree(const char *path, char **bufp, unsigned long *si
return 1;
}
-static int autocrlf_to_working_tree(const char *path, char **bufp, unsigned long *sizep)
-{
- return crlf_to_working_tree(path, bufp, sizep, 1);
-}
-
-static int forcecrlf_to_working_tree(const char *path, char **bufp, unsigned long *sizep)
-{
- return crlf_to_working_tree(path, bufp, sizep, 0);
-}
-
static void setup_crlf_check(struct git_attr_check *check)
{
static struct git_attr *attr_crlf;
if (!git_checkattr(path, 1, &attr_crlf_check)) {
const char *value = attr_crlf_check.value;
if (ATTR_TRUE(value))
- return 1;
+ return CRLF_TEXT;
else if (ATTR_FALSE(value))
- return 0;
+ return CRLF_BINARY;
else if (ATTR_UNSET(value))
;
- else
- die("unknown value %s given to 'crlf' attribute",
- (char *)value);
+ else if (!strcmp(value, "input"))
+ return CRLF_INPUT;
+ /* fallthru */
}
- return -1;
+ return CRLF_GUESS;
}
int convert_to_git(const char *path, char **bufp, unsigned long *sizep)
{
- switch (git_path_check_crlf(path)) {
- case 0:
- return 0;
- case 1:
- return forcecrlf_to_git(path, bufp, sizep);
- default:
- return autocrlf_to_git(path, bufp, sizep);
- }
+ return crlf_to_git(path, bufp, sizep, git_path_check_crlf(path));
}
int convert_to_working_tree(const char *path, char **bufp, unsigned long *sizep)
{
- switch (git_path_check_crlf(path)) {
- case 0:
- return 0;
- case 1:
- return forcecrlf_to_working_tree(path, bufp, sizep);
- default:
- return autocrlf_to_working_tree(path, bufp, sizep);
- }
+ return crlf_to_worktree(path, bufp, sizep, git_path_check_crlf(path));
}
diff --git a/t/t0020-crlf.sh b/t/t0020-crlf.sh
index cf84f0a1ab5b392930f1d5a0008530399a6a00f6..fe1dfd08a02e7a8c9c26542e934ccd6fc4f16f5c 100755 (executable)
--- a/t/t0020-crlf.sh
+++ b/t/t0020-crlf.sh
. ./test-lib.sh
+q_to_nul () {
+ tr Q '\0'
+}
+
append_cr () {
sed -e 's/$/Q/' | tr Q '\015'
}
for w in Hello world how are you; do echo $w; done >one &&
mkdir dir &&
for w in I am very very fine thank you; do echo $w; done >dir/two &&
+ for w in Oh here is NULQin text here; do echo $w; done | q_to_nul >three &&
git add . &&
git commit -m initial &&
one=`git rev-parse HEAD:one` &&
dir=`git rev-parse HEAD:dir` &&
two=`git rev-parse HEAD:dir/two` &&
+ three=`git rev-parse HEAD:three` &&
for w in Some extra lines here; do echo $w; done >>one &&
git diff >patch.file &&
test_expect_success 'update with autocrlf=input' '
- rm -f tmp one dir/two &&
+ rm -f tmp one dir/two three &&
git read-tree --reset -u HEAD &&
git repo-config core.autocrlf input &&
test_expect_success 'update with autocrlf=true' '
- rm -f tmp one dir/two &&
+ rm -f tmp one dir/two three &&
git read-tree --reset -u HEAD &&
git repo-config core.autocrlf true &&
test_expect_success 'checkout with autocrlf=true' '
- rm -f tmp one dir/two &&
+ rm -f tmp one dir/two three &&
git repo-config core.autocrlf true &&
git read-tree --reset -u HEAD &&
test_expect_success 'checkout with autocrlf=input' '
- rm -f tmp one dir/two &&
+ rm -f tmp one dir/two three &&
git repo-config core.autocrlf input &&
git read-tree --reset -u HEAD &&
test_expect_success 'apply patch (autocrlf=input)' '
- rm -f tmp one dir/two &&
+ rm -f tmp one dir/two three &&
git repo-config core.autocrlf input &&
git read-tree --reset -u HEAD &&
test_expect_success 'apply patch --cached (autocrlf=input)' '
- rm -f tmp one dir/two &&
+ rm -f tmp one dir/two three &&
git repo-config core.autocrlf input &&
git read-tree --reset -u HEAD &&
test_expect_success 'apply patch --index (autocrlf=input)' '
- rm -f tmp one dir/two &&
+ rm -f tmp one dir/two three &&
git repo-config core.autocrlf input &&
git read-tree --reset -u HEAD &&
test_expect_success 'apply patch (autocrlf=true)' '
- rm -f tmp one dir/two &&
+ rm -f tmp one dir/two three &&
git repo-config core.autocrlf true &&
git read-tree --reset -u HEAD &&
test_expect_success 'apply patch --cached (autocrlf=true)' '
- rm -f tmp one dir/two &&
+ rm -f tmp one dir/two three &&
git repo-config core.autocrlf true &&
git read-tree --reset -u HEAD &&
test_expect_success 'apply patch --index (autocrlf=true)' '
- rm -f tmp one dir/two &&
+ rm -f tmp one dir/two three &&
git repo-config core.autocrlf true &&
git read-tree --reset -u HEAD &&
test_expect_success '.gitattributes says two is binary' '
+ rm -f tmp one dir/two three &&
echo "two -crlf" >.gitattributes &&
- rm -f tmp one dir/two &&
git repo-config core.autocrlf true &&
git read-tree --reset -u HEAD &&
fi &&
if remove_cr one >/dev/null
+ then
+ : happy
+ else
+ echo "Huh?"
+ false
+ fi &&
+
+ if remove_cr three >/dev/null
+ then
+ echo "Huh?"
+ false
+ else
+ : happy
+ fi
+'
+
+test_expect_success '.gitattributes says two is input' '
+
+ rm -f tmp one dir/two three &&
+ echo "two crlf=input" >.gitattributes &&
+ git read-tree --reset -u HEAD &&
+
+ if remove_cr dir/two >/dev/null
+ then
+ echo "Huh?"
+ false
+ else
+ : happy
+ fi
+'
+
+test_expect_success '.gitattributes says two and three are text' '
+
+ rm -f tmp one dir/two three &&
+ echo "t* crlf" >.gitattributes &&
+ git read-tree --reset -u HEAD &&
+
+ if remove_cr dir/two >/dev/null
+ then
+ : happy
+ else
+ echo "Huh?"
+ false
+ fi &&
+
+ if remove_cr three >/dev/null
then
: happy
else