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