From 02df42ddbf87820011aa4ccba9adfde52670e5e2 Mon Sep 17 00:00:00 2001 From: Russell Belfer Date: Mon, 19 Nov 2012 16:33:30 -0800 Subject: [PATCH] Set up default internal ignores This adds "." ".." and ".git" to the internal ignores list by default - asking about paths with these files will always say that they are ignored. --- include/git2/ignore.h | 7 ++++--- src/ignore.c | 34 +++++++++++++++++++++------------- tests-clar/status/ignore.c | 38 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 16 deletions(-) diff --git a/include/git2/ignore.h b/include/git2/ignore.h index e18615edd..592c96e65 100644 --- a/include/git2/ignore.h +++ b/include/git2/ignore.h @@ -41,9 +41,10 @@ GIT_EXTERN(int) git_ignore_add_rule( /** * Clear ignore rules that were explicitly added. * - * Clears the internal ignore rules that have been set up. This will not - * turn off the rules in .gitignore files that actually exist in the - * filesystem. + * Resets to the default internal ignore rules. This will not turn off + * rules in .gitignore files that actually exist in the filesystem. + * + * The default internal ignores ignore ".", ".." and ".git" entries. * * @param repo The repository to remove ignore rules from. * @return 0 on success diff --git a/src/ignore.c b/src/ignore.c index 6a377e60d..5edc5b65b 100644 --- a/src/ignore.c +++ b/src/ignore.c @@ -7,6 +7,8 @@ #define GIT_IGNORE_FILE_INREPO "info/exclude" #define GIT_IGNORE_FILE ".gitignore" +#define GIT_IGNORE_DEFAULT_RULES ".\n..\n.git\n" + static int parse_ignore_file( git_repository *repo, void *parsedata, const char *buffer, git_attr_file *ignores) { @@ -88,6 +90,19 @@ static int push_one_ignore(void *ref, git_buf *path) return push_ignore_file(ign->repo, ign, &ign->ign_path, path->ptr, GIT_IGNORE_FILE); } +static int get_internal_ignores(git_attr_file **ign, git_repository *repo) +{ + int error; + + if (!(error = git_attr_cache__init(repo))) + error = git_attr_cache__internal_file(repo, GIT_IGNORE_INTERNAL, ign); + + if (!error && !(*ign)->rules.length) + error = parse_ignore_file(repo, NULL, GIT_IGNORE_DEFAULT_RULES, *ign); + + return error; +} + int git_ignore__for_path( git_repository *repo, const char *path, @@ -129,8 +144,7 @@ int git_ignore__for_path( goto cleanup; /* set up internals */ - error = git_attr_cache__internal_file( - repo, GIT_IGNORE_INTERNAL, &ignores->ign_internal); + error = get_internal_ignores(&ignores->ign_internal, repo); if (error < 0) goto cleanup; @@ -239,16 +253,6 @@ cleanup: return 0; } -static int get_internal_ignores(git_attr_file **ign, git_repository *repo) -{ - int error; - - if (!(error = git_attr_cache__init(repo))) - error = git_attr_cache__internal_file(repo, GIT_IGNORE_INTERNAL, ign); - - return error; -} - int git_ignore_add_rule( git_repository *repo, const char *rules) @@ -268,9 +272,13 @@ int git_ignore_clear_internal_rules( int error; git_attr_file *ign_internal; - if (!(error = get_internal_ignores(&ign_internal, repo))) + if (!(error = get_internal_ignores(&ign_internal, repo))) { git_attr_file__clear_rules(ign_internal); + return parse_ignore_file( + repo, NULL, GIT_IGNORE_DEFAULT_RULES, ign_internal); + } + return error; } diff --git a/tests-clar/status/ignore.c b/tests-clar/status/ignore.c index ddd0b3d6e..27f9d85b9 100644 --- a/tests-clar/status/ignore.c +++ b/tests-clar/status/ignore.c @@ -341,3 +341,41 @@ void test_status_ignore__internal_ignores_inside_deep_paths(void) cl_git_pass(git_status_should_ignore(&ignored, g_repo, "xthis/is/deep")); cl_assert(!ignored); } + +void test_status_ignore__automatically_ignore_bad_files(void) +{ + int ignored; + + g_repo = cl_git_sandbox_init("empty_standard_repo"); + + cl_git_pass(git_status_should_ignore(&ignored, g_repo, ".git")); + cl_assert(ignored); + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "this/file/.")); + cl_assert(ignored); + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "path/../funky")); + cl_assert(ignored); + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "path/whatever.c")); + cl_assert(!ignored); + + cl_git_pass(git_ignore_add_rule(g_repo, "*.c\n")); + + cl_git_pass(git_status_should_ignore(&ignored, g_repo, ".git")); + cl_assert(ignored); + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "this/file/.")); + cl_assert(ignored); + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "path/../funky")); + cl_assert(ignored); + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "path/whatever.c")); + cl_assert(ignored); + + cl_git_pass(git_ignore_clear_internal_rules(g_repo)); + + cl_git_pass(git_status_should_ignore(&ignored, g_repo, ".git")); + cl_assert(ignored); + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "this/file/.")); + cl_assert(ignored); + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "path/../funky")); + cl_assert(ignored); + cl_git_pass(git_status_should_ignore(&ignored, g_repo, "path/whatever.c")); + cl_assert(!ignored); +}