summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRussell Belfer <rb@github.com>2013-09-11 14:23:39 -0700
committerRussell Belfer <rb@github.com>2013-09-17 09:31:45 -0700
commit40cb40fab93281c808255d980bbe81a18a4d9e9a (patch)
tree349cfd168a3a704288a3222f69374064e7d86c91 /src
parent0646634e2fea3e0adf724e0b7b15118574b589fc (diff)
downloadlibgit2-40cb40fab93281c808255d980bbe81a18a4d9e9a.tar.gz
Add functions to manipulate filter lists
Extend the git2/sys/filter API with functions to look up a filter and add it manually to a filter list. This requires some trickery because the regular attribute lookups and checks are bypassed when this happens, but in the right hands, it will allow a user to have granular control over applying filters.
Diffstat (limited to 'src')
-rw-r--r--src/buffer.c3
-rw-r--r--src/crlf.c14
-rw-r--r--src/filter.c52
3 files changed, 61 insertions, 8 deletions
diff --git a/src/buffer.c b/src/buffer.c
index aaebac776..07725b9cc 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -548,9 +548,10 @@ int git_buffer_resize(git_buffer *buffer, size_t want_size)
int git_buffer_copy(
git_buffer *buffer, const void *data, size_t datalen)
{
- if (git_buffer__resize(buffer, datalen, false) < 0)
+ if (git_buffer__resize(buffer, datalen + 1, false) < 0)
return -1;
memcpy(buffer->ptr, data, datalen);
+ buffer->ptr[datalen] = '\0';
buffer->size = datalen;
return 0;
}
diff --git a/src/crlf.c b/src/crlf.c
index e974208a6..99c154f70 100644
--- a/src/crlf.c
+++ b/src/crlf.c
@@ -86,6 +86,9 @@ static int has_cr_in_index(const git_filter_source *src)
git_off_t blobsize;
bool found_cr;
+ if (!path)
+ return false;
+
if (git_repository_index__weakptr(&index, repo) < 0) {
giterr_clear();
return false;
@@ -189,9 +192,7 @@ static const char *line_ending(struct crlf_attrs *ca)
switch (ca->eol) {
case GIT_EOL_UNSET:
- return GIT_EOL_NATIVE == GIT_EOL_CRLF
- ? "\r\n"
- : "\n";
+ return GIT_EOL_NATIVE == GIT_EOL_CRLF ? "\r\n" : "\n";
case GIT_EOL_CRLF:
return "\r\n";
@@ -302,7 +303,12 @@ static int crlf_apply(
const git_buffer *from,
const git_filter_source *src)
{
- GIT_UNUSED(self);
+ /* initialize payload in case `check` was bypassed */
+ if (!*payload) {
+ int error = crlf_check(self, payload, src, NULL);
+ if (error < 0 && error != GIT_ENOTFOUND)
+ return error;
+ }
if (git_filter_source_mode(src) == GIT_FILTER_SMUDGE)
return crlf_apply_to_workdir(*payload, to, from);
diff --git a/src/filter.c b/src/filter.c
index 73c2ceacb..79ccac0cf 100644
--- a/src/filter.c
+++ b/src/filter.c
@@ -181,7 +181,13 @@ static int filter_def_name_key_check(const void *key, const void *fdef)
{
const char *name =
fdef ? ((const git_filter_def *)fdef)->filter_name : NULL;
- return name ? -1 : git__strcmp(key, name);
+ return name ? git__strcmp(key, name) : -1;
+}
+
+static int filter_def_filter_key_check(const void *key, const void *fdef)
+{
+ const void *filter = fdef ? ((const git_filter_def *)fdef)->filter : NULL;
+ return (key == filter) ? 0 : -1;
}
static int filter_registry_find(size_t *pos, const char *name)
@@ -331,7 +337,7 @@ git_filter_mode_t git_filter_source_mode(const git_filter_source *src)
return src->mode;
}
-static int git_filter_list_new(
+static int filter_list_new(
git_filter_list **out, const git_filter_source *src)
{
git_filter_list *fl = NULL;
@@ -391,6 +397,16 @@ static int filter_list_check_attributes(
return error;
}
+int git_filter_list_new(
+ git_filter_list **out, git_repository *repo, git_filter_mode_t mode)
+{
+ git_filter_source src = { 0 };
+ src.repo = repo;
+ src.path = NULL;
+ src.mode = mode;
+ return filter_list_new(out, &src);
+}
+
int git_filter_list_load(
git_filter_list **filters,
git_repository *repo,
@@ -441,7 +457,7 @@ int git_filter_list_load(
else if (error < 0)
break;
else {
- if (!fl && (error = git_filter_list_new(&fl, &src)) < 0)
+ if (!fl && (error = filter_list_new(&fl, &src)) < 0)
return error;
fe = git_array_alloc(fl->filters);
@@ -478,6 +494,36 @@ void git_filter_list_free(git_filter_list *fl)
git__free(fl);
}
+int git_filter_list_push(
+ git_filter_list *fl, git_filter *filter, void *payload)
+{
+ int error = 0;
+ size_t pos;
+ git_filter_def *fdef;
+ git_filter_entry *fe;
+
+ assert(fl && filter);
+
+ if (git_vector_search2(
+ &pos, &git__filter_registry->filters,
+ filter_def_filter_key_check, filter) < 0) {
+ giterr_set(GITERR_FILTER, "Cannot use an unregistered filter");
+ return -1;
+ }
+
+ fdef = git_vector_get(&git__filter_registry->filters, pos);
+
+ if (!fdef->initialized && (error = filter_initialize(fdef)) < 0)
+ return error;
+
+ fe = git_array_alloc(fl->filters);
+ GITERR_CHECK_ALLOC(fe);
+ fe->filter = filter;
+ fe->payload = payload;
+
+ return 0;
+}
+
static int filter_list_out_buffer_from_raw(
git_buffer *out, const void *ptr, size_t size)
{