]>
Commit | Line | Data |
---|---|---|
114f5a6c RB |
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 | */ | |
eae0bfdc PP |
7 | |
8 | #include "diff_driver.h" | |
114f5a6c RB |
9 | |
10 | #include "git2/attr.h" | |
11 | ||
0c9c969a | 12 | #include "common.h" |
114f5a6c | 13 | #include "diff.h" |
114f5a6c | 14 | #include "strmap.h" |
114f5a6c RB |
15 | #include "map.h" |
16 | #include "buf_text.h" | |
9f77b3f6 | 17 | #include "config.h" |
0c9c969a | 18 | #include "regexp.h" |
5dc98298 | 19 | #include "repository.h" |
114f5a6c RB |
20 | |
21 | typedef enum { | |
22 | DIFF_DRIVER_AUTO = 0, | |
5dc98298 RB |
23 | DIFF_DRIVER_BINARY = 1, |
24 | DIFF_DRIVER_TEXT = 2, | |
25 | DIFF_DRIVER_PATTERNLIST = 3, | |
114f5a6c RB |
26 | } git_diff_driver_t; |
27 | ||
a5a38643 | 28 | typedef struct { |
0c9c969a | 29 | git_regexp re; |
a5a38643 RB |
30 | int flags; |
31 | } git_diff_driver_pattern; | |
32 | ||
114f5a6c | 33 | enum { |
a5a38643 | 34 | REG_NEGATE = (1 << 15) /* get out of the way of existing flags */ |
114f5a6c RB |
35 | }; |
36 | ||
37 | /* data for finding function context for a given file type */ | |
38 | struct git_diff_driver { | |
39 | git_diff_driver_t type; | |
5dc98298 RB |
40 | uint32_t binary_flags; |
41 | uint32_t other_flags; | |
a5a38643 | 42 | git_array_t(git_diff_driver_pattern) fn_patterns; |
0c9c969a | 43 | git_regexp word_pattern; |
42e6cf78 | 44 | char name[GIT_FLEX_ARRAY]; |
114f5a6c RB |
45 | }; |
46 | ||
c7c260a5 | 47 | #include "userdiff.h" |
2c65602e | 48 | |
114f5a6c RB |
49 | struct git_diff_driver_registry { |
50 | git_strmap *drivers; | |
114f5a6c RB |
51 | }; |
52 | ||
5dc98298 RB |
53 | #define FORCE_DIFFABLE (GIT_DIFF_FORCE_TEXT | GIT_DIFF_FORCE_BINARY) |
54 | ||
114f5a6c | 55 | static git_diff_driver global_drivers[3] = { |
5dc98298 RB |
56 | { DIFF_DRIVER_AUTO, 0, 0, }, |
57 | { DIFF_DRIVER_BINARY, GIT_DIFF_FORCE_BINARY, 0 }, | |
58 | { DIFF_DRIVER_TEXT, GIT_DIFF_FORCE_TEXT, 0 }, | |
114f5a6c RB |
59 | }; |
60 | ||
8fd74c08 | 61 | git_diff_driver_registry *git_diff_driver_registry_new(void) |
114f5a6c | 62 | { |
3eadfecd RB |
63 | git_diff_driver_registry *reg = |
64 | git__calloc(1, sizeof(git_diff_driver_registry)); | |
65 | if (!reg) | |
66 | return NULL; | |
67 | ||
0c9c969a | 68 | if (git_strmap_new(®->drivers) < 0) { |
3eadfecd RB |
69 | git_diff_driver_registry_free(reg); |
70 | return NULL; | |
71 | } | |
72 | ||
73 | return reg; | |
114f5a6c RB |
74 | } |
75 | ||
76 | void git_diff_driver_registry_free(git_diff_driver_registry *reg) | |
77 | { | |
5dc98298 RB |
78 | git_diff_driver *drv; |
79 | ||
3eadfecd RB |
80 | if (!reg) |
81 | return; | |
82 | ||
5dc98298 | 83 | git_strmap_foreach_value(reg->drivers, drv, git_diff_driver_free(drv)); |
3eadfecd | 84 | git_strmap_free(reg->drivers); |
114f5a6c RB |
85 | git__free(reg); |
86 | } | |
87 | ||
a5a38643 RB |
88 | static int diff_driver_add_patterns( |
89 | git_diff_driver *drv, const char *regex_str, int regex_flags) | |
5dc98298 | 90 | { |
a5a38643 RB |
91 | int error = 0; |
92 | const char *scan, *end; | |
93 | git_diff_driver_pattern *pat = NULL; | |
94 | git_buf buf = GIT_BUF_INIT; | |
95 | ||
96 | for (scan = regex_str; scan; scan = end) { | |
97 | /* get pattern to fill in */ | |
98 | if ((pat = git_array_alloc(drv->fn_patterns)) == NULL) { | |
e451cd5c | 99 | return -1; |
a5a38643 | 100 | } |
5dc98298 | 101 | |
a5a38643 RB |
102 | pat->flags = regex_flags; |
103 | if (*scan == '!') { | |
104 | pat->flags |= REG_NEGATE; | |
105 | ++scan; | |
106 | } | |
107 | ||
108 | if ((end = strchr(scan, '\n')) != NULL) { | |
109 | error = git_buf_set(&buf, scan, end - scan); | |
110 | end++; | |
111 | } else { | |
112 | error = git_buf_sets(&buf, scan); | |
113 | } | |
114 | if (error < 0) | |
115 | break; | |
116 | ||
0c9c969a | 117 | if ((error = git_regexp_compile(&pat->re, buf.ptr, regex_flags)) != 0) { |
e451cd5c CMN |
118 | /* |
119 | * TODO: issue a warning | |
120 | */ | |
a5a38643 | 121 | } |
5dc98298 RB |
122 | } |
123 | ||
a5a38643 RB |
124 | if (error && pat != NULL) |
125 | (void)git_array_pop(drv->fn_patterns); /* release last item */ | |
ac3d33df | 126 | git_buf_dispose(&buf); |
5dc98298 | 127 | |
e451cd5c CMN |
128 | /* We want to ignore bad patterns, so return success regardless */ |
129 | return 0; | |
5dc98298 RB |
130 | } |
131 | ||
132 | static int diff_driver_xfuncname(const git_config_entry *entry, void *payload) | |
133 | { | |
0c9c969a | 134 | return diff_driver_add_patterns(payload, entry->value, 0); |
5dc98298 RB |
135 | } |
136 | ||
137 | static int diff_driver_funcname(const git_config_entry *entry, void *payload) | |
138 | { | |
a5a38643 | 139 | return diff_driver_add_patterns(payload, entry->value, 0); |
5dc98298 RB |
140 | } |
141 | ||
142 | static git_diff_driver_registry *git_repository_driver_registry( | |
143 | git_repository *repo) | |
144 | { | |
145 | if (!repo->diff_drivers) { | |
146 | git_diff_driver_registry *reg = git_diff_driver_registry_new(); | |
147 | reg = git__compare_and_swap(&repo->diff_drivers, NULL, reg); | |
148 | ||
149 | if (reg != NULL) /* if we race, free losing allocation */ | |
150 | git_diff_driver_registry_free(reg); | |
151 | } | |
152 | ||
153 | if (!repo->diff_drivers) | |
ac3d33df | 154 | git_error_set(GIT_ERROR_REPOSITORY, "unable to create diff driver registry"); |
5dc98298 RB |
155 | |
156 | return repo->diff_drivers; | |
157 | } | |
158 | ||
392702ee ET |
159 | static int diff_driver_alloc( |
160 | git_diff_driver **out, size_t *namelen_out, const char *name) | |
161 | { | |
162 | git_diff_driver *driver; | |
163 | size_t driverlen = sizeof(git_diff_driver), | |
f1453c59 ET |
164 | namelen = strlen(name), |
165 | alloclen; | |
392702ee | 166 | |
ac3d33df JK |
167 | GIT_ERROR_CHECK_ALLOC_ADD(&alloclen, driverlen, namelen); |
168 | GIT_ERROR_CHECK_ALLOC_ADD(&alloclen, alloclen, 1); | |
392702ee | 169 | |
f1453c59 | 170 | driver = git__calloc(1, alloclen); |
ac3d33df | 171 | GIT_ERROR_CHECK_ALLOC(driver); |
392702ee ET |
172 | |
173 | memcpy(driver->name, name, namelen); | |
174 | ||
175 | *out = driver; | |
176 | ||
177 | if (namelen_out) | |
178 | *namelen_out = namelen; | |
179 | ||
180 | return 0; | |
181 | } | |
182 | ||
a5a38643 RB |
183 | static int git_diff_driver_builtin( |
184 | git_diff_driver **out, | |
185 | git_diff_driver_registry *reg, | |
186 | const char *driver_name) | |
187 | { | |
a5a38643 RB |
188 | git_diff_driver_definition *ddef = NULL; |
189 | git_diff_driver *drv = NULL; | |
0c9c969a | 190 | int error = 0; |
392702ee | 191 | size_t idx; |
a5a38643 RB |
192 | |
193 | for (idx = 0; idx < ARRAY_SIZE(builtin_defs); ++idx) { | |
194 | if (!strcasecmp(driver_name, builtin_defs[idx].name)) { | |
195 | ddef = &builtin_defs[idx]; | |
196 | break; | |
197 | } | |
198 | } | |
199 | if (!ddef) | |
200 | goto done; | |
201 | ||
392702ee ET |
202 | if ((error = diff_driver_alloc(&drv, NULL, ddef->name)) < 0) |
203 | goto done; | |
a5a38643 RB |
204 | |
205 | drv->type = DIFF_DRIVER_PATTERNLIST; | |
a5a38643 RB |
206 | |
207 | if (ddef->fns && | |
208 | (error = diff_driver_add_patterns( | |
0c9c969a | 209 | drv, ddef->fns, ddef->flags)) < 0) |
a5a38643 RB |
210 | goto done; |
211 | ||
212 | if (ddef->words && | |
0c9c969a | 213 | (error = git_regexp_compile(&drv->word_pattern, ddef->words, ddef->flags)) < 0) |
a5a38643 | 214 | goto done; |
a5a38643 | 215 | |
0c9c969a UG |
216 | if ((error = git_strmap_set(reg->drivers, drv->name, drv)) < 0) |
217 | goto done; | |
a5a38643 RB |
218 | |
219 | done: | |
2c65602e | 220 | if (error && drv) |
a5a38643 | 221 | git_diff_driver_free(drv); |
2c65602e | 222 | else |
a5a38643 | 223 | *out = drv; |
a5a38643 RB |
224 | |
225 | return error; | |
226 | } | |
227 | ||
3eadfecd | 228 | static int git_diff_driver_load( |
5dc98298 | 229 | git_diff_driver **out, git_repository *repo, const char *driver_name) |
3eadfecd | 230 | { |
9f77b3f6 | 231 | int error = 0; |
5dc98298 | 232 | git_diff_driver_registry *reg; |
0c9c969a UG |
233 | git_diff_driver *drv; |
234 | size_t namelen; | |
392702ee | 235 | git_config *cfg = NULL; |
5dc98298 | 236 | git_buf name = GIT_BUF_INIT; |
9a97f49e | 237 | git_config_entry *ce = NULL; |
42e6cf78 | 238 | bool found_driver = false; |
5dc98298 | 239 | |
a5a38643 | 240 | if ((reg = git_repository_driver_registry(repo)) == NULL) |
5dc98298 | 241 | return -1; |
a5a38643 | 242 | |
0c9c969a UG |
243 | if ((drv = git_strmap_get(reg->drivers, driver_name)) != NULL) { |
244 | *out = drv; | |
a5a38643 | 245 | return 0; |
5dc98298 RB |
246 | } |
247 | ||
392702ee ET |
248 | if ((error = diff_driver_alloc(&drv, &namelen, driver_name)) < 0) |
249 | goto done; | |
250 | ||
a37aa82e | 251 | drv->type = DIFF_DRIVER_AUTO; |
a37aa82e | 252 | |
5dc98298 | 253 | /* if you can't read config for repo, just use default driver */ |
ac99d86b | 254 | if (git_repository_config_snapshot(&cfg, repo) < 0) { |
ac3d33df | 255 | git_error_clear(); |
a5a38643 | 256 | goto done; |
5dc98298 RB |
257 | } |
258 | ||
5dc98298 | 259 | if ((error = git_buf_printf(&name, "diff.%s.binary", driver_name)) < 0) |
54faddd2 | 260 | goto done; |
9f77b3f6 RB |
261 | |
262 | switch (git_config__get_bool_force(cfg, name.ptr, -1)) { | |
263 | case true: | |
5dc98298 | 264 | /* if diff.<driver>.binary is true, just return the binary driver */ |
5dc98298 | 265 | *out = &global_drivers[DIFF_DRIVER_BINARY]; |
54faddd2 | 266 | goto done; |
9f77b3f6 | 267 | case false: |
5dc98298 RB |
268 | /* if diff.<driver>.binary is false, force binary checks off */ |
269 | /* but still may have custom function context patterns, etc. */ | |
270 | drv->binary_flags = GIT_DIFF_FORCE_TEXT; | |
42e6cf78 | 271 | found_driver = true; |
9f77b3f6 RB |
272 | break; |
273 | default: | |
a5a38643 | 274 | /* diff.<driver>.binary unspecified or "auto", so just continue */ |
9f77b3f6 | 275 | break; |
5dc98298 RB |
276 | } |
277 | ||
278 | /* TODO: warn if diff.<name>.command or diff.<name>.textconv are set */ | |
279 | ||
42e6cf78 | 280 | git_buf_truncate(&name, namelen + strlen("diff..")); |
0c9c969a UG |
281 | if ((error = git_buf_PUTS(&name, "xfuncname")) < 0) |
282 | goto done; | |
283 | ||
4efa3290 | 284 | if ((error = git_config_get_multivar_foreach( |
5dc98298 RB |
285 | cfg, name.ptr, NULL, diff_driver_xfuncname, drv)) < 0) { |
286 | if (error != GIT_ENOTFOUND) | |
54faddd2 | 287 | goto done; |
ac3d33df | 288 | git_error_clear(); /* no diff.<driver>.xfuncname, so just continue */ |
5dc98298 | 289 | } |
3eadfecd | 290 | |
42e6cf78 | 291 | git_buf_truncate(&name, namelen + strlen("diff..")); |
0c9c969a UG |
292 | if ((error = git_buf_PUTS(&name, "funcname")) < 0) |
293 | goto done; | |
294 | ||
4efa3290 | 295 | if ((error = git_config_get_multivar_foreach( |
5dc98298 RB |
296 | cfg, name.ptr, NULL, diff_driver_funcname, drv)) < 0) { |
297 | if (error != GIT_ENOTFOUND) | |
54faddd2 | 298 | goto done; |
ac3d33df | 299 | git_error_clear(); /* no diff.<driver>.funcname, so just continue */ |
5dc98298 RB |
300 | } |
301 | ||
302 | /* if we found any patterns, set driver type to use correct callback */ | |
42e6cf78 | 303 | if (git_array_size(drv->fn_patterns) > 0) { |
5dc98298 | 304 | drv->type = DIFF_DRIVER_PATTERNLIST; |
42e6cf78 RB |
305 | found_driver = true; |
306 | } | |
5dc98298 | 307 | |
42e6cf78 | 308 | git_buf_truncate(&name, namelen + strlen("diff..")); |
0c9c969a UG |
309 | if ((error = git_buf_PUTS(&name, "wordregex")) < 0) |
310 | goto done; | |
311 | ||
9f77b3f6 | 312 | if ((error = git_config__lookup_entry(&ce, cfg, name.ptr, false)) < 0) |
54faddd2 | 313 | goto done; |
9f77b3f6 RB |
314 | if (!ce || !ce->value) |
315 | /* no diff.<driver>.wordregex, so just continue */; | |
0c9c969a | 316 | else if (!(error = git_regexp_compile(&drv->word_pattern, ce->value, 0))) |
42e6cf78 | 317 | found_driver = true; |
9f77b3f6 RB |
318 | else { |
319 | /* TODO: warn about bad regex instead of failure */ | |
9f77b3f6 | 320 | goto done; |
5dc98298 RB |
321 | } |
322 | ||
323 | /* TODO: look up diff.<driver>.algorithm to turn on minimal / patience | |
324 | * diff in drv->other_flags | |
325 | */ | |
326 | ||
54faddd2 | 327 | /* if no driver config found at all, fall back on AUTO driver */ |
42e6cf78 | 328 | if (!found_driver) |
54faddd2 | 329 | goto done; |
42e6cf78 RB |
330 | |
331 | /* store driver in registry */ | |
0c9c969a | 332 | if ((error = git_strmap_set(reg->drivers, drv->name, drv)) < 0) |
54faddd2 | 333 | goto done; |
42e6cf78 | 334 | |
5dc98298 | 335 | *out = drv; |
5dc98298 | 336 | |
54faddd2 | 337 | done: |
9a97f49e | 338 | git_config_entry_free(ce); |
ac3d33df | 339 | git_buf_dispose(&name); |
29c4cb09 | 340 | git_config_free(cfg); |
54faddd2 | 341 | |
a5a38643 RB |
342 | if (!*out) { |
343 | int error2 = git_diff_driver_builtin(out, reg, driver_name); | |
344 | if (!error) | |
345 | error = error2; | |
346 | } | |
54faddd2 RB |
347 | |
348 | if (drv && drv != *out) | |
349 | git_diff_driver_free(drv); | |
350 | ||
5dc98298 | 351 | return error; |
3eadfecd RB |
352 | } |
353 | ||
114f5a6c | 354 | int git_diff_driver_lookup( |
eae0bfdc PP |
355 | git_diff_driver **out, git_repository *repo, |
356 | git_attr_session *attrsession, const char *path) | |
114f5a6c | 357 | { |
3eadfecd | 358 | int error = 0; |
eae0bfdc | 359 | const char *values[1], *attrs[] = { "diff" }; |
114f5a6c RB |
360 | |
361 | assert(out); | |
2c65602e | 362 | *out = NULL; |
114f5a6c RB |
363 | |
364 | if (!repo || !path || !strlen(path)) | |
2c65602e | 365 | /* just use the auto value */; |
eae0bfdc PP |
366 | else if ((error = git_attr_get_many_with_session(values, repo, |
367 | attrsession, 0, path, 1, attrs)) < 0) | |
2c65602e | 368 | /* return error below */; |
eae0bfdc | 369 | |
0c9c969a | 370 | else if (GIT_ATTR_IS_UNSPECIFIED(values[0])) |
42e6cf78 | 371 | /* just use the auto value */; |
0c9c969a | 372 | else if (GIT_ATTR_IS_FALSE(values[0])) |
5dc98298 | 373 | *out = &global_drivers[DIFF_DRIVER_BINARY]; |
0c9c969a | 374 | else if (GIT_ATTR_IS_TRUE(values[0])) |
5dc98298 | 375 | *out = &global_drivers[DIFF_DRIVER_TEXT]; |
114f5a6c RB |
376 | |
377 | /* otherwise look for driver information in config and build driver */ | |
eae0bfdc | 378 | else if ((error = git_diff_driver_load(out, repo, values[0])) < 0) { |
2c65602e RB |
379 | if (error == GIT_ENOTFOUND) { |
380 | error = 0; | |
ac3d33df | 381 | git_error_clear(); |
2c65602e | 382 | } |
3eadfecd | 383 | } |
114f5a6c | 384 | |
42e6cf78 RB |
385 | if (!*out) |
386 | *out = &global_drivers[DIFF_DRIVER_AUTO]; | |
387 | ||
2c65602e | 388 | return error; |
114f5a6c RB |
389 | } |
390 | ||
391 | void git_diff_driver_free(git_diff_driver *driver) | |
392 | { | |
5dc98298 RB |
393 | size_t i; |
394 | ||
395 | if (!driver) | |
396 | return; | |
397 | ||
54faddd2 | 398 | for (i = 0; i < git_array_size(driver->fn_patterns); ++i) |
0c9c969a | 399 | git_regexp_dispose(& git_array_get(driver->fn_patterns, i)->re); |
5dc98298 RB |
400 | git_array_clear(driver->fn_patterns); |
401 | ||
0c9c969a | 402 | git_regexp_dispose(&driver->word_pattern); |
5dc98298 RB |
403 | |
404 | git__free(driver); | |
114f5a6c RB |
405 | } |
406 | ||
5dc98298 RB |
407 | void git_diff_driver_update_options( |
408 | uint32_t *option_flags, git_diff_driver *driver) | |
114f5a6c | 409 | { |
5dc98298 RB |
410 | if ((*option_flags & FORCE_DIFFABLE) == 0) |
411 | *option_flags |= driver->binary_flags; | |
412 | ||
413 | *option_flags |= driver->other_flags; | |
114f5a6c RB |
414 | } |
415 | ||
416 | int git_diff_driver_content_is_binary( | |
417 | git_diff_driver *driver, const char *content, size_t content_len) | |
418 | { | |
d4cf1675 | 419 | git_buf search = GIT_BUF_INIT; |
114f5a6c RB |
420 | |
421 | GIT_UNUSED(driver); | |
422 | ||
d4cf1675 ET |
423 | git_buf_attach_notowned(&search, content, |
424 | min(content_len, GIT_FILTER_BYTES_TO_CHECK_NUL)); | |
425 | ||
114f5a6c RB |
426 | /* TODO: provide encoding / binary detection callbacks that can |
427 | * be UTF-8 aware, etc. For now, instead of trying to be smart, | |
428 | * let's just use the simple NUL-byte detection that core git uses. | |
429 | */ | |
430 | ||
431 | /* previously was: if (git_buf_text_is_binary(&search)) */ | |
432 | if (git_buf_text_contains_nul(&search)) | |
433 | return 1; | |
434 | ||
435 | return 0; | |
436 | } | |
437 | ||
5dc98298 | 438 | static int diff_context_line__simple( |
a5a38643 | 439 | git_diff_driver *driver, git_buf *line) |
5dc98298 | 440 | { |
a5a38643 | 441 | char firstch = line->ptr[0]; |
5dc98298 | 442 | GIT_UNUSED(driver); |
a5a38643 | 443 | return (git__isalpha(firstch) || firstch == '_' || firstch == '$'); |
5dc98298 RB |
444 | } |
445 | ||
446 | static int diff_context_line__pattern_match( | |
a5a38643 | 447 | git_diff_driver *driver, git_buf *line) |
5dc98298 | 448 | { |
b8e86c62 | 449 | size_t i, maxi = git_array_size(driver->fn_patterns); |
0c9c969a | 450 | git_regmatch pmatch[2]; |
5dc98298 | 451 | |
b8e86c62 | 452 | for (i = 0; i < maxi; ++i) { |
a5a38643 RB |
453 | git_diff_driver_pattern *pat = git_array_get(driver->fn_patterns, i); |
454 | ||
0c9c969a | 455 | if (!git_regexp_search(&pat->re, line->ptr, 2, pmatch)) { |
a5a38643 RB |
456 | if (pat->flags & REG_NEGATE) |
457 | return false; | |
b8e86c62 RB |
458 | |
459 | /* use pmatch data to trim line data */ | |
0c9c969a UG |
460 | i = (pmatch[1].start >= 0) ? 1 : 0; |
461 | git_buf_consume(line, git_buf_cstr(line) + pmatch[i].start); | |
462 | git_buf_truncate(line, pmatch[i].end - pmatch[i].start); | |
082e82db | 463 | git_buf_rtrim(line); |
b8e86c62 | 464 | |
5dc98298 | 465 | return true; |
a5a38643 | 466 | } |
5dc98298 RB |
467 | } |
468 | ||
469 | return false; | |
470 | } | |
471 | ||
114f5a6c RB |
472 | static long diff_context_find( |
473 | const char *line, | |
474 | long line_len, | |
475 | char *out, | |
476 | long out_size, | |
477 | void *payload) | |
478 | { | |
5dc98298 | 479 | git_diff_find_context_payload *ctxt = payload; |
114f5a6c | 480 | |
5dc98298 | 481 | if (git_buf_set(&ctxt->line, line, (size_t)line_len) < 0) |
114f5a6c | 482 | return -1; |
5dc98298 | 483 | git_buf_rtrim(&ctxt->line); |
114f5a6c | 484 | |
5dc98298 | 485 | if (!ctxt->line.size) |
114f5a6c RB |
486 | return -1; |
487 | ||
a5a38643 | 488 | if (!ctxt->match_line || !ctxt->match_line(ctxt->driver, &ctxt->line)) |
5dc98298 | 489 | return -1; |
114f5a6c | 490 | |
a5f9b5f8 | 491 | if (out_size > (long)ctxt->line.size) |
584f2d30 | 492 | out_size = (long)ctxt->line.size; |
a5f9b5f8 | 493 | memcpy(out, ctxt->line.ptr, (size_t)out_size); |
114f5a6c | 494 | |
a5f9b5f8 | 495 | return out_size; |
5dc98298 | 496 | } |
114f5a6c | 497 | |
5dc98298 RB |
498 | void git_diff_find_context_init( |
499 | git_diff_find_context_fn *findfn_out, | |
500 | git_diff_find_context_payload *payload_out, | |
501 | git_diff_driver *driver) | |
502 | { | |
503 | *findfn_out = driver ? diff_context_find : NULL; | |
504 | ||
505 | memset(payload_out, 0, sizeof(*payload_out)); | |
506 | if (driver) { | |
507 | payload_out->driver = driver; | |
508 | payload_out->match_line = (driver->type == DIFF_DRIVER_PATTERNLIST) ? | |
509 | diff_context_line__pattern_match : diff_context_line__simple; | |
510 | git_buf_init(&payload_out->line, 0); | |
511 | } | |
114f5a6c RB |
512 | } |
513 | ||
5dc98298 | 514 | void git_diff_find_context_clear(git_diff_find_context_payload *payload) |
114f5a6c | 515 | { |
5dc98298 | 516 | if (payload) { |
ac3d33df | 517 | git_buf_dispose(&payload->line); |
5dc98298 RB |
518 | payload->driver = NULL; |
519 | } | |
114f5a6c | 520 | } |