git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH] Teach core.autocrlf to 'git apply'

From
Junio C Hamano <junkio@cox.net>
Date
Feb 17, 2007, 20:37 UTC
Message-ID
<7vlkiwsepm.fsf@assigned-by-dhcp.cox.net>

This teaches git-apply that the data read from and written to the filesystem might need to get converted to adjust for local line-ending convention.

Signed-off-by: Junio C Hamano <junkio@cox.net>
---
 * Comes on top of lt/crlf branch which is part of 'next'.
   One problem that hasn't been solved is that git-apply without
   --index nor --cached does not read the configuration even
   when in a git-controlled working tree.  This is not a new
   issue and needs to be addressed separately.  For now, just to
   make testing easier, I tentatively added GIT_AUTOCRLF
   environment variable as a hack, but it should be removed from
   the real version.
 builtin-apply.c |   37 +++++++++++++++++++++++++++++++------
 t/t0020-crlf.sh |   22 +++++++++++++++++-----
 2 files changed, 48 insertions(+), 11 deletions(-)
diff --git a/builtin-apply.c b/builtin-apply.c
index 3fefdac..18f7307 100644
--- a/builtin-apply.c
+++ b/builtin-apply.c
@@ -1393,28 +1393,39 @@ static void show_stats(struct patch *patch)
 	free(qname);
 }
 
-static int read_old_data(struct stat *st, const char *path, void *buf, unsigned long size)
+static int read_old_data(struct stat *st, const char *path, char **buf_p, unsigned long *alloc_p, unsigned long *size_p)
 {
 	int fd;
 	unsigned long got;
+	unsigned long nsize;
+	char *nbuf;
+	unsigned long size = *size_p;
+	char *buf = *buf_p;
 
 	switch (st->st_mode & S_IFMT) {
 	case S_IFLNK:
-		return readlink(path, buf, size);
+		return readlink(path, buf, size) != size;
 	case S_IFREG:
 		fd = open(path, O_RDONLY);
 		if (fd < 0)
 			return error("unable to open %s", path);
 		got = 0;
 		for (;;) {
-			int ret = xread(fd, (char *) buf + got, size - got);
+			int ret = xread(fd, buf + got, size - got);
 			if (ret <= 0)
 				break;
 			got += ret;
 		}
 		close(fd);
-		return got;
-
+		nsize = got;
+		nbuf = buf;
+		if (convert_to_git(path, &nbuf, &nsize)) {
+			free(buf);
+			*buf_p = nbuf;
+			*alloc_p = nsize;
+			*size_p = nsize;
+		}
+		return got != size;
 	default:
 		return -1;
 	}
@@ -1910,7 +1921,7 @@ static int apply_data(struct patch *patch, struct stat *st, struct cache_entry *
 		size = st->st_size;
 		alloc = size + 8192;
 		buf = xmalloc(alloc);
-		if (read_old_data(st, patch->old_name, buf, alloc) != size)
+		if (read_old_data(st, patch->old_name, &buf, &alloc, &size))
 			return error("read of %s failed", patch->old_name);
 	}
 
@@ -2282,12 +2293,22 @@ static void add_index_file(const char *path, unsigned mode, void *buf, unsigned
 static int try_create_file(const char *path, unsigned int mode, const char *buf, unsigned long size)
 {
 	int fd;
+	char *nbuf;
+	unsigned long nsize;
 
 	if (S_ISLNK(mode))
 		/* Although buf:size is counted string, it also is NUL
 		 * terminated.
 		 */
 		return symlink(buf, path);
+	nsize = size;
+	nbuf = (char *) buf;
+	if (convert_to_working_tree(path, &nbuf, &nsize)) {
+		free((char *) buf);
+		buf = nbuf;
+		size = nsize;
+	}
+
 	fd = open(path, O_CREAT | O_EXCL | O_WRONLY, (mode & 0100) ? 0777 : 0666);
 	if (fd < 0)
 		return -1;
@@ -2598,6 +2619,10 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix)
 
 	const char *whitespace_option = NULL;
 
+	/* This still is undesirable... */
+	if (getenv("GIT_AUTOCRLF"))
+		git_default_config("core.autocrlf", getenv("GIT_AUTOCRLF"));
+
 	for (i = 1; i < argc; i++) {
 		const char *arg = argv[i];
 		char *end;
diff --git a/t/t0020-crlf.sh b/t/t0020-crlf.sh
index 58a4d86..c64d48c 100755
--- a/t/t0020-crlf.sh
+++ b/t/t0020-crlf.sh
@@ -180,11 +180,9 @@ test_expect_success 'apply patch (autocrlf=true)' '
 	git repo-config core.autocrlf true &&
 	git read-tree --reset -u HEAD &&
 
-	# Sore thumb
-	remove_cr one >tmp && mv -f tmp one &&
-
-	git apply patch.file &&
-	test "$patched" = "`git hash-object --stdin <one`" || {
+	# This is still undesirable...
+	GIT_AUTOCRLF=true git apply patch.file &&
+	test "$patched" = "`remove_cr one | git hash-object --stdin`" || {
 		echo "Eh?  apply without index"
 		false
 	}
@@ -203,4 +201,18 @@ test_expect_success 'apply patch --cached (autocrlf=true)' '
 	}
 '
 
+test_expect_success 'apply patch --index (autocrlf=true)' '
+
+	rm -f tmp one dir/two &&
+	git repo-config core.autocrlf true &&
+	git read-tree --reset -u HEAD &&
+
+	git apply --index patch.file &&
+	test "$patched" = `git rev-parse :one` &&
+	test "$patched" = "`remove_cr one | git hash-object --stdin`" || {
+		echo "Eh?  apply with --index"
+		false
+	}
+'
+
 test_done
Next: Junio C Hamano
Message 1 of 49 in “Teach core.autocrlf to 'git apply'”
  1. Teach core.autocrlf to 'git apply'Junio C Hamano, Feb 17, 2007
  2. Teach 'git apply' to look at $GIT_DIR/configJunio C Hamano, Feb 17, 2007
  3. Jeff KingFeb 17, 2007
  4. Junio C HamanoFeb 17, 2007
  5. Jeff KingFeb 17, 2007
  6. Linus TorvaldsFeb 19, 2007
  7. Shawn O. PearceFeb 19, 2007
  8. Junio C HamanoFeb 19, 2007
  9. Linus TorvaldsFeb 19, 2007
  10. Junio C HamanoFeb 19, 2007
  11. Linus TorvaldsFeb 20, 2007
  12. Junio C HamanoFeb 20, 2007
  13. Johannes SchindelinFeb 20, 2007
  14. Junio C HamanoFeb 20, 2007
  15. Johannes SchindelinFeb 20, 2007
  16. git-apply: require -p<n> when working in a subdirectory.Junio C Hamano, Feb 20, 2007
  17. apply: fix memory leak in prefix_one()Johannes Schindelin, Feb 20, 2007
  18. Junio C HamanoFeb 20, 2007
  19. Johannes SchindelinFeb 20, 2007
  20. git-apply: do not lose cwd when run from a subdirectory.Junio C Hamano, Feb 20, 2007
  21. Junio C HamanoFeb 20, 2007
  22. Linus TorvaldsFeb 20, 2007
  23. Daniel BarkalowFeb 21, 2007
  24. Junio C HamanoFeb 21, 2007
  25. Daniel BarkalowFeb 21, 2007
  26. Linus TorvaldsFeb 21, 2007
  27. Junio C HamanoFeb 21, 2007
  28. git-apply: notice "diff --git" patch againJunio C Hamano, Feb 21, 2007
  29. git-apply: guess correct -p<n> value for non-git patches.Junio C Hamano, Feb 22, 2007
  30. Johannes SchindelinFeb 20, 2007
  31. Simon 'corecode' SchubertFeb 20, 2007
  32. Johannes SchindelinFeb 18, 2007
  33. Junio C HamanoFeb 18, 2007
  34. Johannes SchindelinFeb 18, 2007
  35. Junio C HamanoFeb 18, 2007
  36. Johannes SchindelinFeb 18, 2007
  37. Junio C HamanoFeb 18, 2007
  38. Johannes SchindelinFeb 18, 2007
  39. Junio C HamanoFeb 18, 2007
  40. Johannes SchindelinFeb 18, 2007
  41. Jakub NarebskiFeb 18, 2007
  42. Johannes SchindelinFeb 18, 2007
  43. Junio C HamanoFeb 18, 2007
  44. Johannes SchindelinFeb 18, 2007
  45. Junio C HamanoFeb 18, 2007
  46. Johannes SchindelinFeb 18, 2007
  47. Junio C HamanoFeb 18, 2007
  48. Johannes SchindelinFeb 18, 2007
  49. Junio C HamanoFeb 18, 2007

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.