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 /* @} */