Skip to content

Commit 1f9e41e

Browse files
committed
Improve ignore handling in git_status_file
The git_status_file API was doing a hack to deal with files that are inside ignored directories. The status scan was not reporting any file in this case, so git_status_file would attempt a final "stat()" call, and return IGNORED if the file actually existed. On case-insensitive filesystems where core.ignorecase is set incorrectly, this magic check can "succeed" and report a file as ignored when it should actually return ENOTFOUND. Now that we have the GIT_STATUS_OPT_RECURSE_IGNORED_DIRS, we can use that flag to make sure that git_status_file() will look into ignored directories and eliminate the hack completely, so we give the correct error.
1 parent 9ca4ff4 commit 1f9e41e

File tree

4 files changed

+40
-16
lines changed

4 files changed

+40
-16
lines changed

src/status.c

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,7 @@ int git_status_file(
266266

267267
opts.show = GIT_STATUS_SHOW_INDEX_AND_WORKDIR;
268268
opts.flags = GIT_STATUS_OPT_INCLUDE_IGNORED |
269+
GIT_STATUS_OPT_RECURSE_IGNORED_DIRS |
269270
GIT_STATUS_OPT_INCLUDE_UNTRACKED |
270271
GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS |
271272
GIT_STATUS_OPT_INCLUDE_UNMODIFIED;
@@ -281,22 +282,9 @@ int git_status_file(
281282
}
282283

283284
if (!error && !sfi.count) {
284-
git_buf full = GIT_BUF_INIT;
285-
286-
/* if the file actually exists and we still did not get a callback
287-
* for it, then it must be contained inside an ignored directory, so
288-
* mark it as such instead of generating an error.
289-
*/
290-
if (!git_buf_joinpath(&full, git_repository_workdir(repo), path) &&
291-
git_path_exists(full.ptr))
292-
sfi.status = GIT_STATUS_IGNORED;
293-
else {
294-
giterr_set(GITERR_INVALID,
295-
"Attempt to get status of nonexistent file '%s'", path);
296-
error = GIT_ENOTFOUND;
297-
}
298-
299-
git_buf_free(&full);
285+
giterr_set(GITERR_INVALID,
286+
"Attempt to get status of nonexistent file '%s'", path);
287+
error = GIT_ENOTFOUND;
300288
}
301289

302290
*status_flags = sfi.status;

tests-clar/clar_libgit2.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,18 @@ git_repository *cl_git_sandbox_init(const char *sandbox)
190190
return _cl_repo;
191191
}
192192

193+
git_repository *cl_git_sandbox_reopen(void)
194+
{
195+
if (_cl_repo) {
196+
git_repository_free(_cl_repo);
197+
_cl_repo = NULL;
198+
199+
cl_git_pass(git_repository_open(&_cl_repo, _cl_sandbox));
200+
}
201+
202+
return _cl_repo;
203+
}
204+
193205
void cl_git_sandbox_cleanup(void)
194206
{
195207
if (_cl_repo) {

tests-clar/clar_libgit2.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ int cl_rename(const char *source, const char *dest);
6060

6161
git_repository *cl_git_sandbox_init(const char *sandbox);
6262
void cl_git_sandbox_cleanup(void);
63+
git_repository *cl_git_sandbox_reopen(void);
6364

6465
/* Local-repo url helpers */
6566
const char* cl_git_fixture_url(const char *fixturename);

tests-clar/status/worktree.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -672,3 +672,26 @@ void test_status_worktree__file_status_honors_core_ignorecase_false(void)
672672
{
673673
assert_ignore_case(false, GIT_STATUS_WT_DELETED, GIT_STATUS_WT_NEW);
674674
}
675+
676+
void test_status_worktree__file_status_honors_case_ignorecase_regarding_untracked_files(void)
677+
{
678+
git_repository *repo = cl_git_sandbox_init("status");
679+
unsigned int status;
680+
git_index *index;
681+
682+
cl_repo_set_bool(repo, "core.ignorecase", false);
683+
684+
repo = cl_git_sandbox_reopen();
685+
686+
/* Actually returns GIT_STATUS_IGNORED on Windows */
687+
cl_git_fail_with(git_status_file(&status, repo, "NEW_FILE"), GIT_ENOTFOUND);
688+
689+
cl_git_pass(git_repository_index(&index, repo));
690+
691+
cl_git_pass(git_index_add_bypath(index, "new_file"));
692+
cl_git_pass(git_index_write(index));
693+
git_index_free(index);
694+
695+
/* Actually returns GIT_STATUS_IGNORED on Windows */
696+
cl_git_fail_with(git_status_file(&status, repo, "NEW_FILE"), GIT_ENOTFOUND);
697+
}

0 commit comments

Comments
 (0)