diff options
-rw-r--r-- | src/diff.c | 15 | ||||
-rw-r--r-- | src/iterator.c | 2 | ||||
-rw-r--r-- | tests/diff/workdir.c | 4 | ||||
-rw-r--r-- | tests/status/worktree.c | 6 |
4 files changed, 19 insertions, 8 deletions
diff --git a/src/diff.c b/src/diff.c index aa880650a..4c028ca4e 100644 --- a/src/diff.c +++ b/src/diff.c @@ -664,6 +664,7 @@ static int maybe_modified( unsigned int omode = oitem->mode; unsigned int nmode = nitem->mode; bool new_is_workdir = (info->new_iter->type == GIT_ITERATOR_TYPE_WORKDIR); + bool modified_uncertain = false; const char *matched_pathspec; int error = 0; @@ -731,15 +732,21 @@ static int maybe_modified( /* if the stat data looks different, then mark modified - this just * means that the OID will be recalculated below to confirm change */ - else if (omode != nmode || - oitem->file_size != nitem->file_size || - !diff_time_eq(&oitem->mtime, &nitem->mtime, use_nanos) || + else if (omode != nmode || oitem->file_size != nitem->file_size) { + status = GIT_DELTA_MODIFIED; + modified_uncertain = + (oitem->file_size <= 0 && nitem->file_size > 0); + } + else if (!diff_time_eq(&oitem->mtime, &nitem->mtime, use_nanos) || (use_ctime && !diff_time_eq(&oitem->ctime, &nitem->ctime, use_nanos)) || oitem->ino != nitem->ino || oitem->uid != nitem->uid || oitem->gid != nitem->gid) + { status = GIT_DELTA_MODIFIED; + modified_uncertain = true; + } } /* if mode is GITLINK and submodules are ignored, then skip */ @@ -750,7 +757,7 @@ static int maybe_modified( /* if we got here and decided that the files are modified, but we * haven't calculated the OID of the new item, then calculate it now */ - if (status == GIT_DELTA_MODIFIED && git_oid_iszero(&nitem->id)) { + if (modified_uncertain && git_oid_iszero(&nitem->id)) { if (git_oid_iszero(&noid)) { if ((error = git_diff__oid_for_file(&noid, diff, nitem->path, nitem->mode, nitem->file_size)) < 0) diff --git a/src/iterator.c b/src/iterator.c index 5e668b50c..03058b956 100644 --- a/src/iterator.c +++ b/src/iterator.c @@ -1306,7 +1306,7 @@ static int workdir_iterator__enter_dir(fs_iterator *fi) /* convert submodules to GITLINK and remove trailing slashes */ git_vector_foreach(&ff->entries, pos, entry) { - if (!S_ISDIR(entry->st.st_mode)) + if (!S_ISDIR(entry->st.st_mode) || !strcmp(GIT_DIR, entry->path)) continue; GIT_PERF_INC(fi->base.submodule_lookups); diff --git a/tests/diff/workdir.c b/tests/diff/workdir.c index 03a3ff418..84c8866e0 100644 --- a/tests/diff/workdir.c +++ b/tests/diff/workdir.c @@ -67,8 +67,8 @@ void test_diff_workdir__to_index(void) #ifdef GIT_PERF cl_assert_equal_sz( 13 /* in root */ + 3 /* in subdir */, diff->stat_calls); - cl_assert_equal_sz(9, diff->oid_calculations); - cl_assert_equal_sz(2, diff->submodule_lookups); + cl_assert_equal_sz(5, diff->oid_calculations); + cl_assert_equal_sz(1, diff->submodule_lookups); #endif } diff --git a/tests/status/worktree.c b/tests/status/worktree.c index def3d60f0..f51c61864 100644 --- a/tests/status/worktree.c +++ b/tests/status/worktree.c @@ -578,7 +578,11 @@ void test_status_worktree__line_endings_dont_count_as_changes_with_autocrlf(void cl_git_pass(git_status_file(&status, repo, "current_file")); - cl_assert_equal_i(GIT_STATUS_CURRENT, status); + /* stat data on file should no longer match stat cache, even though + * file diff will be empty because of line-ending conversion - matches + * the Git command-line behavior here. + */ + cl_assert_equal_i(GIT_STATUS_WT_MODIFIED, status); } void test_status_worktree__line_endings_dont_count_as_changes_with_autocrlf_issue_1397(void) |