diff options
Diffstat (limited to 'src/diff.c')
-rw-r--r-- | src/diff.c | 41 |
1 files changed, 26 insertions, 15 deletions
diff --git a/src/diff.c b/src/diff.c index 90baa9588..e3167b90e 100644 --- a/src/diff.c +++ b/src/diff.c @@ -214,7 +214,9 @@ static int diff_delta__from_two( git_diff_list *diff, git_delta_t status, const git_index_entry *old_entry, + uint32_t old_mode, const git_index_entry *new_entry, + uint32_t new_mode, git_oid *new_oid) { git_diff_delta *delta; @@ -224,19 +226,22 @@ static int diff_delta__from_two( return 0; if ((diff->opts.flags & GIT_DIFF_REVERSE) != 0) { - const git_index_entry *temp = old_entry; + uint32_t temp_mode = old_mode; + const git_index_entry *temp_entry = old_entry; old_entry = new_entry; - new_entry = temp; + new_entry = temp_entry; + old_mode = new_mode; + new_mode = temp_mode; } delta = diff_delta__alloc(diff, status, old_entry->path); GITERR_CHECK_ALLOC(delta); - delta->old_file.mode = old_entry->mode; + delta->old_file.mode = old_mode; git_oid_cpy(&delta->old_file.oid, &old_entry->oid); delta->old_file.flags |= GIT_DIFF_FILE_VALID_OID; - delta->new_file.mode = new_entry->mode; + delta->new_file.mode = new_mode; git_oid_cpy(&delta->new_file.oid, new_oid ? new_oid : &new_entry->oid); if (new_oid || !git_oid_iszero(&new_entry->oid)) delta->new_file.flags |= GIT_DIFF_FILE_VALID_OID; @@ -300,7 +305,7 @@ static git_diff_list *git_diff_list_alloc( if (config_bool(cfg, "core.ignorestat", 0)) diff->diffcaps = diff->diffcaps | GIT_DIFFCAPS_ASSUME_UNCHANGED; if (config_bool(cfg, "core.filemode", 1)) - diff->diffcaps = diff->diffcaps | GIT_DIFFCAPS_TRUST_EXEC_BIT; + diff->diffcaps = diff->diffcaps | GIT_DIFFCAPS_TRUST_MODE_BITS; if (config_bool(cfg, "core.trustctime", 1)) diff->diffcaps = diff->diffcaps | GIT_DIFFCAPS_TRUST_CTIME; /* Don't set GIT_DIFFCAPS_USE_DEV - compile time option in core git */ @@ -419,7 +424,7 @@ static int oid_for_workdir_item( return result; } -#define EXEC_BIT_MASK 0000111 +#define MODE_BITS_MASK 0000777 static int maybe_modified( git_iterator *old_iter, @@ -443,13 +448,13 @@ static int maybe_modified( !(diff->diffcaps & GIT_DIFFCAPS_HAS_SYMLINKS)) nmode = GIT_MODE_TYPE(omode) | (nmode & GIT_MODE_PERMS_MASK); - /* on platforms with no execmode, clear exec bit from comparisons */ - if (!(diff->diffcaps & GIT_DIFFCAPS_TRUST_EXEC_BIT)) { - omode = omode & ~EXEC_BIT_MASK; - nmode = nmode & ~EXEC_BIT_MASK; - } + /* on platforms with no execmode, just preserve old mode */ + if (!(diff->diffcaps & GIT_DIFFCAPS_TRUST_MODE_BITS) && + (nmode & MODE_BITS_MASK) != (omode & MODE_BITS_MASK) && + new_iter->type == GIT_ITERATOR_WORKDIR) + nmode = (nmode & ~MODE_BITS_MASK) | (omode & MODE_BITS_MASK); - /* support "assume unchanged" (badly, b/c we still stat everything) */ + /* support "assume unchanged" (poorly, b/c we still stat everything) */ if ((diff->diffcaps & GIT_DIFFCAPS_ASSUME_UNCHANGED) != 0) status = (oitem->flags_extended & GIT_IDXENTRY_INTENT_TO_ADD) ? GIT_DELTA_MODIFIED : GIT_DELTA_UNMODIFIED; @@ -471,8 +476,13 @@ static int maybe_modified( omode == nmode) status = GIT_DELTA_UNMODIFIED; - /* if we have a workdir item with an unknown oid, check deeper */ - else if (git_oid_iszero(&nitem->oid) && new_iter->type == GIT_ITERATOR_WORKDIR) { + /* if modes match and we have an unknown OID and a workdir iterator, + * then check deeper for matching + */ + else if (omode == nmode && + git_oid_iszero(&nitem->oid) && + new_iter->type == GIT_ITERATOR_WORKDIR) + { /* TODO: add check against index file st_mtime to avoid racy-git */ /* if they files look exactly alike, then we'll assume the same */ @@ -517,7 +527,8 @@ static int maybe_modified( use_noid = &noid; } - return diff_delta__from_two(diff, status, oitem, nitem, use_noid); + return diff_delta__from_two( + diff, status, oitem, omode, nitem, nmode, use_noid); } static int diff_from_iterators( |