Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/libgit2.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRussell Belfer <rb@github.com>2013-08-29 03:44:04 +0400
committerRussell Belfer <rb@github.com>2013-09-17 20:30:06 +0400
commit85d5481206a932d747b2d5587b6d4c7f69993ba6 (patch)
treea66d55c92d70668509efce5b231517467a3f8b7e /src/filter.c
parent0cf77103b218ad3622aff34f3296db1bdd5f0df9 (diff)
Create public filter object and use it
This creates include/sys/filter.h with a basic definition of a git_filter and then converts the internal code to use it. There are related internal objects (git_filter_list) that we will want to publish at some point, but this is a first step.
Diffstat (limited to 'src/filter.c')
-rw-r--r--src/filter.c176
1 files changed, 143 insertions, 33 deletions
diff --git a/src/filter.c b/src/filter.c
index 9f749dcbd..7935e6518 100644
--- a/src/filter.c
+++ b/src/filter.c
@@ -13,62 +13,155 @@
#include "git2/config.h"
#include "blob.h"
-int git_filters_load(git_vector *filters, git_repository *repo, const char *path, int mode)
+typedef struct {
+ git_filter *filter;
+ void *payload;
+} git_filter_entry;
+
+struct git_filter_list {
+ git_array_t(git_filter_entry) filters;
+ git_filter_mode_t mode;
+ git_filter_source source;
+ char path[GIT_FLEX_ARRAY];
+};
+
+typedef struct {
+ const char *filter_name;
+ git_filter *filter;
+} git_filter_def;
+
+static git_array_t(git_filter_def) filter_registry = GIT_ARRAY_INIT;
+
+static int filter_load_defaults(void)
{
- int error;
-
- if (mode == GIT_FILTER_TO_ODB) {
- /* Load the CRLF cleanup filter when writing to the ODB */
- error = git_filter_add__crlf_to_odb(filters, repo, path);
- if (error < 0)
- return error;
- } else {
- error = git_filter_add__crlf_to_workdir(filters, repo, path);
- if (error < 0)
- return error;
+ if (!git_array_size(filter_registry)) {
+ git_filter_def *fdef = git_array_alloc(filter_registry);
+ GITERR_CHECK_ALLOC(fdef);
+
+ fdef->filter_name = GIT_FILTER_CRLF;
+ fdef->filter = git_crlf_filter_new();
+ GITERR_CHECK_ALLOC(fdef->filter);
}
- return (int)filters->length;
+ return 0;
}
-void git_filters_free(git_vector *filters)
+static int git_filter_list_new(
+ git_filter_list **out, git_filter_mode_t mode, const git_filter_source *src)
{
- size_t i;
- git_filter *filter;
+ git_filter_list *fl = NULL;
+ size_t pathlen = src->path ? strlen(src->path) : 0;
+
+ fl = git__calloc(1, sizeof(git_filter_list) + pathlen + 1);
+ GITERR_CHECK_ALLOC(fl);
+
+ fl->mode = mode;
+ if (src->path)
+ memcpy(fl->path, src->path, pathlen);
+ fl->source.repo = src->repo;
+ fl->source.path = fl->path;
+
+ *out = fl;
+ return 0;
+}
+
+int git_filter_list_load(
+ git_filter_list **filters,
+ git_repository *repo,
+ const char *path,
+ git_filter_mode_t mode)
+{
+ int error = 0;
+ git_filter_list *fl = NULL;
+ git_filter_source src = { 0 };
+ git_filter_entry *fe;
+ uint32_t f;
+
+ if (filter_load_defaults() < 0)
+ return -1;
+
+ src.repo = repo;
+ src.path = path;
+
+ for (f = 0; f < git_array_size(filter_registry); ++f) {
+ void *payload = NULL;
+ git_filter_def *fdef = git_array_get(filter_registry, f);
+
+ if (!fdef || !fdef->filter)
+ continue;
- git_vector_foreach(filters, i, filter) {
- if (filter->do_free != NULL)
- filter->do_free(filter);
- else
- git__free(filter);
+ if (fdef->filter->check)
+ error = fdef->filter->check(fdef->filter, &payload, mode, &src);
+
+ if (error == GIT_ENOTFOUND)
+ error = 0;
+ else if (error < 0)
+ break;
+ else {
+ if (!fl && (error = git_filter_list_new(&fl, mode, &src)) < 0)
+ return error;
+
+ fe = git_array_alloc(fl->filters);
+ GITERR_CHECK_ALLOC(fe);
+ fe->filter = fdef->filter;
+ fe->payload = payload;
+ }
+ }
+
+ if (error && fl != NULL) {
+ git_array_clear(fl->filters);
+ git__free(fl);
+ fl = NULL;
+ }
+
+ *filters = fl;
+ return error;
+}
+
+void git_filter_list_free(git_filter_list *fl)
+{
+ uint32_t i;
+
+ if (!fl)
+ return;
+
+ for (i = 0; i < git_array_size(fl->filters); ++i) {
+ git_filter_entry *fe = git_array_get(fl->filters, i);
+ if (fe->filter->cleanup)
+ fe->filter->cleanup(fe->filter, fe->payload);
}
- git_vector_free(filters);
+ git_array_clear(fl->filters);
+ git__free(fl);
}
-int git_filters_apply(git_buf *dest, git_buf *source, git_vector *filters)
+int git_filter_list_apply(
+ git_buf *dest,
+ git_buf *source,
+ git_filter_list *fl)
{
- size_t i;
+ int error = 0;
+ uint32_t i;
unsigned int src;
git_buf *dbuffer[2];
+ if (!fl) {
+ git_buf_swap(dest, source);
+ return 0;
+ }
+
dbuffer[0] = source;
dbuffer[1] = dest;
src = 0;
- if (git_buf_len(source) == 0) {
- git_buf_clear(dest);
- return 0;
- }
-
/* Pre-grow the destination buffer to more or less the size
* we expect it to have */
if (git_buf_grow(dest, git_buf_len(source)) < 0)
return -1;
- for (i = 0; i < filters->length; ++i) {
- git_filter *filter = git_vector_get(filters, i);
+ for (i = 0; i < git_array_size(fl->filters); ++i) {
+ git_filter_entry *fe = git_array_get(fl->filters, i);
unsigned int dst = 1 - src;
git_buf_clear(dbuffer[dst]);
@@ -79,8 +172,25 @@ int git_filters_apply(git_buf *dest, git_buf *source, git_vector *filters)
* of the double buffering (so that the text goes through
* cleanly).
*/
- if (filter->apply(filter, dbuffer[dst], dbuffer[src]) == 0)
- src = dst;
+ {
+ git_buffer srcb = GIT_BUFFER_FROM_BUF(dbuffer[src]);
+ git_buffer dstb = GIT_BUFFER_FROM_BUF(dbuffer[dst]);
+
+ error = fe->filter->apply(
+ fe->filter, &fe->payload, fl->mode, &dstb, &srcb, &fl->source);
+
+ if (error == GIT_ENOTFOUND)
+ error = 0;
+ else if (error < 0) {
+ git_buf_clear(dest);
+ return error;
+ }
+ else {
+ git_buf_from_buffer(dbuffer[src], &srcb);
+ git_buf_from_buffer(dbuffer[dst], &dstb);
+ src = dst;
+ }
+ }
if (git_buf_oom(dbuffer[dst]))
return -1;