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