Merge branch 'jk/diff-files-assume-unchanged' into maint
authorJunio C Hamano <gitster@pobox.com>
Wed, 25 Jun 2014 18:47:09 +0000 (11:47 -0700)
committerJunio C Hamano <gitster@pobox.com>
Wed, 25 Jun 2014 18:47:09 +0000 (11:47 -0700)
"git diff --find-copies-harder" sometimes pretended as if the mode
bits have changed for paths that are marked with assume-unchanged
bit.

* jk/diff-files-assume-unchanged:
run_diff_files: do not look at uninitialized stat data

diff-lib.c
t/t4039-diff-assume-unchanged.sh
index 044872935c30d84affb1955a7ae03c0986c90bda..875aff864391ed037627462ac39c314f248b5ae6 100644 (file)
@@ -97,7 +97,6 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
                diff_unmerged_stage = 2;
        entries = active_nr;
        for (i = 0; i < entries; i++) {
-               struct stat st;
                unsigned int oldmode, newmode;
                struct cache_entry *ce = active_cache[i];
                int changed;
@@ -115,6 +114,7 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
                        unsigned int wt_mode = 0;
                        int num_compare_stages = 0;
                        size_t path_len;
+                       struct stat st;
 
                        path_len = ce_namelen(ce);
 
@@ -195,26 +195,35 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
                        continue;
 
                /* If CE_VALID is set, don't look at workdir for file removal */
-               changed = (ce->ce_flags & CE_VALID) ? 0 : check_removed(ce, &st);
-               if (changed) {
-                       if (changed < 0) {
-                               perror(ce->name);
+               if (ce->ce_flags & CE_VALID) {
+                       changed = 0;
+                       newmode = ce->ce_mode;
+               } else {
+                       struct stat st;
+
+                       changed = check_removed(ce, &st);
+                       if (changed) {
+                               if (changed < 0) {
+                                       perror(ce->name);
+                                       continue;
+                               }
+                               diff_addremove(&revs->diffopt, '-', ce->ce_mode,
+                                              ce->sha1, !is_null_sha1(ce->sha1),
+                                              ce->name, 0);
                                continue;
                        }
-                       diff_addremove(&revs->diffopt, '-', ce->ce_mode,
-                                      ce->sha1, !is_null_sha1(ce->sha1),
-                                      ce->name, 0);
-                       continue;
+
+                       changed = match_stat_with_submodule(&revs->diffopt, ce, &st,
+                                                           ce_option, &dirty_submodule);
+                       newmode = ce_mode_from_stat(ce, st.st_mode);
                }
-               changed = match_stat_with_submodule(&revs->diffopt, ce, &st,
-                                                   ce_option, &dirty_submodule);
+
                if (!changed && !dirty_submodule) {
                        ce_mark_uptodate(ce);
                        if (!DIFF_OPT_TST(&revs->diffopt, FIND_COPIES_HARDER))
                                continue;
                }
                oldmode = ce->ce_mode;
-               newmode = ce_mode_from_stat(ce, st.st_mode);
                diff_change(&revs->diffopt, oldmode, newmode,
                            ce->sha1, (changed ? null_sha1 : ce->sha1),
                            !is_null_sha1(ce->sha1), (changed ? 0 : !is_null_sha1(ce->sha1)),
index 9d9498bd95c525b008bd3719c2debf87c66ebef2..23c0e357a765f00d807938fccf81a250c371ec4f 100755 (executable)
@@ -28,4 +28,15 @@ test_expect_success 'diff-files does not examine assume-unchanged entries' '
        test -z "$(git diff-files -- one)"
 '
 
+test_expect_success POSIXPERM 'find-copies-harder is not confused by mode bits' '
+       echo content >exec &&
+       chmod +x exec &&
+       git add exec &&
+       git commit -m exec &&
+       git update-index --assume-unchanged exec &&
+       >expect &&
+       git diff-files --find-copies-harder -- exec >actual &&
+       test_cmp expect actual
+'
+
 test_done