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 "config.h"
9 -
10 - #include "git2/config.h"
11 - #include "git2/sys/config.h"
12 -
13 - #include "buf_text.h"
14 - #include "config_backend.h"
15 - #include "regexp.h"
16 - #include "sysdir.h"
17 - #include "transaction.h"
18 - #include "vector.h"
19 - #if GIT_WIN32
20 - # include <windows.h>
21 - #endif
22 -
23 - #include <ctype.h>
24 -
25 98370 2 void git_config_entry_free(git_config_entry *entry)
26 - {
27 98370 2 if (!entry)
28 98370 3,5 return;
29 -
30 22433 4 entry->free(entry);
31 - }
32 -
33 - typedef struct {
34 - git_refcount rc;
35 -
36 - git_config_backend *backend;
37 - git_config_level_t level;
38 - } backend_internal;
39 -
40 63255 2 static void backend_internal_free(backend_internal *internal)
41 - {
42 - git_config_backend *backend;
43 -
44 63255 2 backend = internal->backend;
45 63255 2 backend->free(backend);
46 63254 3 git__free(internal);
47 63254 4 }
48 -
49 24942 2 static void config_free(git_config *cfg)
50 - {
51 - size_t i;
52 - backend_internal *internal;
53 -
54 90626 2,8,9 for (i = 0; i < cfg->backends.length; ++i) {
55 65684 3 internal = git_vector_get(&cfg->backends, i);
56 65686 4-7 GIT_REFCOUNT_DEC(internal, backend_internal_free);
57 - }
58 -
59 24942 10 git_vector_free(&cfg->backends);
60 -
61 24943 11 git__memzero(cfg, sizeof(*cfg));
62 24943 12 git__free(cfg);
63 24943 13 }
64 -
65 31130 2 void git_config_free(git_config *cfg)
66 - {
67 31130 2 if (cfg == NULL)
68 31130 3,8 return;
69 -
70 28070 4-7 GIT_REFCOUNT_DEC(cfg, config_free);
71 - }
72 -
73 48556 2 static int config_backend_cmp(const void *a, const void *b)
74 - {
75 48556 2 const backend_internal *bk_a = (const backend_internal *)(a);
76 48556 2 const backend_internal *bk_b = (const backend_internal *)(b);
77 -
78 48556 2 return bk_b->level - bk_a->level;
79 - }
80 -
81 24939 2 int git_config_new(git_config **out)
82 - {
83 - git_config *cfg;
84 -
85 24939 2 cfg = git__malloc(sizeof(git_config));
86 24940 3,4 GIT_ERROR_CHECK_ALLOC(cfg);
87 -
88 24940 5 memset(cfg, 0x0, sizeof(git_config));
89 -
90 24943 5,6 if (git_vector_init(&cfg->backends, 3, config_backend_cmp) < 0) {
91 ##### 7 git__free(cfg);
92 ##### 8 return -1;
93 - }
94 -
95 24943 9 *out = cfg;
96 24943 9 GIT_REFCOUNT_INC(cfg);
97 24941 10 return 0;
98 - }
99 -
100 15276 2 int git_config_add_file_ondisk(
101 - git_config *cfg,
102 - const char *path,
103 - git_config_level_t level,
104 - const git_repository *repo,
105 - int force)
106 - {
107 15276 2 git_config_backend *file = NULL;
108 - struct stat st;
109 - int res;
110 -
111 15276 2-4 assert(cfg && path);
112 -
113 15276 5 res = p_stat(path, &st);
114 15273 6-10 if (res < 0 && errno != ENOENT && errno != ENOTDIR) {
115 ##### 11 git_error_set(GIT_ERROR_CONFIG, "failed to stat '%s'", path);
116 ##### 12 return -1;
117 - }
118 -
119 15274 13,14 if (git_config_backend_from_file(&file, path) < 0)
120 ##### 15 return -1;
121 -
122 15275 16,17 if ((res = git_config_add_backend(cfg, file, level, repo, force)) < 0) {
123 - /*
124 - * free manually; the file is not owned by the config
125 - * instance yet and will not be freed on cleanup
126 - */
127 18 18 file->free(file);
128 18 19 return res;
129 - }
130 -
131 15257 20 return 0;
132 - }
133 -
134 1572 2 int git_config_open_ondisk(git_config **out, const char *path)
135 - {
136 - int error;
137 - git_config *config;
138 -
139 1572 2 *out = NULL;
140 -
141 1572 2,3 if (git_config_new(&config) < 0)
142 ##### 4 return -1;
143 -
144 1572 5,6 if ((error = git_config_add_file_ondisk(config, path, GIT_CONFIG_LEVEL_LOCAL, NULL, 0)) < 0)
145 17 7 git_config_free(config);
146 - else
147 1555 8 *out = config;
148 -
149 1572 9 return error;
150 - }
151 -
152 16823 2 int git_config_snapshot(git_config **out, git_config *in)
153 - {
154 16823 2 int error = 0;
155 - size_t i;
156 - backend_internal *internal;
157 - git_config *config;
158 -
159 16823 2 *out = NULL;
160 -
161 16823 2,3 if (git_config_new(&config) < 0)
162 ##### 4 return -1;
163 -
164 64808 5,12,15,16 git_vector_foreach(&in->backends, i, internal) {
165 - git_config_backend *b;
166 -
167 47985 6,7 if ((error = internal->backend->snapshot(&b, internal->backend)) < 0)
168 ##### 8,14 break;
169 -
170 47989 9,10 if ((error = git_config_add_backend(config, b, internal->level, NULL, 0)) < 0) {
171 ##### 11 b->free(b);
172 ##### 13 break;
173 - }
174 - }
175 -
176 16823 17 if (error < 0)
177 ##### 18 git_config_free(config);
178 - else
179 16823 19 *out = config;
180 -
181 16823 20 return error;
182 - }
183 -
184 2439 2 static int find_backend_by_level(
185 - backend_internal **out,
186 - const git_config *cfg,
187 - git_config_level_t level)
188 - {
189 2439 2 int pos = -1;
190 - backend_internal *internal;
191 - size_t i;
192 -
193 - /* when passing GIT_CONFIG_HIGHEST_LEVEL, the idea is to get the config backend
194 - * which has the highest level. As config backends are stored in a vector
195 - * sorted by decreasing order of level, getting the backend at position 0
196 - * will do the job.
197 - */
198 2439 2 if (level == GIT_CONFIG_HIGHEST_LEVEL) {
199 ##### 3 pos = 0;
200 - } else {
201 10557 4,7-9 git_vector_foreach(&cfg->backends, i, internal) {
202 8118 5 if (internal->level == level)
203 2434 6 pos = (int)i;
204 - }
205 - }
206 -
207 2439 10 if (pos == -1) {
208 5 11 git_error_set(GIT_ERROR_CONFIG,
209 - "no configuration exists for the given level '%i'", (int)level);
210 5 12 return GIT_ENOTFOUND;
211 - }
212 -
213 2434 13 *out = git_vector_get(&cfg->backends, pos);
214 -
215 2434 14 return 0;
216 - }
217 -
218 1 2 static int duplicate_level(void **old_raw, void *new_raw)
219 - {
220 1 2 backend_internal **old = (backend_internal **)old_raw;
221 -
222 - GIT_UNUSED(new_raw);
223 -
224 1 2 git_error_set(GIT_ERROR_CONFIG, "there already exists a configuration for the given level (%i)", (int)(*old)->level);
225 1 3 return GIT_EEXISTS;
226 - }
227 -
228 2442 2 static void try_remove_existing_backend(
229 - git_config *cfg,
230 - git_config_level_t level)
231 - {
232 2442 2 int pos = -1;
233 - backend_internal *internal;
234 - size_t i;
235 -
236 2461 2,5-7 git_vector_foreach(&cfg->backends, i, internal) {
237 19 3 if (internal->level == level)
238 4 4 pos = (int)i;
239 - }
240 -
241 2442 8 if (pos == -1)
242 2438 9 return;
243 -
244 4 10 internal = git_vector_get(&cfg->backends, pos);
245 -
246 4 11,12 if (git_vector_remove(&cfg->backends, pos) < 0)
247 ##### 13 return;
248 -
249 4 14 GIT_REFCOUNT_DEC(internal, backend_internal_free);
250 - }
251 -
252 65683 2 static int git_config__add_internal(
253 - git_config *cfg,
254 - backend_internal *internal,
255 - git_config_level_t level,
256 - int force)
257 - {
258 - int result;
259 -
260 - /* delete existing config backend for level if it exists */
261 65683 2 if (force)
262 2442 3 try_remove_existing_backend(cfg, level);
263 -
264 65683 4,5 if ((result = git_vector_insert_sorted(&cfg->backends,
265 - internal, &duplicate_level)) < 0)
266 1 6 return result;
267 -
268 65671 7 git_vector_sort(&cfg->backends);
269 65670 8 internal->backend->cfg = cfg;
270 -
271 65670 8 GIT_REFCOUNT_INC(internal);
272 -
273 65687 9 return 0;
274 - }
275 -
276 2 2 int git_config_open_global(git_config **cfg_out, git_config *cfg)
277 - {
278 2 2,3 if (!git_config_open_level(cfg_out, cfg, GIT_CONFIG_LEVEL_XDG))
279 1 4 return 0;
280 -
281 1 5 return git_config_open_level(cfg_out, cfg, GIT_CONFIG_LEVEL_GLOBAL);
282 - }
283 -
284 2439 2 int git_config_open_level(
285 - git_config **cfg_out,
286 - const git_config *cfg_parent,
287 - git_config_level_t level)
288 - {
289 - git_config *cfg;
290 - backend_internal *internal;
291 - int res;
292 -
293 2439 2,3 if ((res = find_backend_by_level(&internal, cfg_parent, level)) < 0)
294 5 4 return res;
295 -
296 2434 5,6 if ((res = git_config_new(&cfg)) < 0)
297 ##### 7 return res;
298 -
299 2434 8,9 if ((res = git_config__add_internal(cfg, internal, level, true)) < 0) {
300 ##### 10 git_config_free(cfg);
301 ##### 11 return res;
302 - }
303 -
304 2434 12 *cfg_out = cfg;
305 -
306 2434 12 return 0;
307 - }
308 -
309 63262 2 int git_config_add_backend(
310 - git_config *cfg,
311 - git_config_backend *backend,
312 - git_config_level_t level,
313 - const git_repository *repo,
314 - int force)
315 - {
316 - backend_internal *internal;
317 - int result;
318 -
319 63262 2-4 assert(cfg && backend);
320 -
321 63261 5-7 GIT_ERROR_CHECK_VERSION(backend, GIT_CONFIG_BACKEND_VERSION, "git_config_backend");
322 -
323 63259 8,9 if ((result = backend->open(backend, level, repo)) < 0)
324 17 10 return result;
325 -
326 63241 11 internal = git__malloc(sizeof(backend_internal));
327 63251 12,13 GIT_ERROR_CHECK_ALLOC(internal);
328 -
329 63251 14 memset(internal, 0x0, sizeof(backend_internal));
330 -
331 63251 14 internal->backend = backend;
332 63251 14 internal->level = level;
333 -
334 63253 14,15 if ((result = git_config__add_internal(cfg, internal, level, force)) < 0) {
335 1 16 git__free(internal);
336 1 17 return result;
337 - }
338 -
339 63252 18 return 0;
340 - }
341 -
342 - /*
343 - * Loop over all the variables
344 - */
345 -
346 - typedef struct {
347 - git_config_iterator parent;
348 - git_config_iterator *current;
349 - const git_config *cfg;
350 - git_regexp regex;
351 - size_t i;
352 - } all_iter;
353 -
354 6671 2 static int find_next_backend(size_t *out, const git_config *cfg, size_t i)
355 - {
356 - backend_internal *internal;
357 -
358 6671 2,6,8 for (; i > 0; --i) {
359 4338 3 internal = git_vector_get(&cfg->backends, i - 1);
360 4338 4,5 if (!internal || !internal->backend)
361 ##### 6 continue;
362 -
363 4338 7 *out = i;
364 4338 7 return 0;
365 - }
366 -
367 2333 9 return -1;
368 - }
369 -
370 19910 2 static int all_iter_next(git_config_entry **entry, git_config_iterator *_iter)
371 - {
372 19910 2 all_iter *iter = (all_iter *) _iter;
373 - backend_internal *internal;
374 - git_config_backend *backend;
375 - size_t i;
376 19910 2 int error = 0;
377 -
378 19910 2-4 if (iter->current != NULL &&
379 17561 3 (error = iter->current->next(entry, iter->current)) == 0) {
380 15092 5 return 0;
381 - }
382 -
383 4818 6,7 if (error < 0 && error != GIT_ITEROVER)
384 ##### 8 return error;
385 -
386 - do {
387 6671 9,10 if (find_next_backend(&i, iter->cfg, iter->i) < 0)
388 2333 11 return GIT_ITEROVER;
389 -
390 4338 12 internal = git_vector_get(&iter->cfg->backends, i - 1);
391 4338 13 backend = internal->backend;
392 4338 13 iter->i = i - 1;
393 -
394 4338 13 if (iter->current)
395 1989 14 iter->current->free(iter->current);
396 -
397 4338 15 iter->current = NULL;
398 4338 15 error = backend->iterator(&iter->current, backend);
399 4338 16 if (error == GIT_ENOTFOUND)
400 ##### 17 continue;
401 -
402 4338 18 if (error < 0)
403 ##### 19 return error;
404 -
405 4338 20 error = iter->current->next(entry, iter->current);
406 - /* If this backend is empty, then keep going */
407 4338 21 if (error == GIT_ITEROVER)
408 1853 22 continue;
409 -
410 2485 23 return error;
411 -
412 1853 24 } while(1);
413 -
414 - return GIT_ITEROVER;
415 - }
416 -
417 2928 2 static int all_iter_glob_next(git_config_entry **entry, git_config_iterator *_iter)
418 - {
419 - int error;
420 2928 2 all_iter *iter = (all_iter *) _iter;
421 -
422 - /*
423 - * We use the "normal" function to grab the next one across
424 - * backends and then apply the regex
425 - */
426 10759 2,7,8 while ((error = all_iter_next(entry, _iter)) == 0) {
427 - /* skip non-matching keys if regexp was provided */
428 9320 3,4 if (git_regexp_match(&iter->regex, (*entry)->name) != 0)
429 7831 5 continue;
430 -
431 - /* and simply return if we like the entry's name */
432 1489 6 return 0;
433 - }
434 -
435 1439 9 return error;
436 - }
437 -
438 2359 2 static void all_iter_free(git_config_iterator *_iter)
439 - {
440 2359 2 all_iter *iter = (all_iter *) _iter;
441 -
442 2359 2 if (iter->current)
443 2349 3 iter->current->free(iter->current);
444 -
445 2359 4 git__free(iter);
446 2359 5 }
447 -
448 1454 2 static void all_iter_glob_free(git_config_iterator *_iter)
449 - {
450 1454 2 all_iter *iter = (all_iter *) _iter;
451 -
452 1454 2 git_regexp_dispose(&iter->regex);
453 1454 3 all_iter_free(_iter);
454 1454 4 }
455 -
456 905 2 int git_config_iterator_new(git_config_iterator **out, const git_config *cfg)
457 - {
458 - all_iter *iter;
459 -
460 905 2 iter = git__calloc(1, sizeof(all_iter));
461 905 3,4 GIT_ERROR_CHECK_ALLOC(iter);
462 -
463 905 5 iter->parent.free = all_iter_free;
464 905 5 iter->parent.next = all_iter_next;
465 -
466 905 5 iter->i = cfg->backends.length;
467 905 5 iter->cfg = cfg;
468 -
469 905 5 *out = (git_config_iterator *) iter;
470 -
471 905 5 return 0;
472 - }
473 -
474 1961 2 int git_config_iterator_glob_new(git_config_iterator **out, const git_config *cfg, const char *regexp)
475 - {
476 - all_iter *iter;
477 - int result;
478 -
479 1961 2 if (regexp == NULL)
480 506 3 return git_config_iterator_new(out, cfg);
481 -
482 1455 4 iter = git__calloc(1, sizeof(all_iter));
483 1455 5,6 GIT_ERROR_CHECK_ALLOC(iter);
484 -
485 1455 7,8 if ((result = git_regexp_compile(&iter->regex, regexp, 0)) < 0) {
486 1 9 git__free(iter);
487 1 10 return -1;
488 - }
489 -
490 1454 11 iter->parent.next = all_iter_glob_next;
491 1454 11 iter->parent.free = all_iter_glob_free;
492 1454 11 iter->i = cfg->backends.length;
493 1454 11 iter->cfg = cfg;
494 -
495 1454 11 *out = (git_config_iterator *) iter;
496 -
497 1454 11 return 0;
498 - }
499 -
500 506 2 int git_config_foreach(
501 - const git_config *cfg, git_config_foreach_cb cb, void *payload)
502 - {
503 506 2 return git_config_foreach_match(cfg, NULL, cb, payload);
504 - }
505 -
506 73 2 int git_config_backend_foreach_match(
507 - git_config_backend *backend,
508 - const char *regexp,
509 - git_config_foreach_cb cb,
510 - void *payload)
511 - {
512 - git_config_entry *entry;
513 - git_config_iterator* iter;
514 - git_regexp regex;
515 73 2 int error = 0;
516 -
517 73 2-4 assert(backend && cb);
518 -
519 73 5-7 if (regexp && git_regexp_compile(&regex, regexp, 0) < 0)
520 ##### 8 return -1;
521 -
522 73 9,10 if ((error = backend->iterator(&iter, backend)) < 0) {
523 ##### 11 iter = NULL;
524 ##### 11 return -1;
525 - }
526 -
527 1179 12,21,22 while (!(iter->next(&entry, iter) < 0)) {
528 - /* skip non-matching keys if regexp was provided */
529 1106 13-15 if (regexp && git_regexp_match(&regex, entry->name) != 0)
530 553 16 continue;
531 -
532 - /* abort iterator on non-zero return value */
533 553 17,18 if ((error = cb(entry, payload)) != 0) {
534 ##### 19 git_error_set_after_callback(error);
535 ##### 20 break;
536 - }
537 - }
538 -
539 73 23 if (regexp != NULL)
540 72 24 git_regexp_dispose(&regex);
541 -
542 73 25 iter->free(iter);
543 -
544 73 26 return error;
545 - }
546 -
547 611 2 int git_config_foreach_match(
548 - const git_config *cfg,
549 - const char *regexp,
550 - git_config_foreach_cb cb,
551 - void *payload)
552 - {
553 - int error;
554 - git_config_iterator *iter;
555 - git_config_entry *entry;
556 -
557 611 2,3 if ((error = git_config_iterator_glob_new(&iter, cfg, regexp)) < 0)
558 ##### 4 return error;
559 -
560 2034 5,10,11 while (!(error = git_config_next(&entry, iter))) {
561 1425 6,7 if ((error = cb(entry, payload)) != 0) {
562 2 8 git_error_set_after_callback(error);
563 2 9 break;
564 - }
565 - }
566 -
567 611 12 git_config_iterator_free(iter);
568 -
569 611 13 if (error == GIT_ITEROVER)
570 609 14 error = 0;
571 -
572 611 15 return error;
573 - }
574 -
575 - /**************
576 - * Setters
577 - **************/
578 -
579 - typedef enum {
580 - BACKEND_USE_SET,
581 - BACKEND_USE_DELETE
582 - } backend_use;
583 -
584 - static const char *uses[] = {
585 - "set",
586 - "delete"
587 - };
588 -
589 10794 2 static int get_backend_for_use(git_config_backend **out,
590 - git_config *cfg, const char *name, backend_use use)
591 - {
592 - size_t i;
593 - backend_internal *backend;
594 -
595 10794 2 *out = NULL;
596 -
597 10794 2,3 if (git_vector_length(&cfg->backends) == 0) {
598 ##### 4 git_error_set(GIT_ERROR_CONFIG,
599 - "cannot %s value for '%s' when no config backends exist",
600 - uses[use], name);
601 ##### 5 return GIT_ENOTFOUND;
602 - }
603 -
604 10796 6,9-11 git_vector_foreach(&cfg->backends, i, backend) {
605 10795 7 if (!backend->backend->readonly) {
606 10793 8 *out = backend->backend;
607 10793 8 return 0;
608 - }
609 - }
610 -
611 1 12 git_error_set(GIT_ERROR_CONFIG,
612 - "cannot %s value for '%s' when all config backends are readonly",
613 - uses[use], name);
614 1 13 return GIT_ENOTFOUND;
615 - }
616 -
617 5689 2 int git_config_delete_entry(git_config *cfg, const char *name)
618 - {
619 - git_config_backend *backend;
620 -
621 5689 2,3 if (get_backend_for_use(&backend, cfg, name, BACKEND_USE_DELETE) < 0)
622 ##### 4 return GIT_ENOTFOUND;
623 -
624 5689 5 return backend->del(backend, name);
625 - }
626 -
627 418 2 int git_config_set_int64(git_config *cfg, const char *name, int64_t value)
628 - {
629 - char str_value[32]; /* All numbers should fit in here */
630 418 2 p_snprintf(str_value, sizeof(str_value), "%" PRId64, value);
631 418 2 return git_config_set_string(cfg, name, str_value);
632 - }
633 -
634 415 2 int git_config_set_int32(git_config *cfg, const char *name, int32_t value)
635 - {
636 415 2 return git_config_set_int64(cfg, name, (int64_t)value);
637 - }
638 -
639 3650 2 int git_config_set_bool(git_config *cfg, const char *name, int value)
640 - {
641 3650 2 return git_config_set_string(cfg, name, value ? "true" : "false");
642 - }
643 -
644 4920 2 int git_config_set_string(git_config *cfg, const char *name, const char *value)
645 - {
646 - int error;
647 - git_config_backend *backend;
648 -
649 4920 2 if (!value) {
650 1 3 git_error_set(GIT_ERROR_CONFIG, "the value to set cannot be NULL");
651 1 4 return -1;
652 - }
653 -
654 4919 5,6 if (get_backend_for_use(&backend, cfg, name, BACKEND_USE_SET) < 0)
655 1 7 return GIT_ENOTFOUND;
656 -
657 4918 8 error = backend->set(backend, name, value);
658 -
659 4918 9,10 if (!error && GIT_REFCOUNT_OWNER(cfg) != NULL)
660 961 11 git_repository__configmap_lookup_cache_clear(GIT_REFCOUNT_OWNER(cfg));
661 -
662 4918 12 return error;
663 - }
664 -
665 86 2 int git_config__update_entry(
666 - git_config *config,
667 - const char *key,
668 - const char *value,
669 - bool overwrite_existing,
670 - bool only_if_existing)
671 - {
672 86 2 int error = 0;
673 86 2 git_config_entry *ce = NULL;
674 -
675 86 2,3 if ((error = git_config__lookup_entry(&ce, config, key, false)) < 0)
676 ##### 4 return error;
677 -
678 86 5,6 if (!ce && only_if_existing) /* entry doesn't exist */
679 4 7 return 0;
680 82 8,9 if (ce && !overwrite_existing) /* entry would be overwritten */
681 ##### 10 return 0;
682 82 11-14 if (value && ce && ce->value && !strcmp(ce->value, value)) /* no change */
683 ##### 15 return 0;
684 82 16-18 if (!value && (!ce || !ce->value)) /* asked to delete absent entry */
685 33 19 return 0;
686 -
687 49 20 if (!value)
688 ##### 21 error = git_config_delete_entry(config, key);
689 - else
690 49 22 error = git_config_set_string(config, key, value);
691 -
692 49 23 git_config_entry_free(ce);
693 49 24 return error;
694 - }
695 -
696 - /***********
697 - * Getters
698 - ***********/
699 -
700 9645 2 static int config_error_notfound(const char *name)
701 - {
702 9645 2 git_error_set(GIT_ERROR_CONFIG, "config value '%s' was not found", name);
703 9645 3 return GIT_ENOTFOUND;
704 - }
705 -
706 - enum {
707 - GET_ALL_ERRORS = 0,
708 - GET_NO_MISSING = 1,
709 - GET_NO_ERRORS = 2
710 - };
711 -
712 - 2 suppressed: function cannot be solved get_entry (automatic due to inconsistent arc counts in .gcda files)static int get_entry(
713 - git_config_entry **out,
714 - const git_config *cfg,
715 - const char *name,
716 - bool normalize_name,
717 - int want_errors)
718 - {
719 - 2 suppressed: function cannot be solved get_entry (automatic due to inconsistent arc counts in .gcda files) int res = GIT_ENOTFOUND;
720 - 2 suppressed: function cannot be solved get_entry (automatic due to inconsistent arc counts in .gcda files) const char *key = name;
721 - 2 suppressed: function cannot be solved get_entry (automatic due to inconsistent arc counts in .gcda files) char *normalized = NULL;
722 - size_t i;
723 - backend_internal *internal;
724 -
725 - 2 suppressed: function cannot be solved get_entry (automatic due to inconsistent arc counts in .gcda files) *out = NULL;
726 -
727 - 2 suppressed: function cannot be solved get_entry (automatic due to inconsistent arc counts in .gcda files) if (normalize_name) {
728 - 3,4 suppressed: function cannot be solved get_entry (automatic due to inconsistent arc counts in .gcda files) if ((res = git_config__normalize_name(name, &normalized)) < 0)
729 - 5 suppressed: function cannot be solved get_entry (automatic due to inconsistent arc counts in .gcda files) goto cleanup;
730 - 6 suppressed: function cannot be solved get_entry (automatic due to inconsistent arc counts in .gcda files) key = normalized;
731 - }
732 -
733 - 7 suppressed: function cannot be solved get_entry (automatic due to inconsistent arc counts in .gcda files) res = GIT_ENOTFOUND;
734 - 7,14-16 suppressed: function cannot be solved get_entry (automatic due to inconsistent arc counts in .gcda files) git_vector_foreach(&cfg->backends, i, internal) {
735 - 8,9 suppressed: function cannot be solved get_entry (automatic due to inconsistent arc counts in .gcda files) if (!internal || !internal->backend)
736 - 10 suppressed: function cannot be solved get_entry (automatic due to inconsistent arc counts in .gcda files) continue;
737 -
738 - 11 suppressed: function cannot be solved get_entry (automatic due to inconsistent arc counts in .gcda files) res = internal->backend->get(internal->backend, key, out);
739 - 12 suppressed: function cannot be solved get_entry (automatic due to inconsistent arc counts in .gcda files) if (res != GIT_ENOTFOUND)
740 - 13 suppressed: function cannot be solved get_entry (automatic due to inconsistent arc counts in .gcda files) break;
741 - }
742 -
743 - 17 suppressed: function cannot be solved get_entry (automatic due to inconsistent arc counts in .gcda files) git__free(normalized);
744 -
745 - cleanup:
746 - 18 suppressed: function cannot be solved get_entry (automatic due to inconsistent arc counts in .gcda files) if (res == GIT_ENOTFOUND)
747 - 19-22 suppressed: function cannot be solved get_entry (automatic due to inconsistent arc counts in .gcda files) res = (want_errors > GET_ALL_ERRORS) ? 0 : config_error_notfound(name);
748 - 23,24 suppressed: function cannot be solved get_entry (automatic due to inconsistent arc counts in .gcda files) else if (res && (want_errors == GET_NO_ERRORS)) {
749 - 25 suppressed: function cannot be solved get_entry (automatic due to inconsistent arc counts in .gcda files) git_error_clear();
750 - 26 suppressed: function cannot be solved get_entry (automatic due to inconsistent arc counts in .gcda files) res = 0;
751 - }
752 -
753 - 27 suppressed: function cannot be solved get_entry (automatic due to inconsistent arc counts in .gcda files) return res;
754 - }
755 -
756 1200 2 int git_config_get_entry(
757 - git_config_entry **out, const git_config *cfg, const char *name)
758 - {
759 1200 2 return get_entry(out, cfg, name, true, GET_ALL_ERRORS);
760 - }
761 -
762 63308 2 int git_config__lookup_entry(
763 - git_config_entry **out,
764 - const git_config *cfg,
765 - const char *key,
766 - bool no_errors)
767 - {
768 63308 2 return get_entry(
769 - out, cfg, key, false, no_errors ? GET_NO_ERRORS : GET_NO_MISSING);
770 - }
771 -
772 ##### 2 int git_config_get_mapped(
773 - int *out,
774 - const git_config *cfg,
775 - const char *name,
776 - const git_configmap *maps,
777 - size_t map_n)
778 - {
779 - git_config_entry *entry;
780 - int ret;
781 -
782 ##### 2,3 if ((ret = get_entry(&entry, cfg, name, true, GET_ALL_ERRORS)) < 0)
783 ##### 4 return ret;
784 -
785 ##### 5 ret = git_config_lookup_map_value(out, maps, map_n, entry->value);
786 ##### 6 git_config_entry_free(entry);
787 -
788 ##### 7 return ret;
789 - }
790 -
791 234 2 int git_config_get_int64(int64_t *out, const git_config *cfg, const char *name)
792 - {
793 - git_config_entry *entry;
794 - int ret;
795 -
796 234 2,3 if ((ret = get_entry(&entry, cfg, name, true, GET_ALL_ERRORS)) < 0)
797 224 4 return ret;
798 -
799 10 5 ret = git_config_parse_int64(out, entry->value);
800 10 6 git_config_entry_free(entry);
801 -
802 10 7 return ret;
803 - }
804 -
805 4143 2 int git_config_get_int32(int32_t *out, const git_config *cfg, const char *name)
806 - {
807 - git_config_entry *entry;
808 - int ret;
809 -
810 4143 2,3 if ((ret = get_entry(&entry, cfg, name, true, GET_ALL_ERRORS)) < 0)
811 130 4 return ret;
812 -
813 4013 5 ret = git_config_parse_int32(out, entry->value);
814 4013 6 git_config_entry_free(entry);
815 -
816 4013 7 return ret;
817 - }
818 -
819 4685 2 int git_config_get_bool(int *out, const git_config *cfg, const char *name)
820 - {
821 - git_config_entry *entry;
822 - int ret;
823 -
824 4685 2,3 if ((ret = get_entry(&entry, cfg, name, true, GET_ALL_ERRORS)) < 0)
825 796 4 return ret;
826 -
827 3889 5 ret = git_config_parse_bool(out, entry->value);
828 3889 6 git_config_entry_free(entry);
829 -
830 3889 7 return ret;
831 - }
832 -
833 9357 2 static int is_readonly(const git_config *cfg)
834 - {
835 - size_t i;
836 - backend_internal *internal;
837 -
838 24763 2,8-10 git_vector_foreach(&cfg->backends, i, internal) {
839 15406 3,4 if (!internal || !internal->backend)
840 ##### 5 continue;
841 -
842 15406 6 if (!internal->backend->readonly)
843 ##### 7 return 0;
844 - }
845 -
846 9357 11 return 1;
847 - }
848 -
849 14 2 int git_config_get_path(git_buf *out, const git_config *cfg, const char *name)
850 - {
851 - git_config_entry *entry;
852 - int error;
853 -
854 14 2,3 if ((error = get_entry(&entry, cfg, name, true, GET_ALL_ERRORS)) < 0)
855 5 4 return error;
856 -
857 9 5 error = git_config_parse_path(out, entry->value);
858 9 6 git_config_entry_free(entry);
859 -
860 9 7 return error;
861 - }
862 -
863 9357 2 int git_config_get_string(
864 - const char **out, const git_config *cfg, const char *name)
865 - {
866 - git_config_entry *entry;
867 - int ret;
868 -
869 9357 2,3 if (!is_readonly(cfg)) {
870 ##### 4 git_error_set(GIT_ERROR_CONFIG, "get_string called on a live config object");
871 ##### 5 return -1;
872 - }
873 -
874 9357 6 ret = get_entry(&entry, cfg, name, true, GET_ALL_ERRORS);
875 9357 7-12 *out = !ret ? (entry->value ? entry->value : "") : NULL;
876 -
877 9357 13 git_config_entry_free(entry);
878 -
879 9357 14 return ret;
880 - }
881 -
882 314 2 int git_config_get_string_buf(
883 - git_buf *out, const git_config *cfg, const char *name)
884 - {
885 - git_config_entry *entry;
886 - int ret;
887 - const char *str;
888 -
889 314 2 git_buf_sanitize(out);
890 -
891 314 3 ret = get_entry(&entry, cfg, name, true, GET_ALL_ERRORS);
892 314 4-9 str = !ret ? (entry->value ? entry->value : "") : NULL;
893 -
894 314 10 if (str)
895 202 11 ret = git_buf_puts(out, str);
896 -
897 314 12 git_config_entry_free(entry);
898 -
899 314 13 return ret;
900 - }
901 -
902 27 2 char *git_config__get_string_force(
903 - const git_config *cfg, const char *key, const char *fallback_value)
904 - {
905 - git_config_entry *entry;
906 - char *ret;
907 -
908 27 2 get_entry(&entry, cfg, key, false, GET_NO_ERRORS);
909 27 3-9 ret = (entry && entry->value) ? git__strdup(entry->value) : fallback_value ? git__strdup(fallback_value) : NULL;
910 27 10 git_config_entry_free(entry);
911 -
912 27 11 return ret;
913 - }
914 -
915 15161 2 int git_config__get_bool_force(
916 - const git_config *cfg, const char *key, int fallback_value)
917 - {
918 15161 2 int val = fallback_value;
919 - git_config_entry *entry;
920 -
921 15161 2 get_entry(&entry, cfg, key, false, GET_NO_ERRORS);
922 -
923 15163 3-5 if (entry && git_config_parse_bool(&val, entry->value) < 0)
924 ##### 6 git_error_clear();
925 -
926 15163 7 git_config_entry_free(entry);
927 15163 8 return val;
928 - }
929 -
930 1137 2 int git_config__get_int_force(
931 - const git_config *cfg, const char *key, int fallback_value)
932 - {
933 1137 2 int32_t val = (int32_t)fallback_value;
934 - git_config_entry *entry;
935 -
936 1137 2 get_entry(&entry, cfg, key, false, GET_NO_ERRORS);
937 -
938 1137 3-5 if (entry && git_config_parse_int32(&val, entry->value) < 0)
939 ##### 6 git_error_clear();
940 -
941 1137 7 git_config_entry_free(entry);
942 1137 8 return (int)val;
943 - }
944 -
945 396 2 int git_config_get_multivar_foreach(
946 - const git_config *cfg, const char *name, const char *regexp,
947 - git_config_foreach_cb cb, void *payload)
948 - {
949 - int err, found;
950 - git_config_iterator *iter;
951 - git_config_entry *entry;
952 -
953 396 2,3 if ((err = git_config_multivar_iterator_new(&iter, cfg, name, regexp)) < 0)
954 9 4 return err;
955 -
956 387 5 found = 0;
957 610 5,10,11 while ((err = iter->next(&entry, iter)) == 0) {
958 223 6 found = 1;
959 -
960 223 6,7 if ((err = cb(entry, payload)) != 0) {
961 ##### 8 git_error_set_after_callback(err);
962 ##### 9 break;
963 - }
964 - }
965 -
966 387 12 iter->free(iter);
967 387 13 if (err == GIT_ITEROVER)
968 387 14 err = 0;
969 -
970 387 15,16 if (found == 0 && err == 0)
971 198 17 err = config_error_notfound(name);
972 -
973 387 18 return err;
974 - }
975 -
976 - typedef struct {
977 - git_config_iterator parent;
978 - git_config_iterator *iter;
979 - char *name;
980 - git_regexp regex;
981 - int have_regex;
982 - } multivar_iter;
983 -
984 613 2 static int multivar_iter_next(git_config_entry **entry, git_config_iterator *_iter)
985 - {
986 613 2 multivar_iter *iter = (multivar_iter *) _iter;
987 613 2 int error = 0;
988 -
989 7507 2,10,11 while ((error = iter->iter->next(entry, iter->iter)) == 0) {
990 7119 3 if (git__strcmp(iter->name, (*entry)->name))
991 6885 4 continue;
992 -
993 234 5 if (!iter->have_regex)
994 210 6 return 0;
995 -
996 24 7,8 if (git_regexp_match(&iter->regex, (*entry)->value) == 0)
997 15 9 return 0;
998 - }
999 -
1000 388 12 return error;
1001 - }
1002 -
1003 388 2 static void multivar_iter_free(git_config_iterator *_iter)
1004 - {
1005 388 2 multivar_iter *iter = (multivar_iter *) _iter;
1006 -
1007 388 2 iter->iter->free(iter->iter);
1008 -
1009 388 3 git__free(iter->name);
1010 388 4 if (iter->have_regex)
1011 11 5 git_regexp_dispose(&iter->regex);
1012 388 6 git__free(iter);
1013 388 7 }
1014 -
1015 397 2 int git_config_multivar_iterator_new(git_config_iterator **out, const git_config *cfg, const char *name, const char *regexp)
1016 - {
1017 397 2 multivar_iter *iter = NULL;
1018 397 2 git_config_iterator *inner = NULL;
1019 - int error;
1020 -
1021 397 2,3 if ((error = git_config_iterator_new(&inner, cfg)) < 0)
1022 ##### 4 return error;
1023 -
1024 397 5 iter = git__calloc(1, sizeof(multivar_iter));
1025 397 6,7 GIT_ERROR_CHECK_ALLOC(iter);
1026 -
1027 397 8,9 if ((error = git_config__normalize_name(name, &iter->name)) < 0)
1028 9 10 goto on_error;
1029 -
1030 388 11 if (regexp != NULL) {
1031 11 12,13 if ((error = git_regexp_compile(&iter->regex, regexp, 0)) < 0)
1032 ##### 14 goto on_error;
1033 -
1034 11 15 iter->have_regex = 1;
1035 - }
1036 -
1037 388 16 iter->iter = inner;
1038 388 16 iter->parent.free = multivar_iter_free;
1039 388 16 iter->parent.next = multivar_iter_next;
1040 -
1041 388 16 *out = (git_config_iterator *) iter;
1042 -
1043 388 16 return 0;
1044 -
1045 - on_error:
1046 -
1047 9 17 inner->free(inner);
1048 9 18 git__free(iter);
1049 9 19 return error;
1050 - }
1051 -
1052 181 2 int git_config_set_multivar(git_config *cfg, const char *name, const char *regexp, const char *value)
1053 - {
1054 - git_config_backend *backend;
1055 -
1056 181 2,3 if (get_backend_for_use(&backend, cfg, name, BACKEND_USE_DELETE) < 0)
1057 ##### 4 return GIT_ENOTFOUND;
1058 -
1059 181 5 return backend->set_multivar(backend, name, regexp, value);
1060 - }
1061 -
1062 5 2 int git_config_delete_multivar(git_config *cfg, const char *name, const char *regexp)
1063 - {
1064 - git_config_backend *backend;
1065 -
1066 5 2,3 if (get_backend_for_use(&backend, cfg, name, BACKEND_USE_DELETE) < 0)
1067 ##### 4 return GIT_ENOTFOUND;
1068 -
1069 5 5 return backend->del_multivar(backend, name, regexp);
1070 - }
1071 -
1072 201837 2 int git_config_next(git_config_entry **entry, git_config_iterator *iter)
1073 - {
1074 201837 2 return iter->next(entry, iter);
1075 - }
1076 -
1077 49943 2 void git_config_iterator_free(git_config_iterator *iter)
1078 - {
1079 49943 2 if (iter == NULL)
1080 49950 3,5 return;
1081 -
1082 49943 4 iter->free(iter);
1083 - }
1084 -
1085 4092 2 int git_config_find_global(git_buf *path)
1086 - {
1087 4092 2 git_buf_sanitize(path);
1088 4092 3 return git_sysdir_find_global_file(path, GIT_CONFIG_FILENAME_GLOBAL);
1089 - }
1090 -
1091 4091 2 int git_config_find_xdg(git_buf *path)
1092 - {
1093 4091 2 git_buf_sanitize(path);
1094 4091 3 return git_sysdir_find_xdg_file(path, GIT_CONFIG_FILENAME_XDG);
1095 - }
1096 -
1097 4091 2 int git_config_find_system(git_buf *path)
1098 - {
1099 4091 2 git_buf_sanitize(path);
1100 4091 3 return git_sysdir_find_system_file(path, GIT_CONFIG_FILENAME_SYSTEM);
1101 - }
1102 -
1103 4090 2 int git_config_find_programdata(git_buf *path)
1104 - {
1105 - int ret;
1106 -
1107 4090 2 git_buf_sanitize(path);
1108 4090 3 ret = git_sysdir_find_programdata_file(path,
1109 - GIT_CONFIG_FILENAME_PROGRAMDATA);
1110 4091 4 if (ret != GIT_OK)
1111 725 5 return ret;
1112 -
1113 3366 6 return git_path_validate_system_file_ownership(path->ptr);
1114 - }
1115 -
1116 4076 2 int git_config__global_location(git_buf *buf)
1117 - {
1118 - const git_buf *paths;
1119 - const char *sep, *start;
1120 -
1121 4076 2,3 if (git_sysdir_get(&paths, GIT_SYSDIR_GLOBAL) < 0)
1122 ##### 4 return -1;
1123 -
1124 - /* no paths, so give up */
1125 4076 5-7 if (!paths || !git_buf_len(paths))
1126 1233 8 return -1;
1127 -
1128 - /* find unescaped separator or end of string */
1129 99461 9,10,14,15 for (sep = start = git_buf_cstr(paths); *sep; ++sep) {
1130 96620 11,12 if (*sep == GIT_PATH_LIST_SEPARATOR &&
1131 1 13 (sep <= start || sep[-1] != '\\'))
1132 - break;
1133 - }
1134 -
1135 2842 16,17 if (git_buf_set(buf, start, (size_t)(sep - start)) < 0)
1136 ##### 18 return -1;
1137 -
1138 2842 19 return git_buf_joinpath(buf, buf->ptr, GIT_CONFIG_FILENAME_GLOBAL);
1139 - }
1140 -
1141 11 2 int git_config_open_default(git_config **out)
1142 - {
1143 - int error;
1144 11 2 git_config *cfg = NULL;
1145 11 2 git_buf buf = GIT_BUF_INIT;
1146 -
1147 11 2,3 if ((error = git_config_new(&cfg)) < 0)
1148 ##### 4 return error;
1149 -
1150 11 5-8 if (!git_config_find_global(&buf) || !git_config__global_location(&buf)) {
1151 11 9 error = git_config_add_file_ondisk(cfg, buf.ptr,
1152 - GIT_CONFIG_LEVEL_GLOBAL, NULL, 0);
1153 - }
1154 -
1155 11 10-12 if (!error && !git_config_find_xdg(&buf))
1156 6 13 error = git_config_add_file_ondisk(cfg, buf.ptr,
1157 - GIT_CONFIG_LEVEL_XDG, NULL, 0);
1158 -
1159 11 14-16 if (!error && !git_config_find_system(&buf))
1160 ##### 17 error = git_config_add_file_ondisk(cfg, buf.ptr,
1161 - GIT_CONFIG_LEVEL_SYSTEM, NULL, 0);
1162 -
1163 11 18-20 if (!error && !git_config_find_programdata(&buf))
1164 6 21 error = git_config_add_file_ondisk(cfg, buf.ptr,
1165 - GIT_CONFIG_LEVEL_PROGRAMDATA, NULL, 0);
1166 -
1167 11 22 git_buf_dispose(&buf);
1168 -
1169 11 23 if (error) {
1170 ##### 24 git_config_free(cfg);
1171 ##### 25 cfg = NULL;
1172 - }
1173 -
1174 11 26 *out = cfg;
1175 -
1176 11 26 return error;
1177 - }
1178 -
1179 2 2 int git_config_lock(git_transaction **out, git_config *cfg)
1180 - {
1181 - int error;
1182 - git_config_backend *backend;
1183 - backend_internal *internal;
1184 -
1185 2 2,3 assert(cfg);
1186 -
1187 2 4 internal = git_vector_get(&cfg->backends, 0);
1188 2 5,6 if (!internal || !internal->backend) {
1189 ##### 7 git_error_set(GIT_ERROR_CONFIG, "cannot lock; the config has no backends");
1190 ##### 8 return -1;
1191 - }
1192 2 9 backend = internal->backend;
1193 -
1194 2 9,10 if ((error = backend->lock(backend)) < 0)
1195 ##### 11 return error;
1196 -
1197 2 12 return git_transaction_config_new(out, cfg);
1198 - }
1199 -
1200 2 2 int git_config_unlock(git_config *cfg, int commit)
1201 - {
1202 - git_config_backend *backend;
1203 - backend_internal *internal;
1204 -
1205 2 2,3 assert(cfg);
1206 -
1207 2 4 internal = git_vector_get(&cfg->backends, 0);
1208 2 5,6 if (!internal || !internal->backend) {
1209 ##### 7 git_error_set(GIT_ERROR_CONFIG, "cannot lock; the config has no backends");
1210 ##### 8 return -1;
1211 - }
1212 -
1213 2 9 backend = internal->backend;
1214 -
1215 2 9 return backend->unlock(backend, commit);
1216 - }
1217 -
1218 - /***********
1219 - * Parsers
1220 - ***********/
1221 -
1222 904 2 int git_config_lookup_map_value(
1223 - int *out,
1224 - const git_configmap *maps,
1225 - size_t map_n,
1226 - const char *value)
1227 - {
1228 - size_t i;
1229 -
1230 904 2 if (!value)
1231 ##### 3 goto fail_parse;
1232 -
1233 1731 4,18,19 for (i = 0; i < map_n; ++i) {
1234 1731 5 const git_configmap *m = maps + i;
1235 -
1236 1731 5 switch (m->type) {
1237 - case GIT_CONFIGMAP_FALSE:
1238 - case GIT_CONFIGMAP_TRUE: {
1239 - int bool_val;
1240 -
1241 1559 6-8 if (git__parse_bool(&bool_val, value) == 0 &&
1242 1389 8 bool_val == (int)m->type) {
1243 776 9 *out = m->map_value;
1244 776 9 return 0;
1245 - }
1246 783 10 break;
1247 - }
1248 -
1249 - case GIT_CONFIGMAP_INT32:
1250 7 11,12 if (git_config_parse_int32(out, value) == 0)
1251 7 13 return 0;
1252 ##### 14 break;
1253 -
1254 - case GIT_CONFIGMAP_STRING:
1255 165 15 if (strcasecmp(value, m->str_match) == 0) {
1256 121 16 *out = m->map_value;
1257 121 16 return 0;
1258 - }
1259 44 17 break;
1260 - }
1261 - }
1262 -
1263 - fail_parse:
1264 ##### 20 git_error_set(GIT_ERROR_CONFIG, "failed to map '%s'", value);
1265 ##### 21 return -1;
1266 - }
1267 -
1268 17 2 int git_config_lookup_map_enum(git_configmap_t *type_out, const char **str_out,
1269 - const git_configmap *maps, size_t map_n, int enum_val)
1270 - {
1271 - size_t i;
1272 -
1273 39 2,4,6 for (i = 0; i < map_n; i++) {
1274 39 3 const git_configmap *m = &maps[i];
1275 -
1276 39 3 if (m->map_value != enum_val)
1277 22 4 continue;
1278 -
1279 17 5 *type_out = m->type;
1280 17 5 *str_out = m->str_match;
1281 17 5 return 0;
1282 - }
1283 -
1284 ##### 7 git_error_set(GIT_ERROR_CONFIG, "invalid enum value");
1285 ##### 8 return GIT_ENOTFOUND;
1286 - }
1287 -
1288 14346 2 int git_config_parse_bool(int *out, const char *value)
1289 - {
1290 14346 2,3 if (git__parse_bool(out, value) == 0)
1291 14342 4 return 0;
1292 -
1293 3 5,6 if (git_config_parse_int32(out, value) == 0) {
1294 1 7 *out = !!(*out);
1295 1 7 return 0;
1296 - }
1297 -
1298 2 8 git_error_set(GIT_ERROR_CONFIG, "failed to parse '%s' as a boolean value", value);
1299 2 9 return -1;
1300 - }
1301 -
1302 4035 2 int git_config_parse_int64(int64_t *out, const char *value)
1303 - {
1304 - const char *num_end;
1305 - int64_t num;
1306 -
1307 4035 2-4 if (!value || git__strntol64(&num, value, strlen(value), &num_end, 0) < 0)
1308 - goto fail_parse;
1309 -
1310 4032 5 switch (*num_end) {
1311 - case 'g':
1312 - case 'G':
1313 2 6 num *= 1024;
1314 - /* fallthrough */
1315 -
1316 - case 'm':
1317 - case 'M':
1318 4 7 num *= 1024;
1319 - /* fallthrough */
1320 -
1321 - case 'k':
1322 - case 'K':
1323 6 8 num *= 1024;
1324 -
1325 - /* check that that there are no more characters after the
1326 - * given modifier suffix */
1327 6 8 if (num_end[1] != '\0')
1328 ##### 9 return -1;
1329 -
1330 - /* fallthrough */
1331 -
1332 - case '\0':
1333 4032 10 *out = num;
1334 4032 10 return 0;
1335 -
1336 - default:
1337 ##### 11 goto fail_parse;
1338 - }
1339 -
1340 - fail_parse:
1341 3 12-15 git_error_set(GIT_ERROR_CONFIG, "failed to parse '%s' as an integer", value ? value : "(null)");
1342 3 16 return -1;
1343 - }
1344 -
1345 4025 2 int git_config_parse_int32(int32_t *out, const char *value)
1346 - {
1347 - int64_t tmp;
1348 - int32_t truncate;
1349 -
1350 4025 2,3 if (git_config_parse_int64(&tmp, value) < 0)
1351 3 4 goto fail_parse;
1352 -
1353 4022 5 truncate = tmp & 0xFFFFFFFF;
1354 4022 5 if (truncate != tmp)
1355 1 6 goto fail_parse;
1356 -
1357 4021 7 *out = truncate;
1358 4021 7 return 0;
1359 -
1360 - fail_parse:
1361 4 8-11 git_error_set(GIT_ERROR_CONFIG, "failed to parse '%s' as a 32-bit integer", value ? value : "(null)");
1362 4 12 return -1;
1363 - }
1364 -
1365 9 2 int git_config_parse_path(git_buf *out, const char *value)
1366 - {
1367 9 2-4 assert(out && value);
1368 -
1369 9 5 git_buf_sanitize(out);
1370 -
1371 9 6 if (value[0] == '~') {
1372 4 7,8 if (value[1] != '\0' && value[1] != '/') {
1373 1 9 git_error_set(GIT_ERROR_CONFIG, "retrieving a homedir by name is not supported");
1374 1 10 return -1;
1375 - }
1376 -
1377 3 11-14 return git_sysdir_expand_global_file(out, value[1] ? &value[2] : NULL);
1378 - }
1379 -
1380 5 15 return git_buf_sets(out, value);
1381 - }
1382 -
1383 - 2 suppressed: function cannot be solved normalize_section (automatic due to inconsistent arc counts in .gcda files)static int normalize_section(char *start, char *end)
1384 - {
1385 - char *scan;
1386 -
1387 - 2 suppressed: function cannot be solved normalize_section (automatic due to inconsistent arc counts in .gcda files) if (start == end)
1388 - 3 suppressed: function cannot be solved normalize_section (automatic due to inconsistent arc counts in .gcda files) return GIT_EINVALIDSPEC;
1389 -
1390 - /* Validate and downcase range */
1391 - 4,14,15 suppressed: function cannot be solved normalize_section (automatic due to inconsistent arc counts in .gcda files) for (scan = start; *scan; ++scan) {
1392 - 5,6 suppressed: function cannot be solved normalize_section (automatic due to inconsistent arc counts in .gcda files) if (end && scan >= end)
1393 - 7 suppressed: function cannot be solved normalize_section (automatic due to inconsistent arc counts in .gcda files) break;
1394 - 8,9 suppressed: function cannot be solved normalize_section (automatic due to inconsistent arc counts in .gcda files) if (isalnum(*scan))
1395 - 10 suppressed: function cannot be solved normalize_section (automatic due to inconsistent arc counts in .gcda files) *scan = (char)git__tolower(*scan);
1396 - 11,12 suppressed: function cannot be solved normalize_section (automatic due to inconsistent arc counts in .gcda files) else if (*scan != '-' || scan == start)
1397 - 13 suppressed: function cannot be solved normalize_section (automatic due to inconsistent arc counts in .gcda files) return GIT_EINVALIDSPEC;
1398 - }
1399 -
1400 - 16 suppressed: function cannot be solved normalize_section (automatic due to inconsistent arc counts in .gcda files) if (scan == start)
1401 - 17 suppressed: function cannot be solved normalize_section (automatic due to inconsistent arc counts in .gcda files) return GIT_EINVALIDSPEC;
1402 -
1403 - 18 suppressed: function cannot be solved normalize_section (automatic due to inconsistent arc counts in .gcda files) return 0;
1404 - }
1405 -
1406 -
1407 - /* Take something the user gave us and make it nice for our hash function */
1408 31188 2 int git_config__normalize_name(const char *in, char **out)
1409 - {
1410 - char *name, *fdot, *ldot;
1411 -
1412 31188 2-4 assert(in && out);
1413 -
1414 31188 5 name = git__strdup(in);
1415 31187 6,7 GIT_ERROR_CHECK_ALLOC(name);
1416 -
1417 31187 8 fdot = strchr(name, '.');
1418 31187 8 ldot = strrchr(name, '.');
1419 -
1420 31187 8-11 if (fdot == NULL || fdot == name || ldot == NULL || !ldot[1])
1421 - goto invalid;
1422 -
1423 - /* Validate and downcase up to first dot and after last dot */
1424 31167 12,13,15 if (normalize_section(name, fdot) < 0 ||
1425 31157 14 normalize_section(ldot + 1, NULL) < 0)
1426 - goto invalid;
1427 -
1428 - /* If there is a middle range, make sure it doesn't have newlines */
1429 152721 16,19 while (fdot < ldot)
1430 121580 17 if (*fdot++ == '\n')
1431 5 18 goto invalid;
1432 -
1433 31141 20 *out = name;
1434 31141 20 return 0;
1435 -
1436 - invalid:
1437 45 21 git__free(name);
1438 46 22 git_error_set(GIT_ERROR_CONFIG, "invalid config item name '%s'", in);
1439 46 23 return GIT_EINVALIDSPEC;
1440 - }
1441 -
1442 - struct rename_data {
1443 - git_config *config;
1444 - git_buf *name;
1445 - size_t old_len;
1446 - };
1447 -
1448 45 2 static int rename_config_entries_cb(
1449 - const git_config_entry *entry,
1450 - void *payload)
1451 - {
1452 45 2 int error = 0;
1453 45 2 struct rename_data *data = (struct rename_data *)payload;
1454 45 2 size_t base_len = git_buf_len(data->name);
1455 -
1456 45 3-5 if (base_len > 0 &&
1457 31 4 !(error = git_buf_puts(data->name, entry->name + data->old_len)))
1458 - {
1459 31 6,6,7 error = git_config_set_string(
1460 31 6 data->config, git_buf_cstr(data->name), entry->value);
1461 -
1462 31 8 git_buf_truncate(data->name, base_len);
1463 - }
1464 -
1465 45 9 if (!error)
1466 45 10 error = git_config_delete_entry(data->config, entry->name);
1467 -
1468 45 11 return error;
1469 - }
1470 -
1471 53 2 int git_config_rename_section(
1472 - git_repository *repo,
1473 - const char *old_section_name,
1474 - const char *new_section_name)
1475 - {
1476 - git_config *config;
1477 53 2 git_buf pattern = GIT_BUF_INIT, replace = GIT_BUF_INIT;
1478 53 2 int error = 0;
1479 - struct rename_data data;
1480 -
1481 53 2 git_buf_text_puts_escape_regex(&pattern, old_section_name);
1482 -
1483 53 3,4 if ((error = git_buf_puts(&pattern, "\\..+")) < 0)
1484 ##### 5 goto cleanup;
1485 -
1486 53 6,7 if ((error = git_repository_config__weakptr(&config, repo)) < 0)
1487 ##### 8 goto cleanup;
1488 -
1489 53 9 data.config = config;
1490 53 9 data.name = &replace;
1491 53 9 data.old_len = strlen(old_section_name) + 1;
1492 -
1493 53 9,10 if ((error = git_buf_join(&replace, '.', new_section_name, "")) < 0)
1494 ##### 11 goto cleanup;
1495 -
1496 53 12-14 if (new_section_name != NULL &&
1497 28 13 (error = normalize_section(replace.ptr, strchr(replace.ptr, '.'))) < 0)
1498 - {
1499 5 15 git_error_set(
1500 - GIT_ERROR_CONFIG, "invalid config section '%s'", new_section_name);
1501 5 16 goto cleanup;
1502 - }
1503 -
1504 48 17,18 error = git_config_foreach_match(
1505 - config, git_buf_cstr(&pattern), rename_config_entries_cb, &data);
1506 -
1507 - cleanup:
1508 53 19 git_buf_dispose(&pattern);
1509 53 20 git_buf_dispose(&replace);
1510 -
1511 53 21 return error;
1512 - }
1513 -
1514 1 2 int git_config_init_backend(git_config_backend *backend, unsigned int version)
1515 - {
1516 1 2-4 GIT_INIT_STRUCTURE_FROM_TEMPLATE(
1517 - backend, version, git_config_backend, GIT_CONFIG_BACKEND_INIT);
1518 1 5 return 0;
1519 - }