From: Torsten Bögershausen <tbo...@web.de>

We define the working tree file is clean if either:

  * the result of running convert_to_git() on the working tree
    contents matches what is in the index (because that would mean
    doing another "git add" on the path is a no-op); OR

  * the result of running convert_to_working_tree() on the content
    in the index matches what is in the working tree (because that
    would mean doing another "git checkout -f" on the path is a
    no-op).

Add an extra check in ce_compare_data() in read_cache.c.

Helped-by: Junio C Hamano <gits...@pobox.com>
Signed-off-by: Torsten Bögershausen <tbo...@web.de>
---
 read-cache.c               | 61 ++++++++++++++++++++++++++++++++++++++++++++++
 t/t6038-merge-text-auto.sh | 14 +++++------
 2 files changed, 68 insertions(+), 7 deletions(-)

diff --git a/read-cache.c b/read-cache.c
index a3ef967..48c4b31 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -156,17 +156,78 @@ void fill_stat_cache_info(struct cache_entry *ce, struct 
stat *st)
                ce_mark_uptodate(ce);
 }
 
+/*
+ * Compare the data in buf with the data in the file pointed by fd and
+ * return 0 if they are identical, and non-zero if they differ.
+ */
+static int compare_with_fd(const char *input, ssize_t len, int fd)
+{
+       for (;;) {
+               char buf[1024 * 16];
+               ssize_t chunk_len, read_len;
+
+               chunk_len = sizeof(buf) < len ? sizeof(buf) : len;
+               read_len = xread(fd, buf, chunk_len ? chunk_len : 1);
+
+               if (!read_len)
+                       /* EOF on the working tree file */
+                       return !len ? 0 : -1;
+
+               if (!len)
+                       /* we expected there is nothing left */
+                       return -1;
+
+               if (memcmp(buf, input, read_len))
+                       return -1;
+               input += read_len;
+               len -= read_len;
+       }
+}
+
 static int ce_compare_data(const struct cache_entry *ce, struct stat *st)
 {
        int match = -1;
        int fd = open(ce->name, O_RDONLY);
 
+       /*
+        * Would another "git add" on the path change what is in the
+        * index for the path?
+        */
        if (fd >= 0) {
                unsigned char sha1[20];
                if (!index_fd(sha1, fd, st, OBJ_BLOB, ce->name, 0))
                        match = hashcmp(sha1, ce->sha1);
                /* index_fd() closed the file descriptor already */
        }
+       if (!match)
+               return match;
+
+       /*
+        * Would another "git checkout -f" out of the index change
+        * what is in the working tree file?
+        */
+       fd = open(ce->name, O_RDONLY);
+       if (fd >= 0) {
+               enum object_type type;
+               unsigned long size_long;
+               void *data = read_sha1_file(ce->sha1, &type, &size_long);
+
+               if (type == OBJ_BLOB) {
+                       struct strbuf worktree = STRBUF_INIT;
+                       if (convert_to_working_tree(ce->name, data,
+                                                   size_long,
+                                                   &worktree)) {
+                               size_t size;
+                               free(data);
+                               data = strbuf_detach(&worktree, &size);
+                               size_long = size;
+                       }
+                       if (!compare_with_fd(data, size_long, fd))
+                               match = 0;
+               }
+               free(data);
+               close(fd);
+       }
        return match;
 }
 
diff --git a/t/t6038-merge-text-auto.sh b/t/t6038-merge-text-auto.sh
index 0108ead..565daf3 100755
--- a/t/t6038-merge-text-auto.sh
+++ b/t/t6038-merge-text-auto.sh
@@ -108,9 +108,9 @@ test_expect_success 'Merge addition of text=auto' '
 
 test_expect_success 'Detect CRLF/LF conflict after setting text=auto' '
        echo "<<<<<<<" >expected &&
-       echo first line | append_cr >>expected &&
-       echo same line | append_cr >>expected &&
-       echo ======= | append_cr >>expected &&
+       echo first line >>expected &&
+       echo same line >>expected &&
+       echo ======= >>expected &&
        echo first line | append_cr >>expected &&
        echo same line | append_cr >>expected &&
        echo ">>>>>>>" >>expected &&
@@ -121,14 +121,13 @@ test_expect_success 'Detect CRLF/LF conflict after 
setting text=auto' '
        fuzz_conflict file >file.fuzzy &&
        compare_files expected file.fuzzy
 '
-
 test_expect_success 'Detect LF/CRLF conflict from addition of text=auto' '
        echo "<<<<<<<" >expected &&
        echo first line | append_cr >>expected &&
        echo same line | append_cr >>expected &&
-       echo ======= | append_cr >>expected &&
-       echo first line | append_cr >>expected &&
-       echo same line | append_cr >>expected &&
+       echo =======  >>expected &&
+       echo first line >>expected &&
+       echo same line  >>expected &&
        echo ">>>>>>>" >>expected &&
        git config merge.renormalize false &&
        rm -f .gitattributes &&
@@ -138,6 +137,7 @@ test_expect_success 'Detect LF/CRLF conflict from addition 
of text=auto' '
        compare_files expected file.fuzzy
 '
 
+
 test_expect_failure 'checkout -m after setting text=auto' '
        cat <<-\EOF >expected &&
        first line
-- 
2.7.0.992.g0c2c796

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to