diff --git a/src/attr.c b/src/attr.c index 38420807a..102d0248c 100644 --- a/src/attr.c +++ b/src/attr.c @@ -55,7 +55,7 @@ int git_attr_get( *value = NULL; - if (git_attr_path__init(&path, pathname, git_repository_workdir(repo)) < 0) + if (git_attr_path__init(&path, pathname, git_repository_workdir(repo), GIT_DIR_FLAG_UNKNOWN) < 0) return -1; if ((error = collect_attr_files(repo, NULL, flags, pathname, &files)) < 0) @@ -114,7 +114,7 @@ int git_attr_get_many_with_session( assert(values && repo && names); - if (git_attr_path__init(&path, pathname, git_repository_workdir(repo)) < 0) + if (git_attr_path__init(&path, pathname, git_repository_workdir(repo), GIT_DIR_FLAG_UNKNOWN) < 0) return -1; if ((error = collect_attr_files(repo, attr_session, flags, pathname, &files)) < 0) @@ -193,7 +193,7 @@ int git_attr_foreach( assert(repo && callback); - if (git_attr_path__init(&path, pathname, git_repository_workdir(repo)) < 0) + if (git_attr_path__init(&path, pathname, git_repository_workdir(repo), GIT_DIR_FLAG_UNKNOWN) < 0) return -1; if ((error = collect_attr_files(repo, NULL, flags, pathname, &files)) < 0 || diff --git a/src/attr_file.c b/src/attr_file.c index eed39661f..ef98aacc2 100644 --- a/src/attr_file.c +++ b/src/attr_file.c @@ -457,7 +457,7 @@ git_attr_assignment *git_attr_rule__lookup_assignment( } int git_attr_path__init( - git_attr_path *info, const char *path, const char *base) + git_attr_path *info, const char *path, const char *base, git_dir_flag dir_flag) { ssize_t root; @@ -488,7 +488,21 @@ int git_attr_path__init( if (!info->basename || !*info->basename) info->basename = info->path; - info->is_dir = (int)git_path_isdir(info->full.ptr); + switch (dir_flag) + { + case GIT_DIR_FLAG_FALSE: + info->is_dir = 0; + break; + + case GIT_DIR_FLAG_TRUE: + info->is_dir = 1; + break; + + case GIT_DIR_FLAG_UNKNOWN: + default: + info->is_dir = (int)git_path_isdir(info->full.ptr); + break; + } return 0; } diff --git a/src/attr_file.h b/src/attr_file.h index aa9a16de0..388ecf4c0 100644 --- a/src/attr_file.h +++ b/src/attr_file.h @@ -202,8 +202,10 @@ extern bool git_attr_rule__match( extern git_attr_assignment *git_attr_rule__lookup_assignment( git_attr_rule *rule, const char *name); +typedef enum { GIT_DIR_FLAG_TRUE = 1, GIT_DIR_FLAG_FALSE = 0, GIT_DIR_FLAG_UNKNOWN = -1 } git_dir_flag; + extern int git_attr_path__init( - git_attr_path *info, const char *path, const char *base); + git_attr_path *info, const char *path, const char *base, git_dir_flag is_dir); extern void git_attr_path__free(git_attr_path *info); diff --git a/src/ignore.c b/src/ignore.c index 3a5efedce..7ad8500e8 100644 --- a/src/ignore.c +++ b/src/ignore.c @@ -388,7 +388,7 @@ static bool ignore_lookup_in_rules( } int git_ignore__lookup( - int *out, git_ignores *ignores, const char *pathname) + int *out, git_ignores *ignores, const char *pathname, git_dir_flag dir_flag) { unsigned int i; git_attr_file *file; @@ -397,7 +397,7 @@ int git_ignore__lookup( *out = GIT_IGNORE_NOTFOUND; if (git_attr_path__init( - &path, pathname, git_repository_workdir(ignores->repo)) < 0) + &path, pathname, git_repository_workdir(ignores->repo), dir_flag) < 0) return -1; /* first process builtins - success means path was found */ @@ -470,7 +470,7 @@ int git_ignore_path_is_ignored( memset(&path, 0, sizeof(path)); memset(&ignores, 0, sizeof(ignores)); - if ((error = git_attr_path__init(&path, pathname, workdir)) < 0 || + if ((error = git_attr_path__init(&path, pathname, workdir, GIT_DIR_FLAG_UNKNOWN)) < 0 || (error = git_ignore__for_path(repo, path.path, &ignores)) < 0) goto cleanup; diff --git a/src/ignore.h b/src/ignore.h index 77668c661..d40bd60f9 100644 --- a/src/ignore.h +++ b/src/ignore.h @@ -49,7 +49,7 @@ enum { GIT_IGNORE_TRUE = 1, }; -extern int git_ignore__lookup(int *out, git_ignores *ign, const char *path); +extern int git_ignore__lookup(int *out, git_ignores *ign, const char *path, git_dir_flag dir_flag); /* command line Git sometimes generates an error message if given a * pathspec that contains an exact match to an ignored file (provided diff --git a/src/iterator.c b/src/iterator.c index 9ddacebd1..8bab1aab0 100644 --- a/src/iterator.c +++ b/src/iterator.c @@ -1344,6 +1344,16 @@ static int is_submodule(workdir_iterator *wi, git_path_with_stat *ie) return is_submodule; } +GIT_INLINE(git_dir_flag) git_entry__dir_flag(git_index_entry *entry) { +#if defined(GIT_WIN32) && !defined(__MINGW32__) + return (entry && entry->mode) + ? S_ISDIR(entry->mode) ? GIT_DIR_FLAG_TRUE : GIT_DIR_FLAG_FALSE + : GIT_DIR_FLAG_UNKNOWN; +#else + return GIT_DIR_FLAG_UNKNOWN; +#endif +} + static int workdir_iterator__enter_dir(fs_iterator *fi) { workdir_iterator *wi = (workdir_iterator *)fi; @@ -1352,9 +1362,10 @@ static int workdir_iterator__enter_dir(fs_iterator *fi) git_path_with_stat *entry; bool found_submodules = false; + git_dir_flag dir_flag = git_entry__dir_flag(&fi->entry); + /* check if this directory is ignored */ - if (git_ignore__lookup( - &ff->is_ignored, &wi->ignores, fi->path.ptr + fi->root_len) < 0) { + if (git_ignore__lookup(&ff->is_ignored, &wi->ignores, fi->path.ptr + fi->root_len, dir_flag) < 0) { giterr_clear(); ff->is_ignored = GIT_IGNORE_NOTFOUND; } @@ -1483,7 +1494,6 @@ int git_iterator_for_workdir_ext( return fs_iterator__initialize(out, &wi->fi, repo_workdir); } - void git_iterator_free(git_iterator *iter) { if (iter == NULL) @@ -1574,8 +1584,9 @@ int git_iterator_current_parent_tree( static void workdir_iterator_update_is_ignored(workdir_iterator *wi) { - if (git_ignore__lookup( - &wi->is_ignored, &wi->ignores, wi->fi.entry.path) < 0) { + git_dir_flag dir_flag = git_entry__dir_flag(&wi->fi.entry); + + if (git_ignore__lookup(&wi->is_ignored, &wi->ignores, wi->fi.entry.path, dir_flag) < 0) { giterr_clear(); wi->is_ignored = GIT_IGNORE_NOTFOUND; } diff --git a/tests/attr/lookup.c b/tests/attr/lookup.c index 030ea075d..71e87cbae 100644 --- a/tests/attr/lookup.c +++ b/tests/attr/lookup.c @@ -13,7 +13,7 @@ void test_attr_lookup__simple(void) cl_assert_equal_s(cl_fixture("attr/attr0"), file->entry->path); cl_assert(file->rules.length == 1); - cl_git_pass(git_attr_path__init(&path, "test", NULL)); + cl_git_pass(git_attr_path__init(&path, "test", NULL, GIT_DIR_FLAG_UNKNOWN)); cl_assert_equal_s("test", path.path); cl_assert_equal_s("test", path.basename); cl_assert(!path.is_dir); @@ -36,7 +36,7 @@ static void run_test_cases(git_attr_file *file, struct attr_expected *cases, int int error; for (c = cases; c->path != NULL; c++) { - cl_git_pass(git_attr_path__init(&path, c->path, NULL)); + cl_git_pass(git_attr_path__init(&path, c->path, NULL, GIT_DIR_FLAG_UNKNOWN)); if (force_dir) path.is_dir = 1; @@ -133,7 +133,7 @@ void test_attr_lookup__match_variants(void) cl_assert_equal_s(cl_fixture("attr/attr1"), file->entry->path); cl_assert(file->rules.length == 10); - cl_git_pass(git_attr_path__init(&path, "/testing/for/pat0", NULL)); + cl_git_pass(git_attr_path__init(&path, "/testing/for/pat0", NULL, GIT_DIR_FLAG_UNKNOWN)); cl_assert_equal_s("pat0", path.basename); run_test_cases(file, cases, 0);