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@xxxxxxx> --- * 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 - To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html