1 /*
2  * Copyright (C) the libgit2 contributors. All rights reserved.
3  *
4  * This file is part of libgit2, distributed under the GNU GPL v2 with
5  * a Linking Exception. For full terms see the included COPYING file.
6  */
7 module libgit2_d.sys.filter;
8 
9 
10 private static import libgit2_d.buffer;
11 private static import libgit2_d.filter;
12 private static import libgit2_d.oid;
13 private static import libgit2_d.types;
14 
15 /**
16  * @file git2/sys/filter.h
17  * @brief Git filter backend and plugin routines
18  * @defgroup git_backend Git custom backend APIs
19  * @ingroup Git
20  * @{
21  */
22 extern (C):
23 nothrow @nogc:
24 package(libgit2_d):
25 
26 /**
27  * Look up a filter by name
28  *
29  * Params:
30  *      name = The name of the filter
31  *
32  * Returns: Pointer to the filter object or null if not found
33  */
34 //GIT_EXTERN
35 .git_filter* git_filter_lookup(const (char)* name);
36 
37 enum GIT_FILTER_CRLF = "crlf";
38 enum GIT_FILTER_IDENT = "ident";
39 
40 /**
41  * This is priority that the internal CRLF filter will be registered with
42  */
43 enum GIT_FILTER_CRLF_PRIORITY = 0;
44 
45 /**
46  * This is priority that the internal ident filter will be registered with
47  */
48 enum GIT_FILTER_IDENT_PRIORITY = 100;
49 
50 /**
51  * This is priority to use with a custom filter to imitate a core Git
52  * filter driver, so that it will be run last on checkout and first on
53  * checkin.  You do not have to use this, but it helps compatibility.
54  */
55 enum GIT_FILTER_DRIVER_PRIORITY = 200;
56 
57 /**
58  * Create a new empty filter list
59  *
60  * Normally you won't use this because `git_filter_list_load` will create
61  * the filter list for you, but you can use this in combination with the
62  * `git_filter_lookup` and `git_filter_list_push` functions to assemble
63  * your own chains of filters.
64  */
65 //GIT_EXTERN
66 int git_filter_list_new(libgit2_d.filter.git_filter_list** out_, libgit2_d.types.git_repository* repo, libgit2_d.filter.git_filter_mode_t mode, uint options);
67 
68 /**
69  * Add a filter to a filter list with the given payload.
70  *
71  * Normally you won't have to do this because the filter list is created
72  * by calling the "check" function on registered filters when the filter
73  * attributes are set, but this does allow more direct manipulation of
74  * filter lists when desired.
75  *
76  * Note that normally the "check" function can set up a payload for the
77  * filter.  Using this function, you can either pass in a payload if you
78  * know the expected payload format, or you can pass null.  Some filters
79  * may fail with a null payload.  Good luck!
80  */
81 //GIT_EXTERN
82 int git_filter_list_push(libgit2_d.filter.git_filter_list* fl, .git_filter* filter, void* payload);
83 
84 /**
85  * Look up how many filters are in the list
86  *
87  * We will attempt to apply all of these filters to any data passed in,
88  * but note that the filter apply action still has the option of skipping
89  * data that is passed in (for example, the CRLF filter will skip data
90  * that appears to be binary).
91  *
92  * Params:
93  *      fl = A filter list
94  *
95  * Returns: The number of filters in the list
96  */
97 //GIT_EXTERN
98 size_t git_filter_list_length(const (libgit2_d.filter.git_filter_list)* fl);
99 
100 /**
101  * A filter source represents a file/blob to be processed
102  */
103 struct git_filter_source;
104 
105 /**
106  * Get the repository that the source data is coming from.
107  */
108 //GIT_EXTERN
109 libgit2_d.types.git_repository* git_filter_source_repo(const (.git_filter_source)* src);
110 
111 /**
112  * Get the path that the source data is coming from.
113  */
114 //GIT_EXTERN
115 const (char)* git_filter_source_path(const (.git_filter_source)* src);
116 
117 /**
118  * Get the file mode of the source file
119  * If the mode is unknown, this will return 0
120  */
121 //GIT_EXTERN
122 ushort git_filter_source_filemode(const (.git_filter_source)* src);
123 
124 /**
125  * Get the OID of the source
126  * If the OID is unknown (often the case with git_filter_mode_t.GIT_FILTER_CLEAN) then
127  * this will return null.
128  */
129 //GIT_EXTERN
130 const (libgit2_d.oid.git_oid)* git_filter_source_id(const (.git_filter_source)* src);
131 
132 /**
133  * Get the git_filter_mode_t to be used
134  */
135 //GIT_EXTERN
136 libgit2_d.filter.git_filter_mode_t git_filter_source_mode(const (.git_filter_source)* src);
137 
138 /**
139  * Get the combination git_filter_flag_t options to be applied
140  */
141 //GIT_EXTERN
142 uint git_filter_source_flags(const (.git_filter_source)* src);
143 
144 /**
145  * Initialize callback on filter
146  *
147  * Specified as `filter.initialize`, this is an optional callback invoked
148  * before a filter is first used.  It will be called once at most.
149  *
150  * If non-null, the filter's `initialize` callback will be invoked right
151  * before the first use of the filter, so you can defer expensive
152  * initialization operations (in case libgit2 is being used in a way that
153  * doesn't need the filter).
154  */
155 alias git_filter_init_fn = int function(.git_filter* self);
156 
157 /**
158  * Shutdown callback on filter
159  *
160  * Specified as `filter.shutdown`, this is an optional callback invoked
161  * when the filter is unregistered or when libgit2 is shutting down.  It
162  * will be called once at most and should release resources as needed.
163  * This may be called even if the `initialize` callback was not made.
164  *
165  * Typically this function will free the `git_filter` object itself.
166  */
167 alias git_filter_shutdown_fn = void function(.git_filter* self);
168 
169 /**
170  * Callback to decide if a given source needs this filter
171  *
172  * Specified as `filter.check`, this is an optional callback that checks
173  * if filtering is needed for a given source.
174  *
175  * It should return 0 if the filter should be applied (i.e. success),
176  * git_error_code.GIT_PASSTHROUGH if the filter should not be applied, or an error code
177  * to fail out of the filter processing pipeline and return to the caller.
178  *
179  * The `attr_values` will be set to the values of any attributes given in
180  * the filter definition.  See `git_filter` below for more detail.
181  *
182  * The `payload` will be a pointer to a reference payload for the filter.
183  * This will start as null, but `check` can assign to this pointer for
184  * later use by the `apply` callback.  Note that the value should be heap
185  * allocated (not stack), so that it doesn't go away before the `apply`
186  * callback can use it.  If a filter allocates and assigns a value to the
187  * `payload`, it will need a `cleanup` callback to free the payload.
188  */
189 alias git_filter_check_fn = int function(.git_filter* self, void** payload, /* points to null ptr on entry, may be set */
190     const (.git_filter_source)* src, const (char)** attr_values);
191 
192 /**
193  * Callback to actually perform the data filtering
194  *
195  * Specified as `filter.apply`, this is the callback that actually filters
196  * data.  If it successfully writes the output, it should return 0.  Like
197  * `check`, it can return git_error_code.GIT_PASSTHROUGH to indicate that the filter
198  * doesn't want to run.  Other error codes will stop filter processing and
199  * return to the caller.
200  *
201  * The `payload` value will refer to any payload that was set by the
202  * `check` callback.  It may be read from or written to as needed.
203  */
204 alias git_filter_apply_fn = int function(.git_filter* self, void** payload, /* may be read and/or set */
205                                    libgit2_d.buffer.git_buf* to, const (libgit2_d.buffer.git_buf)* from, const (.git_filter_source)* src);
206 
207 alias git_filter_stream_fn = int function(libgit2_d.types.git_writestream** out_, .git_filter* self, void** payload, const (.git_filter_source)* src, libgit2_d.types.git_writestream* next);
208 
209 /**
210  * Callback to clean up after filtering has been applied
211  *
212  * Specified as `filter.cleanup`, this is an optional callback invoked
213  * after the filter has been applied.  If the `check` or `apply` callbacks
214  * allocated a `payload` to keep per-source filter state, use this
215  * callback to free that payload and release resources as required.
216  */
217 alias git_filter_cleanup_fn = void function(.git_filter* self, void* payload);
218 
219 /**
220  * Filter structure used to register custom filters.
221  *
222  * To associate extra data with a filter, allocate extra data and put the
223  * `git_filter` struct at the start of your data buffer, then cast the
224  * `self` pointer to your larger structure when your callback is invoked.
225  */
226 struct git_filter
227 {
228 	/**
229 	 * The `version` field should be set to `GIT_FILTER_VERSION`.
230 	 */
231 	uint version_;
232 
233 	/**
234 	 * A whitespace-separated list of attribute names to check for this
235 	 * filter (e.g. "eol crlf text").  If the attribute name is bare, it
236 	 * will be simply loaded and passed to the `check` callback.  If it
237 	 * has a value (i.e. "name=value"), the attribute must match that
238 	 * value for the filter to be applied.  The value may be a wildcard
239 	 * (eg, "name=*"), in which case the filter will be invoked for any
240 	 * value for the given attribute name.  See the attribute parameter
241 	 * of the `check` callback for the attribute value that was specified.
242 	 */
243 	const (char)* attributes;
244 
245 	/**
246 	 * Called when the filter is first used for any file.
247 	 */
248 	.git_filter_init_fn initialize;
249 
250 	/**
251 	 * Called when the filter is removed or unregistered from the system.
252 	 */
253 	.git_filter_shutdown_fn shutdown;
254 
255 	/**
256 	 * Called to determine whether the filter should be invoked for a
257 	 * given file.  If this function returns `git_error_code.GIT_PASSTHROUGH` then the
258 	 * `apply` function will not be invoked and the contents will be passed
259 	 * through unmodified.
260 	 */
261 	.git_filter_check_fn check;
262 
263 	/**
264 	 * Called to actually apply the filter to file contents.  If this
265 	 * function returns `git_error_code.GIT_PASSTHROUGH` then the contents will be passed
266 	 * through unmodified.
267 	 */
268 	.git_filter_apply_fn apply;
269 
270 	/**
271 	 * Called to apply the filter in a streaming manner.  If this is not
272 	 * specified then the system will call `apply` with the whole buffer.
273 	 */
274 	.git_filter_stream_fn stream;
275 
276 	/**
277 	 * Called when the system is done filtering for a file.
278 	 */
279 	.git_filter_cleanup_fn cleanup;
280 }
281 
282 enum GIT_FILTER_VERSION = 1;
283 
284 pragma(inline, true)
285 pure nothrow @safe @nogc
286 .git_filter GIT_FILTER_INIT()
287 
288 	do
289 	{
290 		.git_filter OUTPUT =
291 		{
292 			version_: .GIT_FILTER_VERSION,
293 		};
294 
295 		return OUTPUT;
296 	}
297 
298 /**
299  * Initializes a `git_filter` with default values. Equivalent to
300  * creating an instance with GIT_FILTER_INIT.
301  *
302  * Params:
303  *      filter = the `git_filter` struct to initialize.
304  *      version = Version the struct; pass `GIT_FILTER_VERSION`
305  *
306  * Returns: Zero on success; -1 on failure.
307  */
308 //GIT_EXTERN
309 int git_filter_init(.git_filter* filter, uint version_);
310 
311 /**
312  * Register a filter under a given name with a given priority.
313  *
314  * As mentioned elsewhere, the initialize callback will not be invoked
315  * immediately.  It is deferred until the filter is used in some way.
316  *
317  * A filter's attribute checks and `check` and `apply` callbacks will be
318  * issued in order of `priority` on smudge (to workdir), and in reverse
319  * order of `priority` on clean (to odb).
320  *
321  * Two filters are preregistered with libgit2:
322  * - GIT_FILTER_CRLF with priority 0
323  * - GIT_FILTER_IDENT with priority 100
324  *
325  * Currently the filter registry is not thread safe, so any registering or
326  * deregistering of filters must be done outside of any possible usage of
327  * the filters (i.e. during application setup or shutdown).
328  *
329  * Params:
330  *      name = A name by which the filter can be referenced.  Attempting to register with an in-use name will return git_error_code.GIT_EEXISTS.
331  *      filter = The filter definition.  This pointer will be stored as is by libgit2 so it must be a durable allocation (either static or on the heap).
332  *      priority = The priority for filter application
333  *
334  * Returns: 0 on successful registry, error code <0 on failure
335  */
336 //GIT_EXTERN
337 int git_filter_register(const (char)* name, .git_filter* filter, int priority);
338 
339 /**
340  * Remove the filter with the given name
341  *
342  * Attempting to remove the builtin libgit2 filters is not permitted and
343  * will return an error.
344  *
345  * Currently the filter registry is not thread safe, so any registering or
346  * deregistering of filters must be done outside of any possible usage of
347  * the filters (i.e. during application setup or shutdown).
348  *
349  * Params:
350  *      name = The name under which the filter was registered
351  *
352  * Returns: 0 on success, error code <0 on failure
353  */
354 //GIT_EXTERN
355 int git_filter_unregister(const (char)* name);
356 
357 /** @} */