summaryrefslogtreecommitdiff
path: root/include/git2/sys
diff options
context:
space:
mode:
authorRussell Belfer <rb@github.com>2013-09-09 16:57:34 -0700
committerRussell Belfer <rb@github.com>2013-09-17 09:31:44 -0700
commit974774c7b00c08585b05ff87174872be005a1f29 (patch)
treecea2a1d9b29a4601b90fe23a47775eb39773dcb5 /include/git2/sys
parent570ba25cb0f757f993e06df629faced32fdf2f8f (diff)
downloadlibgit2-974774c7b00c08585b05ff87174872be005a1f29.tar.gz
Add attributes to filters and fix registry
The filter registry as implemented was too primitive to actually work once multiple filters were coming into play. This expands the implementation of the registry to handle multiple prioritized filters correctly. Additionally, this adds an "attributes" field to a filter that makes it really really easy to implement filters that are based on one or more attribute values. The lookup and even simple value checking can all happen automatically without custom filter code. Lastly, with the registry improvements, this fills out the filter lifecycle callbacks, with initialize and shutdown callbacks that will be called before the filter is first used and after it is last invoked. This allows for system-wide initialization and cleanup by the filter.
Diffstat (limited to 'include/git2/sys')
-rw-r--r--include/git2/sys/filter.h101
1 files changed, 83 insertions, 18 deletions
diff --git a/include/git2/sys/filter.h b/include/git2/sys/filter.h
index b1193a538..b0a753019 100644
--- a/include/git2/sys/filter.h
+++ b/include/git2/sys/filter.h
@@ -46,16 +46,26 @@ GIT_EXTERN(uint16_t) git_filter_source_filemode(const git_filter_source *src);
*/
GIT_EXTERN(const git_oid *) git_filter_source_id(const git_filter_source *src);
+/*
+ * struct git_filter
+ *
+ * The filter lifecycle:
+ * - initialize - first use of filter
+ * - shutdown - filter removed/unregistered from system
+ * - check - considering for file
+ * - apply - applied to file
+ * - cleanup - done with file
+ */
+
/**
- * Callback to actually perform the data filtering
+ * Initialize callback on filter
*/
-typedef int (*git_filter_apply_fn)(
- git_filter *self,
- void **payload, /* may be read and/or set */
- git_filter_mode_t mode,
- git_buffer *to,
- const git_buffer *from,
- const git_filter_source *src);
+typedef int (*git_filter_init_fn)(git_filter *self);
+
+/**
+ * Shutdown callback on filter
+ */
+typedef void (*git_filter_shutdown_fn)(git_filter *self);
/**
* Callback to decide if a given source needs this filter
@@ -64,6 +74,18 @@ typedef int (*git_filter_check_fn)(
git_filter *self,
void **payload, /* points to NULL ptr on entry, may be set */
git_filter_mode_t mode,
+ const git_filter_source *src,
+ const char **attr_values);
+
+/**
+ * Callback to actually perform the data filtering
+ */
+typedef int (*git_filter_apply_fn)(
+ git_filter *self,
+ void **payload, /* may be read and/or set */
+ git_filter_mode_t mode,
+ git_buffer *to,
+ const git_buffer *from,
const git_filter_source *src);
/**
@@ -83,10 +105,32 @@ typedef void (*git_filter_cleanup_fn)(
*
* `version` should be set to GIT_FILTER_VERSION
*
- * `apply` is the callback that actually filters data.
+ * `attributes` is a list of attributes to check on a file to see if the
+ * filter applies. The format is a whitespace-delimited list of names
+ * (like "eol crlf text"). Each name may have an optional value that will
+ * be tested even without a `check` callback. If the value does not
+ * match, the filter will be skipped. The values are specified as in a
+ * .gitattributes file (e.g. "myattr=foobar" or "myattr" or "-myattr").
+ * If a check function is supplied, then the values of the attributes will
+ * be passed to that function.
+ *
+ * `initialize` is an optional callback invoked before a filter is first
+ * used. It will be called once at most.
+ *
+ * `shutdown` is an optional callback invoked when the filter is
+ * unregistered or when libgit2 is shutting down. It will be called once
+ * at most and should free any memory as needed.
*
* `check` is an optional callback that checks if filtering is needed for
- * a given source.
+ * a given source. It should return 0 if the filter should be applied
+ * (i.e. success), GIT_ENOTFOUND if the filter should not be applied, or
+ * an other error code to fail out of the filter processing pipeline and
+ * return to the caller.
+ *
+ * `apply` is the callback that actually filters data. If it successfully
+ * writes the output, it should return 0. Like `check`, it can return
+ * GIT_ENOTFOUND to indicate that the filter doesn't actually want to run.
+ * Other error codes will stop filter processing and return to the caller.
*
* `cleanup` is an optional callback that is made after the filter has
* been applied. Both the `check` and `apply` callbacks are able to
@@ -94,25 +138,46 @@ typedef void (*git_filter_cleanup_fn)(
* is given that value and can clean up as needed.
*/
struct git_filter {
- unsigned int version;
- git_filter_apply_fn apply;
- git_filter_check_fn check;
- git_filter_cleanup_fn cleanup;
+ unsigned int version;
+ const char *attributes;
+ git_filter_init_fn initialize;
+ git_filter_shutdown_fn shutdown;
+ git_filter_check_fn check;
+ git_filter_apply_fn apply;
+ git_filter_cleanup_fn cleanup;
};
#define GIT_FILTER_VERSION 1
/**
- * Register a filter under a given name
+ * Register a filter under a given name with a given priority.
+ *
+ * If non-NULL, the filter's initialize callback will be invoked before
+ * the first use of the filter, so you can defer expensive operations (in
+ * case libgit2 is being used in a way that doesn't need the filter).
*
- * Two filters will be preregistered with libgit2: GIT_FILTER_CRLF and
- * GIT_FILTER_IDENT.
+ * A filter's attribute checks and `check` and `apply` callbacks will be
+ * issued in order of `priority` on smudge (to workdir), and in reverse
+ * order of `priority` on clean (to odb).
+ *
+ * One filter will be preregistered with libgit2:
+ * - GIT_FILTER_CRLF with priority of 0.
+ *
+ * Currently the filter registry is not thread safe, so any registering or
+ * deregistering of filters must be done outside of any possible usage of
+ * the filters (i.e. during application setup or shutdown).
*/
GIT_EXTERN(int) git_filter_register(
- const char *name, const git_filter *filter);
+ const char *name, git_filter *filter, int priority);
/**
* Remove the filter with the given name
+ *
+ * It is not allowed to remove the builtin libgit2 filters.
+ *
+ * Currently the filter registry is not thread safe, so any registering or
+ * deregistering of filters must be done outside of any possible usage of
+ * the filters (i.e. during application setup or shutdown).
*/
GIT_EXTERN(int) git_filter_unregister(const char *name);