Merge branch 'jk/checkout-from-tree'
authorJunio C Hamano <gitster@pobox.com>
Fri, 5 Dec 2014 19:41:33 +0000 (11:41 -0800)
committerJunio C Hamano <gitster@pobox.com>
Fri, 5 Dec 2014 19:41:33 +0000 (11:41 -0800)
"git checkout $treeish $path", when $path in the index and the
working tree already matched what is in $treeish at the $path,
still overwrote the $path unnecessarily.

* jk/checkout-from-tree:
checkout $tree: do not throw away unchanged index entries

builtin/checkout.c
t/t2022-checkout-paths.sh
index 5410dacea0699f70cd942837394c06eac99873d1..5a787580368bd3e6410128ff300853a10e4a50ee 100644 (file)
@@ -67,6 +67,7 @@ static int update_some(const unsigned char *sha1, const char *base, int baselen,
 {
        int len;
        struct cache_entry *ce;
+       int pos;
 
        if (S_ISDIR(mode))
                return READ_TREE_RECURSIVE;
@@ -79,6 +80,23 @@ static int update_some(const unsigned char *sha1, const char *base, int baselen,
        ce->ce_flags = create_ce_flags(0) | CE_UPDATE;
        ce->ce_namelen = len;
        ce->ce_mode = create_ce_mode(mode);
+
+       /*
+        * If the entry is the same as the current index, we can leave the old
+        * entry in place. Whether it is UPTODATE or not, checkout_entry will
+        * do the right thing.
+        */
+       pos = cache_name_pos(ce->name, ce->ce_namelen);
+       if (pos >= 0) {
+               struct cache_entry *old = active_cache[pos];
+               if (ce->ce_mode == old->ce_mode &&
+                   !hashcmp(ce->sha1, old->sha1)) {
+                       old->ce_flags |= CE_UPDATE;
+                       free(ce);
+                       return 0;
+               }
+       }
+
        add_cache_entry(ce, ADD_CACHE_OK_TO_ADD | ADD_CACHE_OK_TO_REPLACE);
        return 0;
 }
index 8e3545d8680c5f5179977082849388b1b31c17d8..f46d0499bc6ea95236f7ca05060b8f8fbbdbbc50 100755 (executable)
@@ -61,4 +61,21 @@ test_expect_success 'do not touch unmerged entries matching $path but not in $tr
        test_cmp expect.next0 actual.next0
 '
 
+test_expect_success 'do not touch files that are already up-to-date' '
+       git reset --hard &&
+       echo one >file1 &&
+       echo two >file2 &&
+       git add file1 file2 &&
+       git commit -m base &&
+       echo modified >file1 &&
+       test-chmtime =1000000000 file2 &&
+       git update-index -q --refresh &&
+       git checkout HEAD -- file1 file2 &&
+       echo one >expect &&
+       test_cmp expect file1 &&
+       echo "1000000000        file2" >expect &&
+       test-chmtime -v +0 file2 >actual &&
+       test_cmp expect actual
+'
+
 test_done