Signed-off-by: Nguyễn Thái Ngọc Duy <pclo...@gmail.com>
---
 Changes: do not lose worktree's executable permission.

 t/t1011-read-tree-sparse-checkout.sh |  3 ++-
 t/t2021-checkout-overwrite.sh        | 18 ++++++++++++++++++
 unpack-trees.c                       | 31 +++++++++++++++++++++++++++++++
 3 files changed, 51 insertions(+), 1 deletion(-)

diff --git a/t/t1011-read-tree-sparse-checkout.sh 
b/t/t1011-read-tree-sparse-checkout.sh
index 5c0053a..38f9899 100755
--- a/t/t1011-read-tree-sparse-checkout.sh
+++ b/t/t1011-read-tree-sparse-checkout.sh
@@ -238,7 +238,8 @@ test_expect_success 'print errors when failed to update 
worktree' '
        echo sub >.git/info/sparse-checkout &&
        git checkout -f init &&
        mkdir sub &&
-       touch sub/added sub/addedtoo &&
+       echo modified >sub/added &&
+       echo modified >sub/addedtoo &&
        test_must_fail git checkout top 2>actual &&
        cat >expected <<\EOF &&
 error: The following untracked working tree files would be overwritten by 
checkout:
diff --git a/t/t2021-checkout-overwrite.sh b/t/t2021-checkout-overwrite.sh
index 5da63e9..bb1696d 100755
--- a/t/t2021-checkout-overwrite.sh
+++ b/t/t2021-checkout-overwrite.sh
@@ -47,4 +47,22 @@ test_expect_success SYMLINKS 'checkout commit with dir must 
not remove untracked
        test -h a/b
 '
 
+test_expect_success 'do not abort on overwriting an existing file with the 
same content' '
+       echo abc >bar &&
+       git add bar &&
+       git commit -m "new file" &&
+       git reset HEAD^ &&
+       git checkout HEAD@{1}
+'
+
+test_expect_success POSIXPERM 'do abort on an existing file, same content but 
different permission' '
+       git checkout -f HEAD^ &&
+       echo abc >bar &&
+       git add bar &&
+       git commit -m "new file" &&
+       git reset HEAD^ &&
+       chmod a+x bar &&
+       test_must_fail git checkout HEAD@{1}
+'
+
 test_done
diff --git a/unpack-trees.c b/unpack-trees.c
index 0e1a196..ea204ae 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -9,6 +9,8 @@
 #include "refs.h"
 #include "attr.h"
 
+#define SAME_CONTENT_SIZE_LIMIT (1024 * 1024)
+
 /*
  * Error messages expected by scripts out of plumbing commands such as
  * read-tree.  Non-scripted Porcelain is not required to use these messages
@@ -1363,6 +1365,7 @@ static int check_ok_to_remove(const char *name, int len, 
int dtype,
                              struct unpack_trees_options *o)
 {
        struct cache_entry *result;
+       unsigned long ce_size;
 
        /*
         * It may be that the 'lstat()' succeeded even though
@@ -1405,6 +1408,34 @@ static int check_ok_to_remove(const char *name, int len, 
int dtype,
                        return 0;
        }
 
+       /*
+        * If it has the same content that we are going to overwrite,
+        * there's no point in complaining. We still overwrite it in
+        * the end though.
+        */
+       if (ce &&
+           S_ISREG(st->st_mode) && S_ISREG(ce->ce_mode) &&
+           (!trust_executable_bit ||
+            (0100 & (ce->ce_mode ^ st->st_mode)) == 0) &&
+           st->st_size < SAME_CONTENT_SIZE_LIMIT &&
+           sha1_object_info(ce->sha1, &ce_size) == OBJ_BLOB &&
+           ce_size == st->st_size) {
+               void *buffer = NULL;
+               unsigned long size;
+               enum object_type type;
+               struct strbuf sb = STRBUF_INIT;
+               int matched =
+                       strbuf_read_file(&sb, ce->name, ce_size) == ce_size &&
+                       (buffer = read_sha1_file(ce->sha1, &type, &size)) != 
NULL &&
+                       type == OBJ_BLOB &&
+                       size == ce_size &&
+                       !memcmp(buffer, sb.buf, size);
+               free(buffer);
+               strbuf_release(&sb);
+               if (matched)
+                       return 0;
+       }
+
        return o->gently ? -1 :
                add_rejected_path(o, error_type, name);
 }
-- 
1.8.0.rc2.23.g1fb49df

--
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