Merge pull request #3205 from ethomson/crlf_query Introduce `git_filter_list_contains`
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 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8d4b733..1fff2d4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -133,6 +133,9 @@ support for HTTPS connections insead of OpenSSL.
path. For this, `GIT_CREDTYPE_SSH_MEMORY` and
`git_cred_ssh_key_memory_new()` have been added.
+* `git_filter_list_contains` will indicate whether a particular
+ filter will be run in the given filter list.
+
### API removals
* `git_remote_save()` and `git_remote_clear_refspecs()` have been
diff --git a/include/git2/filter.h b/include/git2/filter.h
index dc59e63..1828903 100644
--- a/include/git2/filter.h
+++ b/include/git2/filter.h
@@ -96,6 +96,22 @@ GIT_EXTERN(int) git_filter_list_load(
uint32_t flags);
/**
+ * Query the filter list to see if a given filter (by name) will run.
+ * The built-in filters "crlf" and "ident" can be queried, otherwise this
+ * is the name of the filter specified by the filter attribute.
+ *
+ * This will return 0 if the given filter is not in the list, or 1 if
+ * the filter will be applied.
+ *
+ * @param filters A loaded git_filter_list (or NULL)
+ * @param name The name of the filter to query
+ * @return 1 if the filter is in the list, 0 otherwise
+ */
+GIT_EXTERN(int) git_filter_list_contains(
+ git_filter_list *filters,
+ const char *name);
+
+/**
* Apply filter list to a data buffer.
*
* See `git2/buffer.h` for background on `git_buf` objects.
diff --git a/src/filter.c b/src/filter.c
index 3c6a0a9..e25d37c 100644
--- a/src/filter.c
+++ b/src/filter.c
@@ -27,6 +27,7 @@ struct git_filter_source {
};
typedef struct {
+ const char *filter_name;
git_filter *filter;
void *payload;
} git_filter_entry;
@@ -526,7 +527,9 @@ int git_filter_list__load_ext(
fe = git_array_alloc(fl->filters);
GITERR_CHECK_ALLOC(fe);
- fe->filter = fdef->filter;
+
+ fe->filter = fdef->filter;
+ fe->filter_name = fdef->filter_name;
fe->payload = payload;
}
}
@@ -574,6 +577,25 @@ void git_filter_list_free(git_filter_list *fl)
git__free(fl);
}
+int git_filter_list_contains(
+ git_filter_list *fl,
+ const char *name)
+{
+ size_t i;
+
+ assert(name);
+
+ if (!fl)
+ return 0;
+
+ for (i = 0; i < fl->filters.size; i++) {
+ if (strcmp(fl->filters.ptr[i].filter_name, name) == 0)
+ return 1;
+ }
+
+ return 0;
+}
+
int git_filter_list_push(
git_filter_list *fl, git_filter *filter, void *payload)
{
diff --git a/tests/filter/query.c b/tests/filter/query.c
new file mode 100644
index 0000000..6889d71
--- /dev/null
+++ b/tests/filter/query.c
@@ -0,0 +1,91 @@
+#include "clar_libgit2.h"
+#include "git2/sys/filter.h"
+#include "crlf.h"
+#include "buffer.h"
+
+static git_repository *g_repo = NULL;
+
+void test_filter_query__initialize(void)
+{
+ g_repo = cl_git_sandbox_init("crlf");
+
+ cl_git_mkfile("crlf/.gitattributes",
+ "*.txt text\n"
+ "*.bin binary\n"
+ "*.crlf text eol=crlf\n"
+ "*.lf text eol=lf\n"
+ "*.binident binary ident\n"
+ "*.ident text ident\n"
+ "*.identcrlf ident text eol=crlf\n"
+ "*.identlf ident text eol=lf\n"
+ "*.custom custom ident text\n");
+}
+
+void test_filter_query__cleanup(void)
+{
+ cl_git_sandbox_cleanup();
+}
+
+static int filter_for(const char *filename, const char *filter)
+{
+ git_filter_list *fl;
+ int filtered;
+
+ cl_git_pass(git_filter_list_load(
+ &fl, g_repo, NULL, filename, GIT_FILTER_TO_WORKTREE, 0));
+ filtered = git_filter_list_contains(fl, filter);
+ git_filter_list_free(fl);
+
+ return filtered;
+}
+
+void test_filter_query__filters(void)
+{
+ cl_assert_equal_i(1, filter_for("text.txt", "crlf"));
+ cl_assert_equal_i(0, filter_for("binary.bin", "crlf"));
+
+ cl_assert_equal_i(1, filter_for("foo.lf", "crlf"));
+ cl_assert_equal_i(0, filter_for("foo.lf", "ident"));
+
+ cl_assert_equal_i(1, filter_for("id.ident", "crlf"));
+ cl_assert_equal_i(1, filter_for("id.ident", "ident"));
+
+ cl_assert_equal_i(0, filter_for("id.binident", "crlf"));
+ cl_assert_equal_i(1, filter_for("id.binident", "ident"));
+}
+
+void test_filter_query__autocrlf_true_implies_crlf(void)
+{
+ cl_repo_set_bool(g_repo, "core.autocrlf", true);
+ cl_assert_equal_i(1, filter_for("not_in_gitattributes", "crlf"));
+ cl_assert_equal_i(1, filter_for("foo.txt", "crlf"));
+ cl_assert_equal_i(0, filter_for("foo.bin", "crlf"));
+ cl_assert_equal_i(1, filter_for("foo.lf", "crlf"));
+
+ cl_repo_set_bool(g_repo, "core.autocrlf", false);
+ cl_assert_equal_i(0, filter_for("not_in_gitattributes", "crlf"));
+ cl_assert_equal_i(1, filter_for("foo.txt", "crlf"));
+ cl_assert_equal_i(0, filter_for("foo.bin", "crlf"));
+ cl_assert_equal_i(1, filter_for("foo.lf", "crlf"));
+}
+
+void test_filter_query__unknown(void)
+{
+ cl_assert_equal_i(1, filter_for("foo.custom", "crlf"));
+ cl_assert_equal_i(1, filter_for("foo.custom", "ident"));
+ cl_assert_equal_i(0, filter_for("foo.custom", "custom"));
+}
+
+void test_filter_query__custom(void)
+{
+ git_filter custom = { GIT_FILTER_VERSION };
+
+ cl_git_pass(git_filter_register(
+ "custom", &custom, 42));
+
+ cl_assert_equal_i(1, filter_for("foo.custom", "crlf"));
+ cl_assert_equal_i(1, filter_for("foo.custom", "ident"));
+ cl_assert_equal_i(1, filter_for("foo.custom", "custom"));
+
+ git_filter_unregister("custom");
+}