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 "attr_file.h"
9 -
10 - #include "repository.h"
11 - #include "filebuf.h"
12 - #include "attrcache.h"
13 - #include "buf_text.h"
14 - #include "git2/blob.h"
15 - #include "git2/tree.h"
16 - #include "blob.h"
17 - #include "index.h"
18 - #include "wildmatch.h"
19 - #include <ctype.h>
20 -
21 175563 2 static void attr_file_free(git_attr_file *file)
22 - {
23 175563 2 bool unlock = !git_mutex_lock(&file->lock);
24 175685 3 git_attr_file__clear_rules(file, false);
25 175260 4 git_pool_clear(&file->pool);
26 175202 5 if (unlock)
27 175198 6 git_mutex_unlock(&file->lock);
28 175624 7 git_mutex_free(&file->lock);
29 -
30 175686 8 git__memzero(file, sizeof(*file));
31 175581 9 git__free(file);
32 175704 10 }
33 -
34 175543 2 int git_attr_file__new(
35 - git_attr_file **out,
36 - git_attr_file_entry *entry,
37 - git_attr_file_source source)
38 - {
39 175543 2 git_attr_file *attrs = git__calloc(1, sizeof(git_attr_file));
40 175607 3,4 GIT_ERROR_CHECK_ALLOC(attrs);
41 -
42 175622 5,6 if (git_mutex_init(&attrs->lock) < 0) {
43 ##### 7 git_error_set(GIT_ERROR_OS, "failed to initialize lock");
44 ##### 13 goto on_error;
45 - }
46 -
47 175622 8,9 if (git_pool_init(&attrs->pool, 1) < 0)
48 ##### 10 goto on_error;
49 -
50 175416 11 GIT_REFCOUNT_INC(attrs);
51 175680 12 attrs->entry = entry;
52 175680 12 attrs->source = source;
53 175680 12 *out = attrs;
54 175680 12 return 0;
55 -
56 - on_error:
57 ##### 14 git__free(attrs);
58 ##### 15 return -1;
59 - }
60 -
61 175605 2 int git_attr_file__clear_rules(git_attr_file *file, bool need_lock)
62 - {
63 - unsigned int i;
64 - git_attr_rule *rule;
65 -
66 175605 2-4 if (need_lock && git_mutex_lock(&file->lock) < 0) {
67 ##### 5 git_error_set(GIT_ERROR_OS, "failed to lock attribute file");
68 ##### 6 return -1;
69 - }
70 -
71 180203 7,9-11 git_vector_foreach(&file->rules, i, rule)
72 4598 8 git_attr_rule__free(rule);
73 175605 12 git_vector_free(&file->rules);
74 -
75 175262 13 if (need_lock)
76 2 14 git_mutex_unlock(&file->lock);
77 -
78 175291 15 return 0;
79 - }
80 -
81 628045 2 void git_attr_file__free(git_attr_file *file)
82 - {
83 628045 2 if (!file)
84 628820 3,8 return;
85 573626 4-7 GIT_REFCOUNT_DEC(file, attr_file_free);
86 - }
87 -
88 - 2 suppressed: function cannot be solved attr_file_oid_from_index (automatic due to inconsistent arc counts in .gcda files)static int attr_file_oid_from_index(
89 - git_oid *oid, git_repository *repo, const char *path)
90 - {
91 - int error;
92 - git_index *idx;
93 - size_t pos;
94 - const git_index_entry *entry;
95 -
96 - 2-5 suppressed: function cannot be solved attr_file_oid_from_index (automatic due to inconsistent arc counts in .gcda files) if ((error = git_repository_index__weakptr(&idx, repo)) < 0 ||
97 - 4 suppressed: function cannot be solved attr_file_oid_from_index (automatic due to inconsistent arc counts in .gcda files) (error = git_index__find_pos(&pos, idx, path, 0, 0)) < 0)
98 - 6 suppressed: function cannot be solved attr_file_oid_from_index (automatic due to inconsistent arc counts in .gcda files) return error;
99 -
100 - 7,8 suppressed: function cannot be solved attr_file_oid_from_index (automatic due to inconsistent arc counts in .gcda files) if (!(entry = git_index_get_byindex(idx, pos)))
101 - 9 suppressed: function cannot be solved attr_file_oid_from_index (automatic due to inconsistent arc counts in .gcda files) return GIT_ENOTFOUND;
102 -
103 - 10 suppressed: function cannot be solved attr_file_oid_from_index (automatic due to inconsistent arc counts in .gcda files) *oid = entry->id;
104 - 10 suppressed: function cannot be solved attr_file_oid_from_index (automatic due to inconsistent arc counts in .gcda files) return 0;
105 - }
106 -
107 286082 2 int git_attr_file__load(
108 - git_attr_file **out,
109 - git_repository *repo,
110 - git_attr_session *attr_session,
111 - git_attr_file_entry *entry,
112 - git_attr_file_source source,
113 - git_attr_file_parser parser,
114 - bool allow_macros)
115 - {
116 286082 2 int error = 0;
117 286082 2 git_tree *tree = NULL;
118 286082 2 git_tree_entry *tree_entry = NULL;
119 286082 2 git_blob *blob = NULL;
120 286082 2 git_buf content = GIT_BUF_INIT;
121 - const char *content_str;
122 - git_attr_file *file;
123 - struct stat st;
124 286082 2 bool nonexistent = false;
125 - int bom_offset;
126 - git_bom_t bom;
127 - git_oid id;
128 - git_object_size_t blobsize;
129 -
130 286082 2 *out = NULL;
131 -
132 286082 2 switch (source) {
133 - case GIT_ATTR_FILE__IN_MEMORY:
134 - /* in-memory attribute file doesn't need data */
135 1012 3 break;
136 - case GIT_ATTR_FILE__FROM_INDEX: {
137 110719 4-7 if ((error = attr_file_oid_from_index(&id, repo, entry->path)) < 0 ||
138 - (error = git_blob_lookup(&blob, repo, &id)) < 0)
139 110332 8 return error;
140 -
141 - /* Do not assume that data straight from the ODB is NULL-terminated;
142 - * copy the contents of a file to a buffer to work on */
143 9 9 blobsize = git_blob_rawsize(blob);
144 -
145 9 10-13 GIT_ERROR_CHECK_BLOBSIZE(blobsize);
146 9 14,15 git_buf_put(&content, git_blob_rawcontent(blob), (size_t)blobsize);
147 9 46 break;
148 - }
149 - case GIT_ATTR_FILE__FROM_FILE: {
150 174346 16 int fd = -1;
151 -
152 - /* For open or read errors, pretend that we got ENOTFOUND. */
153 - /* TODO: issue warning when warning API is available */
154 -
155 174624 16-18 if (p_stat(entry->fullpath, &st) < 0 ||
156 1172 18-20 S_ISDIR(st.st_mode) ||
157 1168 19,21,22 (fd = git_futils_open_ro(entry->fullpath)) < 0 ||
158 1168 21 (error = git_futils_readbuffer_fd(&content, fd, (size_t)st.st_size)) < 0)
159 173473 23 nonexistent = true;
160 -
161 174600 24 if (fd >= 0)
162 1168 25 p_close(fd);
163 -
164 174600 26 break;
165 - }
166 - case GIT_ATTR_FILE__FROM_HEAD: {
167 5 27-30 if ((error = git_repository_head_tree(&tree, repo)) < 0 ||
168 5 29,32,33 (error = git_tree_entry_bypath(&tree_entry, tree, entry->path)) < 0 ||
169 5 31 (error = git_blob_lookup(&blob, repo, git_tree_entry_id(tree_entry))) < 0)
170 - goto cleanup;
171 -
172 - /*
173 - * Do not assume that data straight from the ODB is NULL-terminated;
174 - * copy the contents of a file to a buffer to work on.
175 - */
176 5 34 blobsize = git_blob_rawsize(blob);
177 -
178 5 35-38 GIT_ERROR_CHECK_BLOBSIZE(blobsize);
179 5 40,41 if ((error = git_buf_put(&content,
180 5 39 git_blob_rawcontent(blob), (size_t)blobsize)) < 0)
181 ##### 42 goto cleanup;
182 -
183 5 43 break;
184 - }
185 - default:
186 ##### 44 git_error_set(GIT_ERROR_INVALID, "unknown file source %d", source);
187 ##### 45 return -1;
188 - }
189 -
190 175626 47,48 if ((error = git_attr_file__new(&file, entry, source)) < 0)
191 ##### 49 goto cleanup;
192 -
193 - /* advance over a UTF8 BOM */
194 175621 50 content_str = git_buf_cstr(&content);
195 175584 51 bom_offset = git_buf_text_detect_bom(&bom, &content);
196 -
197 175548 52 if (bom == GIT_BOM_UTF8)
198 1 53 content_str += bom_offset;
199 -
200 - /* store the key of the attr_reader; don't bother with cache
201 - * invalidation during the same attr reader session.
202 - */
203 175548 54 if (attr_session)
204 2443 55 file->session_key = attr_session->key;
205 -
206 175548 56-58 if (parser && (error = parser(repo, file, content_str, allow_macros)) < 0) {
207 ##### 59 git_attr_file__free(file);
208 ##### 60 goto cleanup;
209 - }
210 -
211 - /* write cache breakers */
212 175553 61 if (nonexistent)
213 173359 62 file->nonexistent = 1;
214 2194 63 else if (source == GIT_ATTR_FILE__FROM_INDEX)
215 9 64,65 git_oid_cpy(&file->cache_data.oid, git_blob_id(blob));
216 2185 66 else if (source == GIT_ATTR_FILE__FROM_HEAD)
217 5 67,68 git_oid_cpy(&file->cache_data.oid, git_tree_id(tree));
218 2180 69 else if (source == GIT_ATTR_FILE__FROM_FILE)
219 1168 70 git_futils_filestamp_set_from_stat(&file->cache_data.stamp, &st);
220 - /* else always cacheable */
221 -
222 175480 71 *out = file;
223 -
224 - cleanup:
225 175480 72 git_blob_free(blob);
226 175282 73 git_tree_entry_free(tree_entry);
227 175193 74 git_tree_free(tree);
228 175091 75 git_buf_dispose(&content);
229 -
230 174996 76 return error;
231 - }
232 -
233 222901 2 int git_attr_file__out_of_date(
234 - git_repository *repo,
235 - git_attr_session *attr_session,
236 - git_attr_file *file)
237 - {
238 222901 2 if (!file)
239 ##### 3 return 1;
240 -
241 - /* we are never out of date if we just created this data in the same
242 - * attr_session; otherwise, nonexistent files must be invalidated
243 - */
244 222901 4,5 if (attr_session && attr_session->key == file->session_key)
245 23685 6 return 0;
246 199216 7 else if (file->nonexistent)
247 168915 8 return 1;
248 -
249 30301 9 switch (file->source) {
250 - case GIT_ATTR_FILE__IN_MEMORY:
251 1935 10 return 0;
252 -
253 - case GIT_ATTR_FILE__FROM_FILE:
254 28162 11 return git_futils_filestamp_check(
255 28162 11 &file->cache_data.stamp, file->entry->fullpath);
256 -
257 - case GIT_ATTR_FILE__FROM_INDEX: {
258 - int error;
259 - git_oid id;
260 -
261 151 12,13 if ((error = attr_file_oid_from_index(
262 151 12 &id, repo, file->entry->path)) < 0)
263 ##### 14 return error;
264 -
265 151 15-17 return (git_oid__cmp(&file->cache_data.oid, &id) != 0);
266 - }
267 -
268 - case GIT_ATTR_FILE__FROM_HEAD: {
269 - git_tree *tree;
270 - int error;
271 -
272 53 18,19 if ((error = git_repository_head_tree(&tree, repo)) < 0)
273 ##### 20 return error;
274 -
275 53 21,22 error = git_oid__cmp(&file->cache_data.oid, git_tree_id(tree));
276 -
277 53 23 git_tree_free(tree);
278 53 24,25 return error;
279 - }
280 -
281 - default:
282 ##### 26 git_error_set(GIT_ERROR_INVALID, "invalid file type %d", file->source);
283 ##### 27 return -1;
284 - }
285 - }
286 -
287 - static int sort_by_hash_and_name(const void *a_raw, const void *b_raw);
288 - static void git_attr_rule__clear(git_attr_rule *rule);
289 - static bool parse_optimized_patterns(
290 - git_attr_fnmatch *spec,
291 - git_pool *pool,
292 - const char *pattern);
293 -
294 168498 2 int git_attr_file__parse_buffer(
295 - git_repository *repo, git_attr_file *attrs, const char *data, bool allow_macros)
296 - {
297 168498 2 const char *scan = data, *context = NULL;
298 168498 2 git_attr_rule *rule = NULL;
299 168498 2 int error = 0;
300 -
301 - /* If subdir file path, convert context for file paths */
302 168498 2-4,6 if (attrs->entry && git_path_root(attrs->entry->path) < 0 &&
303 166546 5 !git__suffixcmp(attrs->entry->path, "/" GIT_ATTR_FILE))
304 2133 7 context = attrs->entry->path;
305 -
306 168764 8,9 if (git_mutex_lock(&attrs->lock) < 0) {
307 ##### 10 git_error_set(GIT_ERROR_OS, "failed to lock attribute file");
308 6 11 return -1;
309 - }
310 -
311 170164 12,35,36 while (!error && *scan) {
312 - /* Allocate rule if needed, otherwise re-use previous rule */
313 1400 13 if (!rule) {
314 1302 14 rule = git__calloc(1, sizeof(*rule));
315 1302 15,16 GIT_ERROR_CHECK_ALLOC(rule);
316 - } else
317 98 17 git_attr_rule__clear(rule);
318 -
319 1400 18 rule->match.flags = GIT_ATTR_FNMATCH_ALLOWNEG | GIT_ATTR_FNMATCH_ALLOWMACRO;
320 -
321 - /* Parse the next "pattern attr attr attr" line */
322 1400 18-21 if ((error = git_attr_fnmatch__parse(&rule->match, &attrs->pool, context, &scan)) < 0 ||
323 1313 20 (error = git_attr_assignment__parse(repo, &attrs->pool, &rule->assigns, &scan)) < 0)
324 - {
325 97 22 if (error != GIT_ENOTFOUND)
326 ##### 23 goto out;
327 97 24 error = 0;
328 97 24 continue;
329 - }
330 -
331 1303 25 if (rule->match.flags & GIT_ATTR_FNMATCH_MACRO) {
332 - /* TODO: warning if macro found in file below repo root */
333 202 26 if (!allow_macros)
334 1 27 continue;
335 201 28,29 if ((error = git_attr_cache__insert_macro(repo, rule)) < 0)
336 ##### 30 goto out;
337 1101 31,32 } else if ((error = git_vector_insert(&attrs->rules, rule)) < 0)
338 ##### 33 goto out;
339 -
340 1302 34 rule = NULL;
341 - }
342 -
343 - out:
344 168764 37 git_mutex_unlock(&attrs->lock);
345 168753 38 git_attr_rule__free(rule);
346 -
347 168625 39 return error;
348 - }
349 -
350 19873 2 uint32_t git_attr_file__name_hash(const char *name)
351 - {
352 19873 2 uint32_t h = 5381;
353 - int c;
354 19873 2,3 assert(name);
355 131303 4,6 while ((c = (int)*name++) != 0)
356 111430 5 h = ((h << 5) + h) + c;
357 19873 7 return h;
358 - }
359 -
360 113 2 int git_attr_file__lookup_one(
361 - git_attr_file *file,
362 - git_attr_path *path,
363 - const char *attr,
364 - const char **value)
365 - {
366 - size_t i;
367 - git_attr_name name;
368 - git_attr_rule *rule;
369 -
370 113 2 *value = NULL;
371 -
372 113 2 name.name = attr;
373 113 2 name.name_hash = git_attr_file__name_hash(attr);
374 -
375 762 3-5,11-13 git_attr_file__foreach_matching_rule(file, path, i, rule) {
376 - size_t pos;
377 -
378 134 6,7 if (!git_vector_bsearch(&pos, &rule->assigns, &name)) {
379 68 8,9 *value = ((git_attr_assignment *)
380 68 8 git_vector_get(&rule->assigns, pos))->value;
381 68 9,10 break;
382 - }
383 - }
384 -
385 113 14 return 0;
386 - }
387 -
388 9 2 int git_attr_file__load_standalone(git_attr_file **out, const char *path)
389 - {
390 9 2 git_buf content = GIT_BUF_INIT;
391 9 2 git_attr_file *file = NULL;
392 - int error;
393 -
394 9 2,3 if ((error = git_futils_readbuffer(&content, path)) < 0)
395 ##### 4 goto out;
396 -
397 - /*
398 - * Because the cache entry is allocated from the file's own pool, we
399 - * don't have to free it - freeing file+pool will free cache entry, too.
400 - */
401 -
402 9 5-8 if ((error = git_attr_file__new(&file, NULL, GIT_ATTR_FILE__FROM_FILE)) < 0 ||
403 9 7,9,10 (error = git_attr_file__parse_buffer(NULL, file, content.ptr, true)) < 0 ||
404 9 9 (error = git_attr_cache__alloc_file_entry(&file->entry, NULL, path, &file->pool)) < 0)
405 - goto out;
406 -
407 9 11 *out = file;
408 - out:
409 9 12 if (error < 0)
410 ##### 13 git_attr_file__free(file);
411 9 14 git_buf_dispose(&content);
412 -
413 9 15 return error;
414 - }
415 -
416 51601 2 bool git_attr_fnmatch__match(
417 - git_attr_fnmatch *match,
418 - git_attr_path *path)
419 - {
420 51601 2 const char *relpath = path->path;
421 - const char *filename;
422 51601 2 int flags = 0;
423 -
424 - /*
425 - * If the rule was generated in a subdirectory, we must only
426 - * use it for paths inside that directory. We can thus return
427 - * a non-match if the prefixes don't match.
428 - */
429 51601 2 if (match->containing_dir) {
430 755 3 if (match->flags & GIT_ATTR_FNMATCH_ICASE) {
431 ##### 4,5 if (git__strncasecmp(path->path, match->containing_dir, match->containing_dir_length))
432 ##### 6 return 0;
433 - } else {
434 755 7,8 if (git__prefixcmp(path->path, match->containing_dir))
435 17 9 return 0;
436 - }
437 -
438 738 10 relpath += match->containing_dir_length;
439 - }
440 -
441 51584 11 if (match->flags & GIT_ATTR_FNMATCH_ICASE)
442 143 12 flags |= WM_CASEFOLD;
443 -
444 51584 13 if (match->flags & GIT_ATTR_FNMATCH_FULLPATH) {
445 1895 14 filename = relpath;
446 1895 14 flags |= WM_PATHNAME;
447 - } else {
448 49689 15 filename = path->basename;
449 - }
450 -
451 51584 16,17 if ((match->flags & GIT_ATTR_FNMATCH_DIRECTORY) && !path->is_dir) {
452 - bool samename;
453 -
454 - /*
455 - * for attribute checks or checks at the root of this match's
456 - * containing_dir (or root of the repository if no containing_dir),
457 - * do not match.
458 - */
459 33 18,19 if (!(match->flags & GIT_ATTR_FNMATCH_IGNORE) ||
460 ##### 19 path->basename == relpath)
461 33 20 return false;
462 -
463 - /* fail match if this is a file with same name as ignored folder */
464 ##### 21,24 samename = (match->flags & GIT_ATTR_FNMATCH_ICASE) ?
465 ##### 21-23 !strcasecmp(match->pattern, relpath) :
466 ##### 23 !strcmp(match->pattern, relpath);
467 -
468 ##### 24 if (samename)
469 ##### 25 return false;
470 -
471 ##### 26,27 return (wildmatch(match->pattern, relpath, flags) == WM_MATCH);
472 - }
473 -
474 51551 28 return (wildmatch(match->pattern, filename, flags) == WM_MATCH);
475 - }
476 -
477 23967 2 bool git_attr_rule__match(
478 - git_attr_rule *rule,
479 - git_attr_path *path)
480 - {
481 23967 2 bool matched = git_attr_fnmatch__match(&rule->match, path);
482 -
483 23967 3 if (rule->match.flags & GIT_ATTR_FNMATCH_NEGATIVE)
484 34 4 matched = !matched;
485 -
486 23967 5 return matched;
487 - }
488 -
489 16 2 git_attr_assignment *git_attr_rule__lookup_assignment(
490 - git_attr_rule *rule, const char *name)
491 - {
492 - size_t pos;
493 - git_attr_name key;
494 16 2 key.name = name;
495 16 2 key.name_hash = git_attr_file__name_hash(name);
496 -
497 16 3,4 if (git_vector_bsearch(&pos, &rule->assigns, &key))
498 3 5 return NULL;
499 -
500 13 6 return git_vector_get(&rule->assigns, pos);
501 - }
502 -
503 - 2 suppressed: function cannot be solved git_attr_path__init (automatic due to inconsistent arc counts in .gcda files)int git_attr_path__init(
504 - git_attr_path *info, const char *path, const char *base, git_dir_flag dir_flag)
505 - {
506 - ssize_t root;
507 -
508 - /* build full path as best we can */
509 - 2 suppressed: function cannot be solved git_attr_path__init (automatic due to inconsistent arc counts in .gcda files) git_buf_init(&info->full, 0);
510 -
511 - 3,4 suppressed: function cannot be solved git_attr_path__init (automatic due to inconsistent arc counts in .gcda files) if (git_path_join_unrooted(&info->full, path, base, &root) < 0)
512 - 5 suppressed: function cannot be solved git_attr_path__init (automatic due to inconsistent arc counts in .gcda files) return -1;
513 -
514 - 6 suppressed: function cannot be solved git_attr_path__init (automatic due to inconsistent arc counts in .gcda files) info->path = info->full.ptr + root;
515 -
516 - /* remove trailing slashes */
517 - 6,10 suppressed: function cannot be solved git_attr_path__init (automatic due to inconsistent arc counts in .gcda files) while (info->full.size > 0) {
518 - 7 suppressed: function cannot be solved git_attr_path__init (automatic due to inconsistent arc counts in .gcda files) if (info->full.ptr[info->full.size - 1] != '/')
519 - 8 suppressed: function cannot be solved git_attr_path__init (automatic due to inconsistent arc counts in .gcda files) break;
520 - 9 suppressed: function cannot be solved git_attr_path__init (automatic due to inconsistent arc counts in .gcda files) info->full.size--;
521 - }
522 - 11 suppressed: function cannot be solved git_attr_path__init (automatic due to inconsistent arc counts in .gcda files) info->full.ptr[info->full.size] = '\0';
523 -
524 - /* skip leading slashes in path */
525 - 11,13 suppressed: function cannot be solved git_attr_path__init (automatic due to inconsistent arc counts in .gcda files) while (*info->path == '/')
526 - 12 suppressed: function cannot be solved git_attr_path__init (automatic due to inconsistent arc counts in .gcda files) info->path++;
527 -
528 - /* find trailing basename component */
529 - 14 suppressed: function cannot be solved git_attr_path__init (automatic due to inconsistent arc counts in .gcda files) info->basename = strrchr(info->path, '/');
530 - 14 suppressed: function cannot be solved git_attr_path__init (automatic due to inconsistent arc counts in .gcda files) if (info->basename)
531 - 15 suppressed: function cannot be solved git_attr_path__init (automatic due to inconsistent arc counts in .gcda files) info->basename++;
532 - 16,17 suppressed: function cannot be solved git_attr_path__init (automatic due to inconsistent arc counts in .gcda files) if (!info->basename || !*info->basename)
533 - 18 suppressed: function cannot be solved git_attr_path__init (automatic due to inconsistent arc counts in .gcda files) info->basename = info->path;
534 -
535 - 19 suppressed: function cannot be solved git_attr_path__init (automatic due to inconsistent arc counts in .gcda files) switch (dir_flag)
536 - {
537 - case GIT_DIR_FLAG_FALSE:
538 - 20 suppressed: function cannot be solved git_attr_path__init (automatic due to inconsistent arc counts in .gcda files) info->is_dir = 0;
539 - 20 suppressed: function cannot be solved git_attr_path__init (automatic due to inconsistent arc counts in .gcda files) break;
540 -
541 - case GIT_DIR_FLAG_TRUE:
542 - 21 suppressed: function cannot be solved git_attr_path__init (automatic due to inconsistent arc counts in .gcda files) info->is_dir = 1;
543 - 21 suppressed: function cannot be solved git_attr_path__init (automatic due to inconsistent arc counts in .gcda files) break;
544 -
545 - case GIT_DIR_FLAG_UNKNOWN:
546 - default:
547 - 22 suppressed: function cannot be solved git_attr_path__init (automatic due to inconsistent arc counts in .gcda files) info->is_dir = (int)git_path_isdir(info->full.ptr);
548 - 23 suppressed: function cannot be solved git_attr_path__init (automatic due to inconsistent arc counts in .gcda files) break;
549 - }
550 -
551 - 24 suppressed: function cannot be solved git_attr_path__init (automatic due to inconsistent arc counts in .gcda files) return 0;
552 - }
553 -
554 66989 2 void git_attr_path__free(git_attr_path *info)
555 - {
556 66989 2 git_buf_dispose(&info->full);
557 66987 3 info->path = NULL;
558 66987 3 info->basename = NULL;
559 66987 3 }
560 -
561 - /*
562 - * From gitattributes(5):
563 - *
564 - * Patterns have the following format:
565 - *
566 - * - A blank line matches no files, so it can serve as a separator for
567 - * readability.
568 - *
569 - * - A line starting with # serves as a comment.
570 - *
571 - * - An optional prefix ! which negates the pattern; any matching file
572 - * excluded by a previous pattern will become included again. If a negated
573 - * pattern matches, this will override lower precedence patterns sources.
574 - *
575 - * - If the pattern ends with a slash, it is removed for the purpose of the
576 - * following description, but it would only find a match with a directory. In
577 - * other words, foo/ will match a directory foo and paths underneath it, but
578 - * will not match a regular file or a symbolic link foo (this is consistent
579 - * with the way how pathspec works in general in git).
580 - *
581 - * - If the pattern does not contain a slash /, git treats it as a shell glob
582 - * pattern and checks for a match against the pathname without leading
583 - * directories.
584 - *
585 - * - Otherwise, git treats the pattern as a shell glob suitable for consumption
586 - * by fnmatch(3) with the FNM_PATHNAME flag: wildcards in the pattern will
587 - * not match a / in the pathname. For example, "Documentation/\*.html" matches
588 - * "Documentation/git.html" but not "Documentation/ppc/ppc.html". A leading
589 - * slash matches the beginning of the pathname; for example, "/\*.c" matches
590 - * "cat-file.c" but not "mozilla-sha1/sha1.c".
591 - */
592 -
593 - /*
594 - * Determine the length of trailing spaces. Escaped spaces do not count as
595 - * trailing whitespace.
596 - */
597 10512 2 static size_t trailing_space_length(const char *p, size_t len)
598 - {
599 - size_t n, i;
600 10519 2,12,13 for (n = len; n; n--) {
601 10519 3,4 if (p[n-1] != ' ' && p[n-1] != '\t')
602 10507 5 break;
603 -
604 - /*
605 - * Count escape-characters before space. In case where it's an
606 - * even number of escape characters, then the escape char itself
607 - * is escaped and the whitespace is an unescaped whitespace.
608 - * Otherwise, the last escape char is not escaped and the
609 - * whitespace in an escaped whitespace.
610 - */
611 12 6 i = n;
612 21 6,8,9 while (i > 1 && p[i-2] == '\\')
613 9 7 i--;
614 12 10 if ((n - i) % 2)
615 5 11 break;
616 - }
617 10512 14 return len - n;
618 - }
619 -
620 10511 2 static size_t unescape_spaces(char *str)
621 - {
622 10511 2 char *scan, *pos = str;
623 10511 2 bool escaped = false;
624 -
625 10511 2 if (!str)
626 ##### 3 return 0;
627 -
628 101380 4,13,14 for (scan = str; *scan; scan++) {
629 90869 5,6 if (!escaped && *scan == '\\') {
630 27 7 escaped = true;
631 27 7 continue;
632 - }
633 -
634 - /* Only insert the escape character for escaped non-spaces */
635 90842 8-10 if (escaped && !git__isspace(*scan))
636 16 11 *pos++ = '\\';
637 -
638 90842 12 *pos++ = *scan;
639 90842 12 escaped = false;
640 - }
641 -
642 10511 15 if (pos != scan)
643 8 16 *pos = '\0';
644 -
645 10511 17 return (pos - str);
646 - }
647 -
648 - /*
649 - * This will return 0 if the spec was filled out,
650 - * GIT_ENOTFOUND if the fnmatch does not require matching, or
651 - * another error code there was an actual problem.
652 - */
653 - 2 suppressed: function cannot be solved git_attr_fnmatch__parse (automatic due to inconsistent arc counts in .gcda files)int git_attr_fnmatch__parse(
654 - git_attr_fnmatch *spec,
655 - git_pool *pool,
656 - const char *context,
657 - const char **base)
658 - {
659 - const char *pattern, *scan;
660 - int slash_count, allow_space;
661 - bool escaped;
662 -
663 - 2-5 suppressed: function cannot be solved git_attr_fnmatch__parse (automatic due to inconsistent arc counts in .gcda files) assert(spec && base && *base);
664 -
665 - 6,7 suppressed: function cannot be solved git_attr_fnmatch__parse (automatic due to inconsistent arc counts in .gcda files) if (parse_optimized_patterns(spec, pool, *base))
666 - 8 suppressed: function cannot be solved git_attr_fnmatch__parse (automatic due to inconsistent arc counts in .gcda files) return 0;
667 -
668 - 9 suppressed: function cannot be solved git_attr_fnmatch__parse (automatic due to inconsistent arc counts in .gcda files) spec->flags = (spec->flags & GIT_ATTR_FNMATCH__INCOMING);
669 - 9 suppressed: function cannot be solved git_attr_fnmatch__parse (automatic due to inconsistent arc counts in .gcda files) allow_space = ((spec->flags & GIT_ATTR_FNMATCH_ALLOWSPACE) != 0);
670 -
671 - 9 suppressed: function cannot be solved git_attr_fnmatch__parse (automatic due to inconsistent arc counts in .gcda files) pattern = *base;
672 -
673 - 9,11-13 suppressed: function cannot be solved git_attr_fnmatch__parse (automatic due to inconsistent arc counts in .gcda files) while (!allow_space && git__isspace(*pattern))
674 - 10 suppressed: function cannot be solved git_attr_fnmatch__parse (automatic due to inconsistent arc counts in .gcda files) pattern++;
675 -
676 - 14-17 suppressed: function cannot be solved git_attr_fnmatch__parse (automatic due to inconsistent arc counts in .gcda files) if (!*pattern || *pattern == '#' || *pattern == '\n' ||
677 - 17,18 suppressed: function cannot be solved git_attr_fnmatch__parse (automatic due to inconsistent arc counts in .gcda files) (*pattern == '\r' && *(pattern + 1) == '\n')) {
678 - 19 suppressed: function cannot be solved git_attr_fnmatch__parse (automatic due to inconsistent arc counts in .gcda files) *base = git__next_line(pattern);
679 - 20 suppressed: function cannot be solved git_attr_fnmatch__parse (automatic due to inconsistent arc counts in .gcda files) return GIT_ENOTFOUND;
680 - }
681 -
682 - 21,22 suppressed: function cannot be solved git_attr_fnmatch__parse (automatic due to inconsistent arc counts in .gcda files) if (*pattern == '[' && (spec->flags & GIT_ATTR_FNMATCH_ALLOWMACRO) != 0) {
683 - 23 suppressed: function cannot be solved git_attr_fnmatch__parse (automatic due to inconsistent arc counts in .gcda files) if (strncmp(pattern, "[attr]", 6) == 0) {
684 - 24 suppressed: function cannot be solved git_attr_fnmatch__parse (automatic due to inconsistent arc counts in .gcda files) spec->flags = spec->flags | GIT_ATTR_FNMATCH_MACRO;
685 - 24 suppressed: function cannot be solved git_attr_fnmatch__parse (automatic due to inconsistent arc counts in .gcda files) pattern += 6;
686 - }
687 - /* else a character range like [a-e]* which is accepted */
688 - }
689 -
690 - 25,26 suppressed: function cannot be solved git_attr_fnmatch__parse (automatic due to inconsistent arc counts in .gcda files) if (*pattern == '!' && (spec->flags & GIT_ATTR_FNMATCH_ALLOWNEG) != 0) {
691 - 27 suppressed: function cannot be solved git_attr_fnmatch__parse (automatic due to inconsistent arc counts in .gcda files) spec->flags = spec->flags | GIT_ATTR_FNMATCH_NEGATIVE;
692 - 27 suppressed: function cannot be solved git_attr_fnmatch__parse (automatic due to inconsistent arc counts in .gcda files) pattern++;
693 - }
694 -
695 - 28 suppressed: function cannot be solved git_attr_fnmatch__parse (automatic due to inconsistent arc counts in .gcda files) slash_count = 0;
696 - 28 suppressed: function cannot be solved git_attr_fnmatch__parse (automatic due to inconsistent arc counts in .gcda files) escaped = false;
697 - /* Scan until a non-escaped whitespace. */
698 - 28,50,51 suppressed: function cannot be solved git_attr_fnmatch__parse (automatic due to inconsistent arc counts in .gcda files) for (scan = pattern; *scan != '\0'; ++scan) {
699 - 29 suppressed: function cannot be solved git_attr_fnmatch__parse (automatic due to inconsistent arc counts in .gcda files) char c = *scan;
700 -
701 - 29,30 suppressed: function cannot be solved git_attr_fnmatch__parse (automatic due to inconsistent arc counts in .gcda files) if (c == '\\' && !escaped) {
702 - 31 suppressed: function cannot be solved git_attr_fnmatch__parse (automatic due to inconsistent arc counts in .gcda files) escaped = true;
703 - 31 suppressed: function cannot be solved git_attr_fnmatch__parse (automatic due to inconsistent arc counts in .gcda files) continue;
704 - 32-34 suppressed: function cannot be solved git_attr_fnmatch__parse (automatic due to inconsistent arc counts in .gcda files) } else if (git__isspace(c) && !escaped) {
705 - 35-39 suppressed: function cannot be solved git_attr_fnmatch__parse (automatic due to inconsistent arc counts in .gcda files) if (!allow_space || (c != ' ' && c != '\t' && c != '\r'))
706 - break;
707 - 40 suppressed: function cannot be solved git_attr_fnmatch__parse (automatic due to inconsistent arc counts in .gcda files) } else if (c == '/') {
708 - 41 suppressed: function cannot be solved git_attr_fnmatch__parse (automatic due to inconsistent arc counts in .gcda files) spec->flags = spec->flags | GIT_ATTR_FNMATCH_FULLPATH;
709 - 41 suppressed: function cannot be solved git_attr_fnmatch__parse (automatic due to inconsistent arc counts in .gcda files) slash_count++;
710 -
711 - 41,42 suppressed: function cannot be solved git_attr_fnmatch__parse (automatic due to inconsistent arc counts in .gcda files) if (slash_count == 1 && pattern == scan)
712 - 43,44 suppressed: function cannot be solved git_attr_fnmatch__parse (automatic due to inconsistent arc counts in .gcda files) pattern++;
713 - 45-47 suppressed: function cannot be solved git_attr_fnmatch__parse (automatic due to inconsistent arc counts in .gcda files) } else if (git__iswildcard(c) && !escaped) {
714 - /* remember if we see an unescaped wildcard in pattern */
715 - 48 suppressed: function cannot be solved git_attr_fnmatch__parse (automatic due to inconsistent arc counts in .gcda files) spec->flags = spec->flags | GIT_ATTR_FNMATCH_HASWILD;
716 - }
717 -
718 - 49 suppressed: function cannot be solved git_attr_fnmatch__parse (automatic due to inconsistent arc counts in .gcda files) escaped = false;
719 - }
720 -
721 - 52 suppressed: function cannot be solved git_attr_fnmatch__parse (automatic due to inconsistent arc counts in .gcda files) *base = scan;
722 -
723 - 52 suppressed: function cannot be solved git_attr_fnmatch__parse (automatic due to inconsistent arc counts in .gcda files) if ((spec->length = scan - pattern) == 0)
724 - 53 suppressed: function cannot be solved git_attr_fnmatch__parse (automatic due to inconsistent arc counts in .gcda files) return GIT_ENOTFOUND;
725 -
726 - /*
727 - * Remove one trailing \r in case this is a CRLF delimited
728 - * file, in the case of Icon\r\r\n, we still leave the first
729 - * \r there to match against.
730 - */
731 - 54 suppressed: function cannot be solved git_attr_fnmatch__parse (automatic due to inconsistent arc counts in .gcda files) if (pattern[spec->length - 1] == '\r')
732 - 55 suppressed: function cannot be solved git_attr_fnmatch__parse (automatic due to inconsistent arc counts in .gcda files) if (--spec->length == 0)
733 - 56 suppressed: function cannot be solved git_attr_fnmatch__parse (automatic due to inconsistent arc counts in .gcda files) return GIT_ENOTFOUND;
734 -
735 - /* Remove trailing spaces. */
736 - 57 suppressed: function cannot be solved git_attr_fnmatch__parse (automatic due to inconsistent arc counts in .gcda files) spec->length -= trailing_space_length(pattern, spec->length);
737 -
738 - 58 suppressed: function cannot be solved git_attr_fnmatch__parse (automatic due to inconsistent arc counts in .gcda files) if (spec->length == 0)
739 - 59 suppressed: function cannot be solved git_attr_fnmatch__parse (automatic due to inconsistent arc counts in .gcda files) return GIT_ENOTFOUND;
740 -
741 - 60 suppressed: function cannot be solved git_attr_fnmatch__parse (automatic due to inconsistent arc counts in .gcda files) if (pattern[spec->length - 1] == '/') {
742 - 61 suppressed: function cannot be solved git_attr_fnmatch__parse (automatic due to inconsistent arc counts in .gcda files) spec->length--;
743 - 61 suppressed: function cannot be solved git_attr_fnmatch__parse (automatic due to inconsistent arc counts in .gcda files) spec->flags = spec->flags | GIT_ATTR_FNMATCH_DIRECTORY;
744 - 61 suppressed: function cannot be solved git_attr_fnmatch__parse (automatic due to inconsistent arc counts in .gcda files) if (--slash_count <= 0)
745 - 62 suppressed: function cannot be solved git_attr_fnmatch__parse (automatic due to inconsistent arc counts in .gcda files) spec->flags = spec->flags & ~GIT_ATTR_FNMATCH_FULLPATH;
746 - }
747 -
748 - 63 suppressed: function cannot be solved git_attr_fnmatch__parse (automatic due to inconsistent arc counts in .gcda files) if (context) {
749 - 64 suppressed: function cannot be solved git_attr_fnmatch__parse (automatic due to inconsistent arc counts in .gcda files) char *slash = strrchr(context, '/');
750 - size_t len;
751 - 64 suppressed: function cannot be solved git_attr_fnmatch__parse (automatic due to inconsistent arc counts in .gcda files) if (slash) {
752 - /* include the slash for easier matching */
753 - 65 suppressed: function cannot be solved git_attr_fnmatch__parse (automatic due to inconsistent arc counts in .gcda files) len = slash - context + 1;
754 - 65 suppressed: function cannot be solved git_attr_fnmatch__parse (automatic due to inconsistent arc counts in .gcda files) spec->containing_dir = git_pool_strndup(pool, context, len);
755 - 66 suppressed: function cannot be solved git_attr_fnmatch__parse (automatic due to inconsistent arc counts in .gcda files) spec->containing_dir_length = len;
756 - }
757 - }
758 -
759 - 67 suppressed: function cannot be solved git_attr_fnmatch__parse (automatic due to inconsistent arc counts in .gcda files) spec->pattern = git_pool_strndup(pool, pattern, spec->length);
760 -
761 - 68 suppressed: function cannot be solved git_attr_fnmatch__parse (automatic due to inconsistent arc counts in .gcda files) if (!spec->pattern) {
762 - 69 suppressed: function cannot be solved git_attr_fnmatch__parse (automatic due to inconsistent arc counts in .gcda files) *base = git__next_line(pattern);
763 - 70 suppressed: function cannot be solved git_attr_fnmatch__parse (automatic due to inconsistent arc counts in .gcda files) return -1;
764 - } else {
765 - /* strip '\' that might have been used for internal whitespace */
766 - 71 suppressed: function cannot be solved git_attr_fnmatch__parse (automatic due to inconsistent arc counts in .gcda files) spec->length = unescape_spaces(spec->pattern);
767 - }
768 -
769 - 72 suppressed: function cannot be solved git_attr_fnmatch__parse (automatic due to inconsistent arc counts in .gcda files) return 0;
770 - }
771 -
772 14500 2 static bool parse_optimized_patterns(
773 - git_attr_fnmatch *spec,
774 - git_pool *pool,
775 - const char *pattern)
776 - {
777 14500 2-4 if (!pattern[1] && (pattern[0] == '*' || pattern[0] == '.')) {
778 4 5 spec->flags = GIT_ATTR_FNMATCH_MATCH_ALL;
779 4 5 spec->pattern = git_pool_strndup(pool, pattern, 1);
780 4 6 spec->length = 1;
781 -
782 4 6 return true;
783 - }
784 -
785 14496 7 return false;
786 - }
787 -
788 36234 2 static int sort_by_hash_and_name(const void *a_raw, const void *b_raw)
789 - {
790 36234 2 const git_attr_name *a = a_raw;
791 36234 2 const git_attr_name *b = b_raw;
792 -
793 36234 2 if (b->name_hash < a->name_hash)
794 13802 3 return 1;
795 22432 4 else if (b->name_hash > a->name_hash)
796 17290 5 return -1;
797 - else
798 5142 6 return strcmp(b->name, a->name);
799 - }
800 -
801 7440 2 static void git_attr_assignment__free(git_attr_assignment *assign)
802 - {
803 - /* name and value are stored in a git_pool associated with the
804 - * git_attr_file, so they do not need to be freed here
805 - */
806 7440 2 assign->name = NULL;
807 7440 2 assign->value = NULL;
808 7440 2 git__free(assign);
809 7440 3 }
810 -
811 660 2 static int merge_assignments(void **old_raw, void *new_raw)
812 - {
813 660 2 git_attr_assignment **old = (git_attr_assignment **)old_raw;
814 660 2 git_attr_assignment *new = (git_attr_assignment *)new_raw;
815 -
816 660 2-5 GIT_REFCOUNT_DEC(*old, git_attr_assignment__free);
817 660 6 *old = new;
818 660 6 return GIT_EEXISTS;
819 - }
820 -
821 - 2 suppressed: function cannot be solved git_attr_assignment__parse (automatic due to inconsistent arc counts in .gcda files)int git_attr_assignment__parse(
822 - git_repository *repo,
823 - git_pool *pool,
824 - git_vector *assigns,
825 - const char **base)
826 - {
827 - int error;
828 - 2 suppressed: function cannot be solved git_attr_assignment__parse (automatic due to inconsistent arc counts in .gcda files) const char *scan = *base;
829 - 2 suppressed: function cannot be solved git_attr_assignment__parse (automatic due to inconsistent arc counts in .gcda files) git_attr_assignment *assign = NULL;
830 -
831 - 2-4 suppressed: function cannot be solved git_attr_assignment__parse (automatic due to inconsistent arc counts in .gcda files) assert(assigns && !assigns->length);
832 -
833 - 5 suppressed: function cannot be solved git_attr_assignment__parse (automatic due to inconsistent arc counts in .gcda files) git_vector_set_cmp(assigns, sort_by_hash_and_name);
834 -
835 - 6,68,69 suppressed: function cannot be solved git_attr_assignment__parse (automatic due to inconsistent arc counts in .gcda files) while (*scan && *scan != '\n') {
836 - const char *name_start, *value_start;
837 -
838 - /* skip leading blanks */
839 - 7-11 suppressed: function cannot be solved git_attr_assignment__parse (automatic due to inconsistent arc counts in .gcda files) while (git__isspace(*scan) && *scan != '\n') scan++;
840 -
841 - /* allocate assign if needed */
842 - 12 suppressed: function cannot be solved git_attr_assignment__parse (automatic due to inconsistent arc counts in .gcda files) if (!assign) {
843 - 13 suppressed: function cannot be solved git_attr_assignment__parse (automatic due to inconsistent arc counts in .gcda files) assign = git__calloc(1, sizeof(git_attr_assignment));
844 - 14,15 suppressed: function cannot be solved git_attr_assignment__parse (automatic due to inconsistent arc counts in .gcda files) GIT_ERROR_CHECK_ALLOC(assign);
845 - 16 suppressed: function cannot be solved git_attr_assignment__parse (automatic due to inconsistent arc counts in .gcda files) GIT_REFCOUNT_INC(assign);
846 - }
847 -
848 - 17 suppressed: function cannot be solved git_attr_assignment__parse (automatic due to inconsistent arc counts in .gcda files) assign->name_hash = 5381;
849 - 17 suppressed: function cannot be solved git_attr_assignment__parse (automatic due to inconsistent arc counts in .gcda files) assign->value = git_attr__true;
850 -
851 - /* look for magic name prefixes */
852 - 17 suppressed: function cannot be solved git_attr_assignment__parse (automatic due to inconsistent arc counts in .gcda files) if (*scan == '-') {
853 - 18 suppressed: function cannot be solved git_attr_assignment__parse (automatic due to inconsistent arc counts in .gcda files) assign->value = git_attr__false;
854 - 18 suppressed: function cannot be solved git_attr_assignment__parse (automatic due to inconsistent arc counts in .gcda files) scan++;
855 - 19 suppressed: function cannot be solved git_attr_assignment__parse (automatic due to inconsistent arc counts in .gcda files) } else if (*scan == '!') {
856 - 20 suppressed: function cannot be solved git_attr_assignment__parse (automatic due to inconsistent arc counts in .gcda files) assign->value = git_attr__unset; /* explicit unspecified state */
857 - 20 suppressed: function cannot be solved git_attr_assignment__parse (automatic due to inconsistent arc counts in .gcda files) scan++;
858 - 21 suppressed: function cannot be solved git_attr_assignment__parse (automatic due to inconsistent arc counts in .gcda files) } else if (*scan == '#') /* comment rest of line */
859 - 22 suppressed: function cannot be solved git_attr_assignment__parse (automatic due to inconsistent arc counts in .gcda files) break;
860 -
861 - /* find the name */
862 - 23 suppressed: function cannot be solved git_attr_assignment__parse (automatic due to inconsistent arc counts in .gcda files) name_start = scan;
863 - 23,25-28 suppressed: function cannot be solved git_attr_assignment__parse (automatic due to inconsistent arc counts in .gcda files) while (*scan && !git__isspace(*scan) && *scan != '=') {
864 - 24 suppressed: function cannot be solved git_attr_assignment__parse (automatic due to inconsistent arc counts in .gcda files) assign->name_hash =
865 - 24 suppressed: function cannot be solved git_attr_assignment__parse (automatic due to inconsistent arc counts in .gcda files) ((assign->name_hash << 5) + assign->name_hash) + *scan;
866 - 24 suppressed: function cannot be solved git_attr_assignment__parse (automatic due to inconsistent arc counts in .gcda files) scan++;
867 - }
868 - 29 suppressed: function cannot be solved git_attr_assignment__parse (automatic due to inconsistent arc counts in .gcda files) if (scan == name_start) {
869 - /* must have found lone prefix (" - ") or leading = ("=foo")
870 - * or end of buffer -- advance until whitespace and continue
871 - */
872 - 30-34 suppressed: function cannot be solved git_attr_assignment__parse (automatic due to inconsistent arc counts in .gcda files) while (*scan && !git__isspace(*scan)) scan++;
873 - 35 suppressed: function cannot be solved git_attr_assignment__parse (automatic due to inconsistent arc counts in .gcda files) continue;
874 - }
875 -
876 - /* allocate permanent storage for name */
877 - 36 suppressed: function cannot be solved git_attr_assignment__parse (automatic due to inconsistent arc counts in .gcda files) assign->name = git_pool_strndup(pool, name_start, scan - name_start);
878 - 37,38 suppressed: function cannot be solved git_attr_assignment__parse (automatic due to inconsistent arc counts in .gcda files) GIT_ERROR_CHECK_ALLOC(assign->name);
879 -
880 - /* if there is an equals sign, find the value */
881 - 39 suppressed: function cannot be solved git_attr_assignment__parse (automatic due to inconsistent arc counts in .gcda files) if (*scan == '=') {
882 - 40-44 suppressed: function cannot be solved git_attr_assignment__parse (automatic due to inconsistent arc counts in .gcda files) for (value_start = ++scan; *scan && !git__isspace(*scan); ++scan);
883 -
884 - /* if we found a value, allocate permanent storage for it */
885 - 45 suppressed: function cannot be solved git_attr_assignment__parse (automatic due to inconsistent arc counts in .gcda files) if (scan > value_start) {
886 - 46 suppressed: function cannot be solved git_attr_assignment__parse (automatic due to inconsistent arc counts in .gcda files) assign->value = git_pool_strndup(pool, value_start, scan - value_start);
887 - 47,48 suppressed: function cannot be solved git_attr_assignment__parse (automatic due to inconsistent arc counts in .gcda files) GIT_ERROR_CHECK_ALLOC(assign->value);
888 - }
889 - }
890 -
891 - /* expand macros (if given a repo with a macro cache) */
892 - 49,50 suppressed: function cannot be solved git_attr_assignment__parse (automatic due to inconsistent arc counts in .gcda files) if (repo != NULL && assign->value == git_attr__true) {
893 - 51 suppressed: function cannot be solved git_attr_assignment__parse (automatic due to inconsistent arc counts in .gcda files) git_attr_rule *macro =
894 - 51 suppressed: function cannot be solved git_attr_assignment__parse (automatic due to inconsistent arc counts in .gcda files) git_attr_cache__lookup_macro(repo, assign->name);
895 -
896 - 52 suppressed: function cannot be solved git_attr_assignment__parse (automatic due to inconsistent arc counts in .gcda files) if (macro != NULL) {
897 - unsigned int i;
898 - git_attr_assignment *massign;
899 -
900 - 53,60-62 suppressed: function cannot be solved git_attr_assignment__parse (automatic due to inconsistent arc counts in .gcda files) git_vector_foreach(&macro->assigns, i, massign) {
901 - 54 suppressed: function cannot be solved git_attr_assignment__parse (automatic due to inconsistent arc counts in .gcda files) GIT_REFCOUNT_INC(massign);
902 -
903 - 55 suppressed: function cannot be solved git_attr_assignment__parse (automatic due to inconsistent arc counts in .gcda files) error = git_vector_insert_sorted(
904 - assigns, massign, &merge_assignments);
905 - 56,57 suppressed: function cannot be solved git_attr_assignment__parse (automatic due to inconsistent arc counts in .gcda files) if (error < 0 && error != GIT_EEXISTS) {
906 - 58 suppressed: function cannot be solved git_attr_assignment__parse (automatic due to inconsistent arc counts in .gcda files) git_attr_assignment__free(assign);
907 - 59 suppressed: function cannot be solved git_attr_assignment__parse (automatic due to inconsistent arc counts in .gcda files) return error;
908 - }
909 - }
910 - }
911 - }
912 -
913 - /* insert allocated assign into vector */
914 - 63 suppressed: function cannot be solved git_attr_assignment__parse (automatic due to inconsistent arc counts in .gcda files) error = git_vector_insert_sorted(assigns, assign, &merge_assignments);
915 - 64,65 suppressed: function cannot be solved git_attr_assignment__parse (automatic due to inconsistent arc counts in .gcda files) if (error < 0 && error != GIT_EEXISTS)
916 - 66 suppressed: function cannot be solved git_attr_assignment__parse (automatic due to inconsistent arc counts in .gcda files) return error;
917 -
918 - /* clear assign since it is now "owned" by the vector */
919 - 67 suppressed: function cannot be solved git_attr_assignment__parse (automatic due to inconsistent arc counts in .gcda files) assign = NULL;
920 - }
921 -
922 - 70 suppressed: function cannot be solved git_attr_assignment__parse (automatic due to inconsistent arc counts in .gcda files) if (assign != NULL)
923 - 71 suppressed: function cannot be solved git_attr_assignment__parse (automatic due to inconsistent arc counts in .gcda files) git_attr_assignment__free(assign);
924 -
925 - 72 suppressed: function cannot be solved git_attr_assignment__parse (automatic due to inconsistent arc counts in .gcda files) *base = git__next_line(scan);
926 -
927 - 73 suppressed: function cannot be solved git_attr_assignment__parse (automatic due to inconsistent arc counts in .gcda files) return (assigns->length == 0) ? GIT_ENOTFOUND : 0;
928 - }
929 -
930 174897 2 static void git_attr_rule__clear(git_attr_rule *rule)
931 - {
932 - unsigned int i;
933 - git_attr_assignment *assign;
934 -
935 174897 2 if (!rule)
936 174896 3,15 return;
937 -
938 6183 4 if (!(rule->match.flags & GIT_ATTR_FNMATCH_IGNORE)) {
939 10301 5,10-12 git_vector_foreach(&rule->assigns, i, assign)
940 7615 6-9 GIT_REFCOUNT_DEC(assign, git_attr_assignment__free);
941 2686 13 git_vector_free(&rule->assigns);
942 - }
943 -
944 - /* match.pattern is stored in a git_pool, so no need to free */
945 6182 14 rule->match.pattern = NULL;
946 6182 14 rule->match.length = 0;
947 - }
948 -
949 174779 2 void git_attr_rule__free(git_attr_rule *rule)
950 - {
951 174779 2 git_attr_rule__clear(rule);
952 174849 3 git__free(rule);
953 174721 4 }
954 -
955 8423 2 int git_attr_session__init(git_attr_session *session, git_repository *repo)
956 - {
957 8423 2,3 assert(repo);
958 -
959 8423 4 memset(session, 0, sizeof(*session));
960 8423 4 session->key = git_atomic_inc(&repo->attr_session_key);
961 -
962 8423 5 return 0;
963 - }
964 -
965 8425 2 void git_attr_session__free(git_attr_session *session)
966 - {
967 8425 2 if (!session)
968 8425 3,7 return;
969 -
970 8425 4 git_buf_dispose(&session->sysdir);
971 8425 5 git_buf_dispose(&session->tmp);
972 -
973 8425 6 memset(session, 0, sizeof(git_attr_session));
974 - }