Commit 1f9e41ee by Russell Belfer

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.
parent 9ca4ff41
...@@ -266,6 +266,7 @@ int git_status_file( ...@@ -266,6 +266,7 @@ int git_status_file(
opts.show = GIT_STATUS_SHOW_INDEX_AND_WORKDIR; opts.show = GIT_STATUS_SHOW_INDEX_AND_WORKDIR;
opts.flags = GIT_STATUS_OPT_INCLUDE_IGNORED | opts.flags = GIT_STATUS_OPT_INCLUDE_IGNORED |
GIT_STATUS_OPT_RECURSE_IGNORED_DIRS |
GIT_STATUS_OPT_INCLUDE_UNTRACKED | GIT_STATUS_OPT_INCLUDE_UNTRACKED |
GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS | GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS |
GIT_STATUS_OPT_INCLUDE_UNMODIFIED; GIT_STATUS_OPT_INCLUDE_UNMODIFIED;
...@@ -281,24 +282,11 @@ int git_status_file( ...@@ -281,24 +282,11 @@ int git_status_file(
} }
if (!error && !sfi.count) { if (!error && !sfi.count) {
git_buf full = GIT_BUF_INIT;
/* if the file actually exists and we still did not get a callback
* for it, then it must be contained inside an ignored directory, so
* mark it as such instead of generating an error.
*/
if (!git_buf_joinpath(&full, git_repository_workdir(repo), path) &&
git_path_exists(full.ptr))
sfi.status = GIT_STATUS_IGNORED;
else {
giterr_set(GITERR_INVALID, giterr_set(GITERR_INVALID,
"Attempt to get status of nonexistent file '%s'", path); "Attempt to get status of nonexistent file '%s'", path);
error = GIT_ENOTFOUND; error = GIT_ENOTFOUND;
} }
git_buf_free(&full);
}
*status_flags = sfi.status; *status_flags = sfi.status;
git__free(sfi.expected); git__free(sfi.expected);
......
...@@ -190,6 +190,18 @@ git_repository *cl_git_sandbox_init(const char *sandbox) ...@@ -190,6 +190,18 @@ git_repository *cl_git_sandbox_init(const char *sandbox)
return _cl_repo; return _cl_repo;
} }
git_repository *cl_git_sandbox_reopen(void)
{
if (_cl_repo) {
git_repository_free(_cl_repo);
_cl_repo = NULL;
cl_git_pass(git_repository_open(&_cl_repo, _cl_sandbox));
}
return _cl_repo;
}
void cl_git_sandbox_cleanup(void) void cl_git_sandbox_cleanup(void)
{ {
if (_cl_repo) { if (_cl_repo) {
......
...@@ -60,6 +60,7 @@ int cl_rename(const char *source, const char *dest); ...@@ -60,6 +60,7 @@ int cl_rename(const char *source, const char *dest);
git_repository *cl_git_sandbox_init(const char *sandbox); git_repository *cl_git_sandbox_init(const char *sandbox);
void cl_git_sandbox_cleanup(void); void cl_git_sandbox_cleanup(void);
git_repository *cl_git_sandbox_reopen(void);
/* Local-repo url helpers */ /* Local-repo url helpers */
const char* cl_git_fixture_url(const char *fixturename); const char* cl_git_fixture_url(const char *fixturename);
......
...@@ -672,3 +672,26 @@ void test_status_worktree__file_status_honors_core_ignorecase_false(void) ...@@ -672,3 +672,26 @@ void test_status_worktree__file_status_honors_core_ignorecase_false(void)
{ {
assert_ignore_case(false, GIT_STATUS_WT_DELETED, GIT_STATUS_WT_NEW); assert_ignore_case(false, GIT_STATUS_WT_DELETED, GIT_STATUS_WT_NEW);
} }
void test_status_worktree__file_status_honors_case_ignorecase_regarding_untracked_files(void)
{
git_repository *repo = cl_git_sandbox_init("status");
unsigned int status;
git_index *index;
cl_repo_set_bool(repo, "core.ignorecase", false);
repo = cl_git_sandbox_reopen();
/* Actually returns GIT_STATUS_IGNORED on Windows */
cl_git_fail_with(git_status_file(&status, repo, "NEW_FILE"), GIT_ENOTFOUND);
cl_git_pass(git_repository_index(&index, repo));
cl_git_pass(git_index_add_bypath(index, "new_file"));
cl_git_pass(git_index_write(index));
git_index_free(index);
/* Actually returns GIT_STATUS_IGNORED on Windows */
cl_git_fail_with(git_status_file(&status, repo, "NEW_FILE"), GIT_ENOTFOUND);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment