login
Header Space

 
 

[WIP v2] safecrlf: Add mechanism to warn about irreversible crlf conversions

Score:
Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]
To: <dpotapov@...>, <git@...>
Cc: <torvalds@...>, Steffen Prohaska <prohaska@...>
Date: Sunday, January 13, 2008 - 5:05 am

This version gets the naked LF/autocrlf=true case right.
However, different from what Dimitry suggested, the safety check
is run for all cases that are irreversible.  Dimitry suggested to
run it only for the CRLF_GUESS case.  I believe this is not
sufficient: the explicit CFLF_TEXT case should also be checked.
The user explicitly marked the file as text but the conversion is
nonetheless irreversible in the current setting.  This might be
unexpected and we should warn about it.  Paranoid users can even
ask git to fail in this case.  Such users would need to manually
fix the file, e.g. running dos2unix.

I also added basic tests.

A documentation is yet missing.

    Steffen

---- snip snap ---

CRLF conversion bears a slight chance of corrupting data.
autocrlf=true will convert CRLF to LF during commit and LF to
CRLF during checkout.  A file that containes a mixture of LF and
CRLF before the commit cannot be recreated by git.  For text
files this does not really matter because we do not care about
the line endings anyway; but for binary files that are
accidentally classified as text the conversion can result in
corrupted data.

If you recognize such corruption during commit you can easily fix
it by setting the conversion type explicitly in .gitattributes.
Right after committing you still have the original file in your
work tree and this file is not yet corrupted.

However, in mixed Windows/Unix environments text files quite
easily can end up containing a mixture of CRLF and LF line
endings and git should handle such situations gracefully.  For
example a user could copy a CRLF file from Windows to Unix and
mix it with an existing LF file there.  The result would contain
both types of line endings.

Unfortunately, the desired effect of cleaning up text files
with mixed lineendings and undesired effect of corrupting binary
files can not be distinguished.  In both cases CRLF are removed
in an irreversible way.  For text files this is the right thing
to do, while for binary file its corrupting data.

In a sane environment committing and checking out the same file
should not modify the origin file in the work tree.  For
autocrlf=input the original file must not contain CRLF.  For
autocrlf=true the original file must not contain LF without
preceding CR.  Otherwise the conversion is irreversible.  Note,
git might be able to recreate the original file with different
autocrlf settings, but in the current environment checking out
will yield a file that differs from the file before the commit.

This patch adds a mechanism that can either warn the user about
an irreversible conversion or can even refuse to convert.  The
mechanism is controlled by the variable core.safecrlf, with the
following values
 - false: disable safecrlf mechanism
 - warn: warn about irreversible conversions
 - true: refuse irreversible conversions

The default is to warn.

The concept of a safety check was originally proposed in a similar
way by Linus Torvalds.  Thanks to Dimitry Potapov for insisting
on getting the naked LF/autocrlf=true case right.

Signed-off-by: Steffen Prohaska <prohaska@zib.de>
---
 cache.h         |    8 ++++++++
 config.c        |    9 +++++++++
 convert.c       |   28 +++++++++++++++++++++++++---
 environment.c   |    1 +
 t/t0020-crlf.sh |   45 +++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 88 insertions(+), 3 deletions(-)

diff --git a/cache.h b/cache.h
index 39331c2..4e03e3d 100644
--- a/cache.h
+++ b/cache.h
@@ -330,6 +330,14 @@ extern size_t packed_git_limit;
 extern size_t delta_base_cache_limit;
 extern int auto_crlf;
 
+enum safe_crlf {
+	SAFE_CRLF_FALSE = 0,
+	SAFE_CRLF_FAIL = 1,
+	SAFE_CRLF_WARN = 2,
+};
+
+extern enum safe_crlf safe_crlf;
+
 #define GIT_REPO_VERSION 0
 extern int repository_format_version;
 extern int check_repository_format(void);
diff --git a/config.c b/config.c
index 857deb6..0a46046 100644
--- a/config.c
+++ b/config.c
@@ -407,6 +407,15 @@ int git_default_config(const char *var, const char *value)
 		return 0;
 	}
 
+	if (!strcmp(var, "core.safecrlf")) {
+		if (value && !strcasecmp(value, "warn")) {
+			safe_crlf = SAFE_CRLF_WARN;
+			return 0;
+		}
+		safe_crlf = git_config_bool(var, value);
+		return 0;
+	}
+
 	if (!strcmp(var, "user.name")) {
 		strlcpy(git_default_name, value, sizeof(git_default_name));
 		return 0;
diff --git a/convert.c b/convert.c
index 4df7559..c9678ee 100644
--- a/convert.c
+++ b/convert.c
@@ -90,9 +90,6 @@ static int crlf_to_git(const char *path, const char *src, size_t len,
 		return 0;
 
 	gather_stats(src, len, &stats);
-	/* No CR? Nothing to convert, regardless. */
-	if (!stats.cr)
-		return 0;
 
 	if (action == CRLF_GUESS) {
 		/*
@@ -110,6 +107,20 @@ static int crlf_to_git(const char *path, const char *src, size_t len,
 			return 0;
 	}
 
+	if (safe_crlf && auto_crlf > 0 && action != CRLF_INPUT) {
+		/* CRLFs would be added by checkout: check if we have "naked" LFs */
+		if (stats.lf != stats.crlf) {
+			if (safe_crlf == SAFE_CRLF_WARN)
+				warning("Checkout will replace LFs with CRLF in %s", path);
+			else
+				die("Checkout would replace LFs with CRLF in %s", path);
+		}
+	}
+
+	/* Optimization: No CR? Nothing to convert, regardless. */
+	if (!stats.cr)
+		return 0;
+
 	/* only grow if not in place */
 	if (strbuf_avail(buf) + buf->len < len)
 		strbuf_grow(buf, len - buf->len);
@@ -132,6 +143,17 @@ static int crlf_to_git(const char *path, const char *src, size_t len,
 				*dst++ = c;
 		} while (--len);
 	}
+
+	if (safe_crlf && (action == CRLF_INPUT || auto_crlf <= 0)) {
+		/* CRLFs would not be restored by checkout: check if we removed CRLFs */
+		if (buf->len != dst - buf->buf) {
+			if (safe_crlf == SAFE_CRLF_WARN)
+				warning("Stripped CRLF from %s.", path);
+			else
+				die("Refusing to strip CRLF from %s.", path);
+		}
+	}
+
 	strbuf_setlen(buf, dst - buf->buf);
 	return 1;
 }
diff --git a/environment.c b/environment.c
index 18a1c4e..e351e99 100644
--- a/environment.c
+++ b/environment.c
@@ -35,6 +35,7 @@ int pager_use_color = 1;
 char *editor_program;
 char *excludes_file;
 int auto_crlf = 0;	/* 1: both ways, -1: only when adding git objects */
+enum safe_crlf safe_crlf = SAFE_CRLF_WARN;
 unsigned whitespace_rule_cfg = WS_DEFAULT_RULE;
 
 /* This is set by setup_git_dir_gently() and/or git_default_config() */
diff --git a/t/t0020-crlf.sh b/t/t0020-crlf.sh
index 89baebd..e2e0f7b 100755
--- a/t/t0020-crlf.sh
+++ b/t/t0020-crlf.sh
@@ -8,6 +8,10 @@ q_to_nul () {
 	tr Q '\000'
 }
 
+q_to_cr () {
+	tr Q '\015'
+}
+
 append_cr () {
 	sed -e 's/$/Q/' | tr Q '\015'
 }
@@ -42,6 +46,47 @@ test_expect_success setup '
 	echo happy.
 '
 
+test_expect_failure 'safecrlf: autocrlf=input, all CRLF' '
+
+	git repo-config core.autocrlf input &&
+	git repo-config core.safecrlf true &&
+
+	for w in I am all CRLF; do echo $w; done | append_cr >allcrlf &&
+	git add allcrlf
+'
+
+test_expect_failure 'safecrlf: autocrlf=input, mixed LF/CRLF' '
+
+	git repo-config core.autocrlf input &&
+	git repo-config core.safecrlf true &&
+
+	for w in Oh here is CRLFQ in text; do echo $w; done | q_to_cr >mixed &&
+	git add mixed
+'
+
+test_expect_failure 'safecrlf: autocrlf=true, all LF' '
+
+	git repo-config core.autocrlf true &&
+	git repo-config core.safecrlf true &&
+
+	for w in I am all LF; do echo $w; done >alllf &&
+	git add alllf
+'
+
+test_expect_failure 'safecrlf: autocrlf=true mixed LF/CRLF' '
+
+	git repo-config core.autocrlf true &&
+	git repo-config core.safecrlf true &&
+
+	for w in Oh here is CRLFQ in text; do echo $w; done | q_to_cr >mixed &&
+	git add mixed
+'
+
+test_expect_success 'switch off autocrlf, safecrlf' '
+	git repo-config core.autocrlf false &&
+	git repo-config core.safecrlf false
+'
+
 test_expect_success 'update with autocrlf=input' '
 
 	rm -f tmp one dir/two three &&
-- 
1.5.4.rc2.60.g46ee

-
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]

Messages in current thread:
CRLF problems with Git on Win32, Peter Karlsson, (Mon Jan 7, 5:16 am)
Re: CRLF problems with Git on Win32, Steffen Prohaska, (Mon Jan 7, 5:57 am)
Re: CRLF problems with Git on Win32, Peter Klavins, (Mon Jan 7, 6:13 am)
Re: CRLF problems with Git on Win32, Peter Karlsson, (Mon Jan 7, 9:50 am)
Re: CRLF problems with Git on Win32, Steffen Prohaska, (Mon Jan 7, 12:05 pm)
Re: CRLF problems with Git on Win32, Peter Klavins, (Mon Jan 7, 10:14 am)
Re: CRLF problems with Git on Win32, Steffen Prohaska, (Mon Jan 7, 8:58 am)
Re: CRLF problems with Git on Win32, Jeff King, (Mon Jan 7, 6:12 am)
Re: CRLF problems with Git on Win32, Robin Rosenberg, (Mon Jan 7, 2:47 pm)
Re: CRLF problems with Git on Win32, Johannes Schindelin, (Mon Jan 7, 3:16 pm)
Re: CRLF problems with Git on Win32, Robin Rosenberg, (Mon Jan 7, 5:03 pm)
Re: CRLF problems with Git on Win32, Thomas Neumann, (Mon Jan 7, 5:42 pm)
Re: CRLF problems with Git on Win32, Peter Karlsson, (Tue Jan 8, 6:56 am)
Re: CRLF problems with Git on Win32, Jan Hudec, (Wed Jan 9, 2:46 pm)
Re: CRLF problems with Git on Win32, Peter Harris, (Tue Jan 8, 9:07 am)
Re: CRLF problems with Git on Win32, Dmitry Potapov, (Tue Jan 8, 5:33 pm)
Re: CRLF problems with Git on Win32, Kelvie Wong, (Tue Jan 8, 11:58 am)
Re: CRLF problems with Git on Win32, Peter Karlsson, (Tue Jan 8, 11:20 am)
Re: CRLF problems with Git on Win32, Johannes Schindelin, (Tue Jan 8, 7:52 am)
Re: CRLF problems with Git on Win32, Jeff King, (Tue Jan 8, 7:07 am)
Re: CRLF problems with Git on Win32, Johannes Schindelin, (Tue Jan 8, 7:54 am)
Re: CRLF problems with Git on Win32, Linus Torvalds, (Mon Jan 7, 5:36 pm)
Re: CRLF problems with Git on Win32, Peter Karlsson, (Tue Jan 8, 5:26 pm)
Re: CRLF problems with Git on Win32, Johannes Schindelin, (Wed Jan 9, 6:56 am)
Re: CRLF problems with Git on Win32, Steffen Prohaska, (Wed Jan 9, 8:41 am)
Re: CRLF problems with Git on Win32, Gregory Jefferis, (Wed Jan 9, 9:52 am)
Re: CRLF problems with Git on Win32, Dmitry Potapov, (Wed Jan 9, 11:03 am)
Re: CRLF problems with Git on Win32, Gregory Jefferis, (Wed Jan 9, 1:37 pm)
Re: CRLF problems with Git on Win32, Dmitry Potapov, (Wed Jan 9, 3:05 pm)
Re: CRLF problems with Git on Win32, Johannes Schindelin, (Wed Jan 9, 10:03 am)
Re: CRLF problems with Git on Win32, Dmitry Potapov, (Wed Jan 9, 11:22 am)
Re: CRLF problems with Git on Win32, Johannes Schindelin, (Mon Jan 7, 5:18 pm)
Re: CRLF problems with Git on Win32, Steffen Prohaska, (Mon Jan 7, 5:40 pm)
Re: CRLF problems with Git on Win32, J. Bruce Fields, (Tue Jan 8, 1:29 pm)
Re: CRLF problems with Git on Win32, Steffen Prohaska, (Tue Jan 8, 1:56 pm)
Re: CRLF problems with Git on Win32, Junio C Hamano, (Tue Jan 8, 2:07 pm)
Re: CRLF problems with Git on Win32, Gregory Jefferis, (Thu Jan 10, 3:58 pm)
Re: CRLF problems with Git on Win32, Rogan Dawes, (Thu Jan 10, 4:50 pm)
Re: CRLF problems with Git on Win32, Junio C Hamano, (Thu Jan 10, 9:15 pm)
Re: CRLF problems with Git on Win32, Gregory Jefferis, (Thu Jan 10, 5:15 pm)
Re: CRLF problems with Git on Win32, Linus Torvalds, (Thu Jan 10, 4:20 pm)
Re: CRLF problems with Git on Win32, Gregory Jefferis, (Thu Jan 10, 5:28 pm)
Re: CRLF problems with Git on Win32, Linus Torvalds, (Thu Jan 10, 8:02 pm)
Re: CRLF problems with Git on Win32, Steffen Prohaska, (Fri Jan 11, 3:10 am)
Re: CRLF problems with Git on Win32, Linus Torvalds, (Fri Jan 11, 11:58 am)
Re: CRLF problems with Git on Win32, Steffen Prohaska, (Fri Jan 11, 12:28 pm)
Re: CRLF problems with Git on Win32, Gregory Jefferis, (Fri Jan 11, 3:00 pm)
Re: CRLF problems with Git on Win32, Dmitry Potapov, (Sat Jan 12, 11:26 am)
Re: CRLF problems with Git on Win32, Linus Torvalds, (Fri Jan 11, 1:25 pm)
Re: CRLF problems with Git on Win32, Steffen Prohaska, (Fri Jan 11, 1:56 pm)
Re: CRLF problems with Git on Win32, Linus Torvalds, (Fri Jan 11, 2:10 pm)
Re: CRLF problems with Git on Win32, Christer Weinigel, (Fri Jan 11, 3:53 pm)
Re: CRLF problems with Git on Win32, Steffen Prohaska, (Fri Jan 11, 2:29 pm)
Re: CRLF problems with Git on Win32, Linus Torvalds, (Fri Jan 11, 3:16 pm)
[WIP v2] safecrlf: Add mechanism to warn about irreversible ..., Steffen Prohaska, (Sun Jan 13, 5:05 am)
Re: CRLF problems with Git on Win32, Sam Ravnborg, (Fri Jan 11, 3:50 pm)
Re: CRLF problems with Git on Win32, Dmitry Potapov, (Sat Jan 12, 11:08 am)
Re: CRLF problems with Git on Win32, Johannes Schindelin, (Fri Jan 11, 5:18 pm)
Re: CRLF problems with Git on Win32, Sam Ravnborg, (Fri Jan 11, 6:21 pm)
Re: CRLF problems with Git on Win32, Junio C Hamano, (Thu Jan 10, 8:32 pm)
Re: CRLF problems with Git on Win32, Dmitry Potapov, (Thu Jan 10, 7:23 pm)
Re: CRLF problems with Git on Win32, Steffen Prohaska, (Tue Jan 8, 2:58 pm)
Re: CRLF problems with Git on Win32, Dmitry Potapov, (Tue Jan 8, 4:50 pm)
Re: CRLF problems with Git on Win32, Linus Torvalds, (Tue Jan 8, 5:31 pm)
Re: CRLF problems with Git on Win32, Dmitry Potapov, (Tue Jan 8, 6:51 pm)
Re: CRLF problems with Git on Win32, Linus Torvalds, (Tue Jan 8, 8:01 pm)
Re: CRLF problems with Git on Win32, Sean, (Tue Jan 8, 6:09 pm)
Re: CRLF problems with Git on Win32, Junio C Hamano, (Tue Jan 8, 5:15 pm)
Re: CRLF problems with Git on Win32, Robin Rosenberg, (Tue Jan 8, 5:57 pm)
Re: CRLF problems with Git on Win32, Junio C Hamano, (Tue Jan 8, 4:11 pm)
Re: CRLF problems with Git on Win32, Steffen Prohaska, (Tue Jan 8, 4:20 pm)
Re: CRLF problems with Git on Win32, J. Bruce Fields, (Tue Jan 8, 3:09 pm)
Re: CRLF problems with Git on Win32, Steffen Prohaska, (Tue Jan 8, 3:59 pm)
Re: CRLF problems with Git on Win32, Junio C Hamano, (Tue Jan 8, 3:47 pm)
Re: CRLF problems with Git on Win32, Linus Torvalds, (Tue Jan 8, 4:41 pm)
Re: [msysGit] Re: CRLF problems with Git on Win32, Steffen Prohaska, (Tue Jan 8, 4:02 pm)
Re: [msysGit] Re: CRLF problems with Git on Win32, Johannes Schindelin, (Wed Jan 9, 7:03 am)
Re: [msysGit] Re: CRLF problems with Git on Win32, Steffen Prohaska, (Wed Jan 9, 8:45 am)
Re: [msysGit] Re: CRLF problems with Git on Win32, Johannes Schindelin, (Wed Jan 9, 9:32 am)
Re: CRLF problems with Git on Win32, Junio C Hamano, (Tue Jan 8, 4:15 pm)
Re: [msysGit] Re: CRLF problems with Git on Win32, Steffen Prohaska, (Tue Jan 8, 4:39 pm)
Re: CRLF problems with Git on Win32, Junio C Hamano, (Mon Jan 7, 6:06 pm)
Re: CRLF problems with Git on Win32, Steffen Prohaska, (Tue Jan 8, 3:02 am)
Re: CRLF problems with Git on Win32, Junio C Hamano, (Tue Jan 8, 3:29 am)
Re: CRLF problems with Git on Win32, Jeff King, (Tue Jan 8, 6:08 am)
Re: CRLF problems with Git on Win32, Gregory Jefferis, (Tue Jan 8, 8:20 am)
Re: CRLF problems with Git on Win32, Junio C Hamano, (Tue Jan 8, 6:35 am)
Re: CRLF problems with Git on Win32, Linus Torvalds, (Mon Jan 7, 6:58 pm)
Re: [msysGit] Re: CRLF problems with Git on Win32, Marius Storm-Olsen, (Tue Jan 8, 4:55 am)
Re: CRLF problems with Git on Win32, Gregory Jefferis, (Mon Jan 7, 7:46 pm)
git and unicode, Gonzalo Garramuño, (Tue Jan 8, 7:09 am)
Re: git and unicode, Robin Rosenberg, (Tue Jan 8, 4:36 pm)
Re: git and unicode, Remi Vanicat, (Tue Jan 8, 11:09 am)
Re: CRLF problems with Git on Win32, Junio C Hamano, (Mon Jan 7, 6:00 am)
Re: CRLF problems with Git on Win32, Steffen Prohaska, (Mon Jan 7, 8:15 am)
speck-geostationary