summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/git2/ignore.h7
-rw-r--r--src/ignore.c34
-rw-r--r--tests-clar/status/ignore.c38
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);
+}