Code

Teach core.autocrlf to 'git apply'
authorJunio C Hamano <junkio@cox.net>
Sat, 17 Feb 2007 20:37:25 +0000 (12:37 -0800)
committerJunio C Hamano <junkio@cox.net>
Sat, 17 Feb 2007 23:27:47 +0000 (15:27 -0800)
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>
builtin-apply.c
t/t0020-crlf.sh

index 3fefdacd94526b62ac72707d6d80b039f104c06d..45c4acbd205d02d0c6586b925909756b4508867c 100644 (file)
@@ -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,7 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix)
 
        const char *whitespace_option = NULL;
 
+
        for (i = 1; i < argc; i++) {
                const char *arg = argv[i];
                char *end;
index 58a4d86df3f8b82d4a5a7dcabdb93ee62b20a35c..723b29ad17f778f9f9a96682dee1793191b88667 100755 (executable)
@@ -180,11 +180,8 @@ 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`" || {
+       test "$patched" = "`remove_cr one | git hash-object --stdin`" || {
                echo "Eh?  apply without index"
                false
        }
@@ -203,4 +200,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