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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
diff --git a/include/git2/ignore.h b/include/git2/ignore.h
index e18615e..592c96e 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 6a377e6..5edc5b6 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 ddd0b3d..27f9d85 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);
+}