]> git.proxmox.com Git - libgit2.git/blob - tests/config/read.c
a2e668c207b48c526cbb4190f3e0afd1d538521e
[libgit2.git] / tests / config / read.c
1 #include "clar_libgit2.h"
2 #include "fs_path.h"
3
4 static git_buf buf = GIT_BUF_INIT;
5
6 void test_config_read__cleanup(void)
7 {
8 git_buf_dispose(&buf);
9 }
10
11 void test_config_read__simple_read(void)
12 {
13 git_config *cfg;
14 int32_t i;
15
16 cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config0")));
17
18 cl_git_pass(git_config_get_int32(&i, cfg, "core.repositoryformatversion"));
19 cl_assert(i == 0);
20 cl_git_pass(git_config_get_bool(&i, cfg, "core.filemode"));
21 cl_assert(i == 1);
22 cl_git_pass(git_config_get_bool(&i, cfg, "core.bare"));
23 cl_assert(i == 0);
24 cl_git_pass(git_config_get_bool(&i, cfg, "core.logallrefupdates"));
25 cl_assert(i == 1);
26
27 git_config_free(cfg);
28 }
29
30 void test_config_read__case_sensitive(void)
31 {
32 git_config *cfg;
33 int i;
34
35 cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config1")));
36
37 cl_git_pass(git_config_get_string_buf(&buf, cfg, "this.that.other"));
38 cl_assert_equal_s("true", buf.ptr);
39 git_buf_dispose(&buf);
40
41 cl_git_pass(git_config_get_string_buf(&buf, cfg, "this.That.other"));
42 cl_assert_equal_s("yes", buf.ptr);
43
44 cl_git_pass(git_config_get_bool(&i, cfg, "this.that.other"));
45 cl_assert(i == 1);
46 cl_git_pass(git_config_get_bool(&i, cfg, "this.That.other"));
47 cl_assert(i == 1);
48
49 /* This one doesn't exist */
50 cl_must_fail(git_config_get_bool(&i, cfg, "this.thaT.other"));
51
52 git_config_free(cfg);
53 }
54
55 /*
56 * If \ is the last non-space character on the line, we read the next
57 * one, separating each line with SP.
58 */
59 void test_config_read__multiline_value(void)
60 {
61 git_config *cfg;
62
63 cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config2")));
64
65 cl_git_pass(git_config_get_string_buf(&buf, cfg, "this.That.and"));
66 cl_assert_equal_s("one one one two two three three", buf.ptr);
67
68 git_config_free(cfg);
69 }
70
71 static void clean_test_config(void *unused)
72 {
73 GIT_UNUSED(unused);
74 cl_fixture_cleanup("./testconfig");
75 }
76
77 void test_config_read__multiline_value_and_eof(void)
78 {
79 git_config *cfg;
80
81 cl_set_cleanup(&clean_test_config, NULL);
82 cl_git_mkfile("./testconfig", "[header]\n key1 = foo\\\n");
83 cl_git_pass(git_config_open_ondisk(&cfg, "./testconfig"));
84
85 cl_git_pass(git_config_get_string_buf(&buf, cfg, "header.key1"));
86 cl_assert_equal_s("foo", buf.ptr);
87
88 git_config_free(cfg);
89 }
90
91 void test_config_read__multiline_eof(void)
92 {
93 git_config *cfg;
94
95 cl_set_cleanup(&clean_test_config, NULL);
96 cl_git_mkfile("./testconfig", "[header]\n key1 = \\\n");
97 cl_git_pass(git_config_open_ondisk(&cfg, "./testconfig"));
98
99 cl_git_pass(git_config_get_string_buf(&buf, cfg, "header.key1"));
100 cl_assert_equal_s("", buf.ptr);
101
102 git_config_free(cfg);
103 }
104
105 /*
106 * This kind of subsection declaration is case-insensitive
107 */
108 void test_config_read__subsection_header(void)
109 {
110 git_config *cfg;
111
112 cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config3")));
113
114 cl_git_pass(git_config_get_string_buf(&buf, cfg, "section.subsection.var"));
115 cl_assert_equal_s("hello", buf.ptr);
116
117 /* The subsection is transformed to lower-case */
118 cl_must_fail(git_config_get_string_buf(&buf, cfg, "section.subSectIon.var"));
119
120 git_config_free(cfg);
121 }
122
123 void test_config_read__lone_variable(void)
124 {
125 git_config *cfg;
126 int i;
127
128 cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config4")));
129
130 cl_git_fail(git_config_get_int32(&i, cfg, "some.section.variable"));
131
132 cl_git_pass(git_config_get_string_buf(&buf, cfg, "some.section.variable"));
133 cl_assert_equal_s("", buf.ptr);
134 git_buf_dispose(&buf);
135
136 cl_git_pass(git_config_get_bool(&i, cfg, "some.section.variable"));
137 cl_assert(i == 1);
138
139 cl_git_pass(git_config_get_string_buf(&buf, cfg, "some.section.variableeq"));
140 cl_assert_equal_s("", buf.ptr);
141
142 cl_git_pass(git_config_get_bool(&i, cfg, "some.section.variableeq"));
143 cl_assert(i == 0);
144
145 git_config_free(cfg);
146 }
147
148 void test_config_read__number_suffixes(void)
149 {
150 git_config *cfg;
151 int64_t i;
152
153 cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config5")));
154
155 cl_git_pass(git_config_get_int64(&i, cfg, "number.simple"));
156 cl_assert(i == 1);
157
158 cl_git_pass(git_config_get_int64(&i, cfg, "number.k"));
159 cl_assert(i == 1 * 1024);
160
161 cl_git_pass(git_config_get_int64(&i, cfg, "number.kk"));
162 cl_assert(i == 1 * 1024);
163
164 cl_git_pass(git_config_get_int64(&i, cfg, "number.m"));
165 cl_assert(i == 1 * 1024 * 1024);
166
167 cl_git_pass(git_config_get_int64(&i, cfg, "number.mm"));
168 cl_assert(i == 1 * 1024 * 1024);
169
170 cl_git_pass(git_config_get_int64(&i, cfg, "number.g"));
171 cl_assert(i == 1 * 1024 * 1024 * 1024);
172
173 cl_git_pass(git_config_get_int64(&i, cfg, "number.gg"));
174 cl_assert(i == 1 * 1024 * 1024 * 1024);
175
176 git_config_free(cfg);
177 }
178
179 void test_config_read__blank_lines(void)
180 {
181 git_config *cfg;
182 int i;
183
184 cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config6")));
185
186 cl_git_pass(git_config_get_bool(&i, cfg, "valid.subsection.something"));
187 cl_assert(i == 1);
188
189 cl_git_pass(git_config_get_bool(&i, cfg, "something.else.something"));
190 cl_assert(i == 0);
191
192 git_config_free(cfg);
193 }
194
195 void test_config_read__invalid_ext_headers(void)
196 {
197 git_config *cfg;
198 cl_must_fail(git_config_open_ondisk(&cfg, cl_fixture("config/config7")));
199 }
200
201 void test_config_read__empty_files(void)
202 {
203 git_config *cfg;
204 cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config8")));
205 git_config_free(cfg);
206 }
207
208 void test_config_read__symbol_headers(void)
209 {
210 git_config *cfg;
211 cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config20")));
212 cl_git_pass(git_config_get_string_buf(&buf, cfg, "valid.[subsection].something"));
213 cl_assert_equal_s("a", buf.ptr);
214 git_buf_dispose(&buf);
215 cl_git_pass(git_config_get_string_buf(&buf, cfg, "sec.[subsec]/child.parent"));
216 cl_assert_equal_s("grand", buf.ptr);
217 git_buf_dispose(&buf);
218 cl_git_pass(git_config_get_string_buf(&buf, cfg, "sec2.[subsec2]/child2.type"));
219 cl_assert_equal_s("dvcs", buf.ptr);
220 git_buf_dispose(&buf);
221 cl_git_pass(git_config_get_string_buf(&buf, cfg, "sec3.escape\"quote.vcs"));
222 cl_assert_equal_s("git", buf.ptr);
223 git_buf_dispose(&buf);
224 cl_git_pass(git_config_get_string_buf(&buf, cfg, "sec4.escaping\\slash.lib"));
225 cl_assert_equal_s("git2", buf.ptr);
226 git_buf_dispose(&buf);
227 git_config_free(cfg);
228 }
229
230 void test_config_read__multiline_multiple_quoted_comment_chars(void)
231 {
232 git_config *cfg;
233 cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config21")));
234 git_config_free(cfg);
235 }
236
237 void test_config_read__multiline_multiple_quoted_quote_at_beginning_of_line(void)
238 {
239 git_config* cfg;
240 cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config22")));
241 cl_git_pass(git_config_get_string_buf(&buf, cfg, "alias.m"));
242 cl_assert_equal_s("cmd ;; ;; bar", buf.ptr);
243 git_buf_dispose(&buf);
244 cl_git_pass(git_config_get_string_buf(&buf, cfg, "alias.m2"));
245 cl_assert_equal_s("'; ; something '", buf.ptr);
246 git_buf_dispose(&buf);
247 git_config_free(cfg);
248 }
249
250 void test_config_read__header_in_last_line(void)
251 {
252 git_config *cfg;
253
254 cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config10")));
255 git_config_free(cfg);
256 }
257
258 void test_config_read__prefixes(void)
259 {
260 git_config *cfg;
261
262 cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config9")));
263 cl_git_pass(git_config_get_string_buf(&buf, cfg, "remote.ab.url"));
264 cl_assert_equal_s("http://example.com/git/ab", buf.ptr);
265 git_buf_dispose(&buf);
266
267 cl_git_pass(git_config_get_string_buf(&buf, cfg, "remote.abba.url"));
268 cl_assert_equal_s("http://example.com/git/abba", buf.ptr);
269
270 git_config_free(cfg);
271 }
272
273 void test_config_read__escaping_quotes(void)
274 {
275 git_config *cfg;
276
277 cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config13")));
278 cl_git_pass(git_config_get_string_buf(&buf, cfg, "core.editor"));
279 cl_assert_equal_s("\"C:/Program Files/Nonsense/bah.exe\" \"--some option\"", buf.ptr);
280
281 git_config_free(cfg);
282 }
283
284 void test_config_read__invalid_escape_sequence(void)
285 {
286 git_config *cfg;
287
288 cl_set_cleanup(&clean_test_config, NULL);
289 cl_git_mkfile("./testconfig", "[header]\n key1 = \\\\\\;\n key2 = value2\n");
290 cl_git_fail(git_config_open_ondisk(&cfg, "./testconfig"));
291
292 git_config_free(cfg);
293 }
294
295 static int count_cfg_entries_and_compare_levels(
296 const git_config_entry *entry, void *payload)
297 {
298 int *count = payload;
299
300 if (!strcmp(entry->value, "7") || !strcmp(entry->value, "17"))
301 cl_assert(entry->level == GIT_CONFIG_LEVEL_GLOBAL);
302 else
303 cl_assert(entry->level == GIT_CONFIG_LEVEL_SYSTEM);
304
305 (*count)++;
306 return 0;
307 }
308
309 static int cfg_callback_countdown(const git_config_entry *entry, void *payload)
310 {
311 int *count = payload;
312 GIT_UNUSED(entry);
313 (*count)--;
314 if (*count == 0)
315 return -100;
316 return 0;
317 }
318
319 void test_config_read__foreach(void)
320 {
321 git_config *cfg;
322 int count, ret;
323
324 cl_git_pass(git_config_new(&cfg));
325 cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config9"),
326 GIT_CONFIG_LEVEL_SYSTEM, NULL, 0));
327 cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config15"),
328 GIT_CONFIG_LEVEL_GLOBAL, NULL, 0));
329
330 count = 0;
331 cl_git_pass(git_config_foreach(cfg, count_cfg_entries_and_compare_levels, &count));
332 cl_assert_equal_i(7, count);
333
334 count = 3;
335 cl_git_fail(ret = git_config_foreach(cfg, cfg_callback_countdown, &count));
336 cl_assert_equal_i(-100, ret);
337
338 git_config_free(cfg);
339 }
340
341 void test_config_read__iterator(void)
342 {
343 const char *keys[] = {
344 "core.dummy2",
345 "core.verylong",
346 "core.dummy",
347 "remote.ab.url",
348 "remote.abba.url",
349 "core.dummy2",
350 "core.global"
351 };
352 git_config *cfg;
353 git_config_iterator *iter;
354 git_config_entry *entry;
355 int count, ret;
356
357 cl_git_pass(git_config_new(&cfg));
358 cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config9"),
359 GIT_CONFIG_LEVEL_SYSTEM, NULL, 0));
360 cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config15"),
361 GIT_CONFIG_LEVEL_GLOBAL, NULL, 0));
362
363 count = 0;
364 cl_git_pass(git_config_iterator_new(&iter, cfg));
365
366 while ((ret = git_config_next(&entry, iter)) == 0) {
367 cl_assert_equal_s(entry->name, keys[count]);
368 count++;
369 }
370
371 git_config_iterator_free(iter);
372 cl_assert_equal_i(GIT_ITEROVER, ret);
373 cl_assert_equal_i(7, count);
374
375 count = 3;
376 cl_git_pass(git_config_iterator_new(&iter, cfg));
377
378 git_config_iterator_free(iter);
379 git_config_free(cfg);
380 }
381
382 static int count_cfg_entries(const git_config_entry *entry, void *payload)
383 {
384 int *count = payload;
385 GIT_UNUSED(entry);
386 (*count)++;
387 return 0;
388 }
389
390 void test_config_read__foreach_match(void)
391 {
392 git_config *cfg;
393 int count;
394
395 cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config9")));
396
397 count = 0;
398 cl_git_pass(
399 git_config_foreach_match(cfg, "core.*", count_cfg_entries, &count));
400 cl_assert_equal_i(3, count);
401
402 count = 0;
403 cl_git_pass(
404 git_config_foreach_match(cfg, "remote\\.ab.*", count_cfg_entries, &count));
405 cl_assert_equal_i(2, count);
406
407 count = 0;
408 cl_git_pass(
409 git_config_foreach_match(cfg, ".*url$", count_cfg_entries, &count));
410 cl_assert_equal_i(2, count);
411
412 count = 0;
413 cl_git_pass(
414 git_config_foreach_match(cfg, ".*dummy.*", count_cfg_entries, &count));
415 cl_assert_equal_i(2, count);
416
417 count = 0;
418 cl_git_pass(
419 git_config_foreach_match(cfg, ".*nomatch.*", count_cfg_entries, &count));
420 cl_assert_equal_i(0, count);
421
422 git_config_free(cfg);
423 }
424
425 static void check_glob_iter(git_config *cfg, const char *regexp, int expected)
426 {
427 git_config_iterator *iter;
428 git_config_entry *entry;
429 int count, error;
430
431 cl_git_pass(git_config_iterator_glob_new(&iter, cfg, regexp));
432
433 count = 0;
434 while ((error = git_config_next(&entry, iter)) == 0)
435 count++;
436
437 cl_assert_equal_i(GIT_ITEROVER, error);
438 cl_assert_equal_i(expected, count);
439 git_config_iterator_free(iter);
440 }
441
442 void test_config_read__iterator_invalid_glob(void)
443 {
444 git_config *cfg;
445 git_config_iterator *iter;
446
447 cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config9")));
448
449 cl_git_fail(git_config_iterator_glob_new(&iter, cfg, "*"));
450
451 git_config_free(cfg);
452 }
453
454 void test_config_read__iterator_glob(void)
455 {
456 git_config *cfg;
457
458 cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config9")));
459
460 check_glob_iter(cfg, "core.*", 3);
461 check_glob_iter(cfg, "remote\\.ab.*", 2);
462 check_glob_iter(cfg, ".*url$", 2);
463 check_glob_iter(cfg, ".*dummy.*", 2);
464 check_glob_iter(cfg, ".*nomatch.*", 0);
465
466 git_config_free(cfg);
467 }
468
469 void test_config_read__whitespace_not_required_around_assignment(void)
470 {
471 git_config *cfg;
472
473 cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config14")));
474
475 cl_git_pass(git_config_get_string_buf(&buf, cfg, "a.b"));
476 cl_assert_equal_s("c", buf.ptr);
477 git_buf_dispose(&buf);
478
479 cl_git_pass(git_config_get_string_buf(&buf, cfg, "d.e"));
480 cl_assert_equal_s("f", buf.ptr);
481
482 git_config_free(cfg);
483 }
484
485 void test_config_read__read_git_config_entry(void)
486 {
487 git_config *cfg;
488 git_config_entry *entry;
489
490 cl_git_pass(git_config_new(&cfg));
491 cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config9"),
492 GIT_CONFIG_LEVEL_SYSTEM, NULL, 0));
493
494 cl_git_pass(git_config_get_entry(&entry, cfg, "core.dummy2"));
495 cl_assert_equal_s("core.dummy2", entry->name);
496 cl_assert_equal_s("42", entry->value);
497 cl_assert_equal_i(GIT_CONFIG_LEVEL_SYSTEM, entry->level);
498
499 git_config_entry_free(entry);
500 git_config_free(cfg);
501 }
502
503 /*
504 * At the beginning of the test:
505 * - config9 has: core.dummy2=42
506 * - config15 has: core.dummy2=7
507 * - config16 has: core.dummy2=28
508 */
509 void test_config_read__local_config_overrides_global_config_overrides_system_config(void)
510 {
511 git_config *cfg;
512 int32_t i;
513
514 cl_git_pass(git_config_new(&cfg));
515 cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config9"),
516 GIT_CONFIG_LEVEL_SYSTEM, NULL, 0));
517 cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config15"),
518 GIT_CONFIG_LEVEL_GLOBAL, NULL, 0));
519 cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config16"),
520 GIT_CONFIG_LEVEL_LOCAL, NULL, 0));
521
522 cl_git_pass(git_config_get_int32(&i, cfg, "core.dummy2"));
523 cl_assert_equal_i(28, i);
524
525 git_config_free(cfg);
526
527 cl_git_pass(git_config_new(&cfg));
528 cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config9"),
529 GIT_CONFIG_LEVEL_SYSTEM, NULL, 0));
530 cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config15"),
531 GIT_CONFIG_LEVEL_GLOBAL, NULL, 0));
532
533 cl_git_pass(git_config_get_int32(&i, cfg, "core.dummy2"));
534 cl_assert_equal_i(7, i);
535
536 git_config_free(cfg);
537 }
538
539 /*
540 * At the beginning of the test:
541 * - config9 has: core.global does not exist
542 * - config15 has: core.global=17
543 * - config16 has: core.global=29
544 *
545 * And also:
546 * - config9 has: core.system does not exist
547 * - config15 has: core.system does not exist
548 * - config16 has: core.system=11
549 */
550 void test_config_read__fallback_from_local_to_global_and_from_global_to_system(void)
551 {
552 git_config *cfg;
553 int32_t i;
554
555 cl_git_pass(git_config_new(&cfg));
556 cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config9"),
557 GIT_CONFIG_LEVEL_SYSTEM, NULL, 0));
558 cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config15"),
559 GIT_CONFIG_LEVEL_GLOBAL, NULL, 0));
560 cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config16"),
561 GIT_CONFIG_LEVEL_LOCAL, NULL, 0));
562
563 cl_git_pass(git_config_get_int32(&i, cfg, "core.global"));
564 cl_assert_equal_i(17, i);
565 cl_git_pass(git_config_get_int32(&i, cfg, "core.system"));
566 cl_assert_equal_i(11, i);
567
568 git_config_free(cfg);
569 }
570
571 void test_config_read__parent_dir_is_file(void)
572 {
573 git_config *cfg;
574 int count;
575
576 cl_git_pass(git_config_new(&cfg));
577 /*
578 * Verify we can add non-existing files when the parent directory is not
579 * a directory.
580 */
581 cl_git_pass(git_config_add_file_ondisk(cfg, "/dev/null/.gitconfig",
582 GIT_CONFIG_LEVEL_SYSTEM, NULL, 0));
583
584 count = 0;
585 cl_git_pass(git_config_foreach(cfg, count_cfg_entries_and_compare_levels, &count));
586 cl_assert_equal_i(0, count);
587
588 git_config_free(cfg);
589 }
590
591 /*
592 * At the beginning of the test, config18 has:
593 * int32global = 28
594 * int64global = 9223372036854775803
595 * boolglobal = true
596 * stringglobal = I'm a global config value!
597 *
598 * And config19 has:
599 * int32global = -1
600 * int64global = -2
601 * boolglobal = false
602 * stringglobal = don't find me!
603 *
604 */
605 void test_config_read__simple_read_from_specific_level(void)
606 {
607 git_config *cfg, *cfg_specific;
608 int i;
609 int64_t l, expected = +9223372036854775803;
610
611 cl_git_pass(git_config_new(&cfg));
612 cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config18"),
613 GIT_CONFIG_LEVEL_GLOBAL, NULL, 0));
614 cl_git_pass(git_config_add_file_ondisk(cfg, cl_fixture("config/config19"),
615 GIT_CONFIG_LEVEL_SYSTEM, NULL, 0));
616
617 cl_git_pass(git_config_open_level(&cfg_specific, cfg, GIT_CONFIG_LEVEL_GLOBAL));
618
619 cl_git_pass(git_config_get_int32(&i, cfg_specific, "core.int32global"));
620 cl_assert_equal_i(28, i);
621 cl_git_pass(git_config_get_int64(&l, cfg_specific, "core.int64global"));
622 cl_assert(l == expected);
623 cl_git_pass(git_config_get_bool(&i, cfg_specific, "core.boolglobal"));
624 cl_assert_equal_b(true, i);
625 cl_git_pass(git_config_get_string_buf(&buf, cfg_specific, "core.stringglobal"));
626 cl_assert_equal_s("I'm a global config value!", buf.ptr);
627
628 git_config_free(cfg_specific);
629 git_config_free(cfg);
630 }
631
632 void test_config_read__can_load_and_parse_an_empty_config_file(void)
633 {
634 git_config *cfg;
635 int i;
636
637 cl_set_cleanup(&clean_test_config, NULL);
638 cl_git_mkfile("./testconfig", "");
639 cl_git_pass(git_config_open_ondisk(&cfg, "./testconfig"));
640 cl_assert_equal_i(GIT_ENOTFOUND, git_config_get_int32(&i, cfg, "nope.neither"));
641
642 git_config_free(cfg);
643 }
644
645 void test_config_read__corrupt_header(void)
646 {
647 git_config *cfg;
648
649 cl_set_cleanup(&clean_test_config, NULL);
650 cl_git_mkfile("./testconfig", "[sneaky ] \"quoted closing quote mark\\\"");
651 cl_git_fail(git_config_open_ondisk(&cfg, "./testconfig"));
652
653 git_config_free(cfg);
654 }
655
656 void test_config_read__corrupt_header2(void)
657 {
658 git_config *cfg;
659
660 cl_set_cleanup(&clean_test_config, NULL);
661 cl_git_mkfile("./testconfig", "[unclosed \"bracket\"\n lib = git2\n");
662 cl_git_fail(git_config_open_ondisk(&cfg, "./testconfig"));
663
664 git_config_free(cfg);
665 }
666
667 void test_config_read__corrupt_header3(void)
668 {
669 git_config *cfg;
670
671 cl_set_cleanup(&clean_test_config, NULL);
672 cl_git_mkfile("./testconfig", "[unclosed \"slash\\\"]\n lib = git2\n");
673 cl_git_fail(git_config_open_ondisk(&cfg, "./testconfig"));
674
675 git_config_free(cfg);
676 }
677
678 void test_config_read__invalid_key_chars(void)
679 {
680 git_config *cfg;
681
682 cl_set_cleanup(&clean_test_config, NULL);
683 cl_git_mkfile("./testconfig", "[foo]\n has_underscore = git2\n");
684 cl_git_fail(git_config_open_ondisk(&cfg, "./testconfig"));
685
686 cl_git_rewritefile("./testconfig", "[foo]\n has/slash = git2\n");
687 cl_git_fail(git_config_open_ondisk(&cfg, "./testconfig"));
688
689 cl_git_rewritefile("./testconfig", "[foo]\n has+plus = git2\n");
690 cl_git_fail(git_config_open_ondisk(&cfg, "./testconfig"));
691
692 cl_git_rewritefile("./testconfig", "[no_key]\n = git2\n");
693 cl_git_fail(git_config_open_ondisk(&cfg, "./testconfig"));
694
695 git_config_free(cfg);
696 }
697
698 void test_config_read__lone_variable_with_trailing_whitespace(void)
699 {
700 git_config *cfg;
701 int b;
702
703 cl_set_cleanup(&clean_test_config, NULL);
704 cl_git_mkfile("./testconfig", "[foo]\n lonevariable \n");
705 cl_git_pass(git_config_open_ondisk(&cfg, "./testconfig"));
706
707 cl_git_pass(git_config_get_bool(&b, cfg, "foo.lonevariable"));
708 cl_assert_equal_b(true, b);
709
710 git_config_free(cfg);
711 }
712
713 void test_config_read__override_variable(void)
714 {
715 git_config *cfg;
716
717 cl_set_cleanup(&clean_test_config, NULL);
718 cl_git_mkfile("./testconfig", "[some] var = one\nvar = two");
719 cl_git_pass(git_config_open_ondisk(&cfg, "./testconfig"));
720
721 cl_git_pass(git_config_get_string_buf(&buf, cfg, "some.var"));
722 cl_assert_equal_s("two", buf.ptr);
723
724 git_config_free(cfg);
725 }
726
727 void test_config_read__path(void)
728 {
729 git_config *cfg;
730 git_buf path = GIT_BUF_INIT;
731 git_buf old_path = GIT_BUF_INIT;
732 git_str home_path = GIT_STR_INIT;
733 git_str expected_path = GIT_STR_INIT;
734
735 cl_git_pass(p_mkdir("fakehome", 0777));
736 cl_git_pass(git_fs_path_prettify(&home_path, "fakehome", NULL));
737 cl_git_pass(git_libgit2_opts(GIT_OPT_GET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, &old_path));
738 cl_git_pass(git_libgit2_opts(GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, home_path.ptr));
739 cl_git_mkfile("./testconfig", "[some]\n path = ~/somefile");
740 cl_git_pass(git_fs_path_join_unrooted(&expected_path, "somefile", home_path.ptr, NULL));
741
742 cl_git_pass(git_config_open_ondisk(&cfg, "./testconfig"));
743 cl_git_pass(git_config_get_path(&path, cfg, "some.path"));
744 cl_assert_equal_s(expected_path.ptr, path.ptr);
745 git_buf_dispose(&path);
746
747 cl_git_mkfile("./testconfig", "[some]\n path = ~/");
748 cl_git_pass(git_fs_path_join_unrooted(&expected_path, "", home_path.ptr, NULL));
749
750 cl_git_pass(git_config_get_path(&path, cfg, "some.path"));
751 cl_assert_equal_s(expected_path.ptr, path.ptr);
752 git_buf_dispose(&path);
753
754 cl_git_mkfile("./testconfig", "[some]\n path = ~");
755 cl_git_pass(git_str_sets(&expected_path, home_path.ptr));
756
757 cl_git_pass(git_config_get_path(&path, cfg, "some.path"));
758 cl_assert_equal_s(expected_path.ptr, path.ptr);
759 git_buf_dispose(&path);
760
761 cl_git_mkfile("./testconfig", "[some]\n path = ~user/foo");
762 cl_git_fail(git_config_get_path(&path, cfg, "some.path"));
763
764 cl_git_pass(git_libgit2_opts(GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, old_path.ptr));
765 git_buf_dispose(&old_path);
766 git_str_dispose(&home_path);
767 git_str_dispose(&expected_path);
768 git_config_free(cfg);
769 }
770
771 void test_config_read__crlf_style_line_endings(void)
772 {
773 git_buf buf = GIT_BUF_INIT;
774 git_config *cfg;
775
776 cl_set_cleanup(&clean_test_config, NULL);
777 cl_git_mkfile("./testconfig", "[some]\r\n var = value\r\n");
778 cl_git_pass(git_config_open_ondisk(&cfg, "./testconfig"));
779 cl_git_pass(git_config_get_string_buf(&buf, cfg, "some.var"));
780 cl_assert_equal_s(buf.ptr, "value");
781
782 git_config_free(cfg);
783 git_buf_dispose(&buf);
784 }
785
786 void test_config_read__trailing_crlf(void)
787 {
788 git_buf buf = GIT_BUF_INIT;
789 git_config *cfg;
790
791 cl_set_cleanup(&clean_test_config, NULL);
792 cl_git_mkfile("./testconfig", "[some]\r\n var = value\r\n\r\n");
793 cl_git_pass(git_config_open_ondisk(&cfg, "./testconfig"));
794 cl_git_pass(git_config_get_string_buf(&buf, cfg, "some.var"));
795 cl_assert_equal_s(buf.ptr, "value");
796
797 git_config_free(cfg);
798 git_buf_dispose(&buf);
799 }
800
801 void test_config_read__bom(void)
802 {
803 git_buf buf = GIT_BUF_INIT;
804 git_config *cfg;
805
806 cl_set_cleanup(&clean_test_config, NULL);
807 cl_git_mkfile("./testconfig", "\xEF\xBB\xBF[some]\n var = value\n");
808 cl_git_pass(git_config_open_ondisk(&cfg, "./testconfig"));
809 cl_git_pass(git_config_get_string_buf(&buf, cfg, "some.var"));
810 cl_assert_equal_s(buf.ptr, "value");
811
812 git_config_free(cfg);
813 git_buf_dispose(&buf);
814 }
815
816 void test_config_read__arbitrary_whitespace_before_subsection(void)
817 {
818 git_buf buf = GIT_BUF_INIT;
819 git_config *cfg;
820
821 cl_set_cleanup(&clean_test_config, NULL);
822 cl_git_mkfile("./testconfig", "[some \t \"subsection\"]\n var = value\n");
823 cl_git_pass(git_config_open_ondisk(&cfg, "./testconfig"));
824 cl_git_pass(git_config_get_string_buf(&buf, cfg, "some.subsection.var"));
825 cl_assert_equal_s(buf.ptr, "value");
826
827 git_config_free(cfg);
828 git_buf_dispose(&buf);
829 }
830
831 void test_config_read__no_whitespace_after_subsection(void)
832 {
833 git_config *cfg;
834
835 cl_set_cleanup(&clean_test_config, NULL);
836 cl_git_mkfile("./testconfig", "[some \"subsection\" ]\n var = value\n");
837 cl_git_fail(git_config_open_ondisk(&cfg, "./testconfig"));
838
839 git_config_free(cfg);
840 }
841
842 void test_config_read__invalid_space_section(void)
843 {
844 git_config *cfg;
845
846 cl_set_cleanup(&clean_test_config, NULL);
847 cl_git_mkfile("./testconfig", "\xEF\xBB\xBF[some section]\n var = value\n");
848 cl_git_fail(git_config_open_ondisk(&cfg, "./testconfig"));
849
850 git_config_free(cfg);
851 }
852
853 void test_config_read__invalid_quoted_first_section(void)
854 {
855 git_config *cfg;
856
857 cl_set_cleanup(&clean_test_config, NULL);
858 cl_git_mkfile("./testconfig", "\xEF\xBB\xBF[\"some\"]\n var = value\n");
859 cl_git_fail(git_config_open_ondisk(&cfg, "./testconfig"));
860
861 git_config_free(cfg);
862 }
863
864 void test_config_read__invalid_unquoted_subsection(void)
865 {
866 git_config *cfg;
867
868 cl_set_cleanup(&clean_test_config, NULL);
869 cl_git_mkfile("./testconfig", "\xEF\xBB\xBF[some sub section]\n var = value\n");
870 cl_git_fail(git_config_open_ondisk(&cfg, "./testconfig"));
871
872 git_config_free(cfg);
873 }
874
875 void test_config_read__invalid_quoted_third_section(void)
876 {
877 git_config *cfg;
878
879 cl_set_cleanup(&clean_test_config, NULL);
880 cl_git_mkfile("./testconfig", "\xEF\xBB\xBF[some sub \"section\"]\n var = value\n");
881 cl_git_fail(git_config_open_ondisk(&cfg, "./testconfig"));
882
883 git_config_free(cfg);
884 }
885
886 void test_config_read__unreadable_file_ignored(void)
887 {
888 git_buf buf = GIT_BUF_INIT;
889 git_config *cfg;
890 int ret;
891
892 cl_set_cleanup(&clean_test_config, NULL);
893 cl_git_mkfile("./testconfig", "[some] var = value\n[some \"OtheR\"] var = value");
894 cl_git_pass(p_chmod("./testconfig", 0));
895
896 ret = git_config_open_ondisk(&cfg, "./test/config");
897 cl_assert(ret == 0 || ret == GIT_ENOTFOUND);
898
899 git_config_free(cfg);
900 git_buf_dispose(&buf);
901 }
902
903 void test_config_read__single_line(void)
904 {
905 git_buf buf = GIT_BUF_INIT;
906 git_config *cfg;
907
908 cl_set_cleanup(&clean_test_config, NULL);
909 cl_git_mkfile("./testconfig", "[some] var = value\n[some \"OtheR\"] var = value");
910 cl_git_pass(git_config_open_ondisk(&cfg, "./testconfig"));
911 cl_git_pass(git_config_get_string_buf(&buf, cfg, "some.var"));
912 cl_assert_equal_s(buf.ptr, "value");
913
914 git_buf_dispose(&buf);
915 cl_git_pass(git_config_get_string_buf(&buf, cfg, "some.OtheR.var"));
916 cl_assert_equal_s(buf.ptr, "value");
917
918 git_config_free(cfg);
919 cl_git_mkfile("./testconfig", "[some] var = value\n[some \"OtheR\"]var = value");
920 cl_git_pass(git_config_open_ondisk(&cfg, "./testconfig"));
921 git_buf_dispose(&buf);
922 cl_git_pass(git_config_get_string_buf(&buf, cfg, "some.var"));
923 cl_assert_equal_s(buf.ptr, "value");
924
925 git_buf_dispose(&buf);
926 cl_git_pass(git_config_get_string_buf(&buf, cfg, "some.OtheR.var"));
927 cl_assert_equal_s(buf.ptr, "value");
928
929 git_config_free(cfg);
930 git_buf_dispose(&buf);
931 }
932
933 static int read_nosection_cb(const git_config_entry *entry, void *payload) {
934 int *seen = (int*)payload;
935 if (strcmp(entry->name, "key") == 0) {
936 (*seen)++;
937 }
938 return 0;
939 }
940
941 /* This would ideally issue a warning, if we had a way to do so. */
942 void test_config_read__nosection(void)
943 {
944 git_config *cfg;
945 git_buf buf = GIT_BUF_INIT;
946 int seen = 0;
947
948 cl_git_pass(git_config_open_ondisk(&cfg, cl_fixture("config/config-nosection")));
949
950 /*
951 * Given a key with no section, we do not allow reading it,
952 * but we do include it in an iteration over the config
953 * store. This appears to match how git's own APIs (and
954 * git-config(1)) behave.
955 */
956
957 cl_git_fail_with(git_config_get_string_buf(&buf, cfg, "key"), GIT_EINVALIDSPEC);
958
959 cl_git_pass(git_config_foreach(cfg, read_nosection_cb, &seen));
960 cl_assert_equal_i(seen, 1);
961
962 git_buf_dispose(&buf);
963 git_config_free(cfg);
964 }
965
966 enum {
967 MAP_TRUE = 0,
968 MAP_FALSE = 1,
969 MAP_ALWAYS = 2
970 };
971
972 static git_configmap _test_map1[] = {
973 {GIT_CONFIGMAP_STRING, "always", MAP_ALWAYS},
974 {GIT_CONFIGMAP_FALSE, NULL, MAP_FALSE},
975 {GIT_CONFIGMAP_TRUE, NULL, MAP_TRUE},
976 };
977
978 static git_configmap _test_map2[] = {
979 {GIT_CONFIGMAP_INT32, NULL, 0},
980 };
981
982 void test_config_read__get_mapped(void)
983 {
984 git_config *cfg;
985 int val;
986 int known_good;
987
988 cl_set_cleanup(&clean_test_config, NULL);
989 cl_git_mkfile("./testconfig", "[header]\n"
990 " key1 = 1\n"
991 " key2 = true\n"
992 " key3\n"
993 " key4 = always\n"
994 " key5 = false\n"
995 " key6 = 0\n"
996 " key7 = never\n"
997 " key8 = On\n"
998 " key9 = off\n");
999 cl_git_pass(git_config_open_ondisk(&cfg, "./testconfig"));
1000
1001 /* check parsing bool and string */
1002 cl_git_pass(git_config_get_mapped(&val, cfg, "header.key1", _test_map1, ARRAY_SIZE(_test_map1)));
1003 cl_assert_equal_i(val, MAP_TRUE);
1004 cl_git_pass(git_config_get_mapped(&val, cfg, "header.key2", _test_map1, ARRAY_SIZE(_test_map1)));
1005 cl_assert_equal_i(val, MAP_TRUE);
1006 cl_git_pass(git_config_get_mapped(&val, cfg, "header.key3", _test_map1, ARRAY_SIZE(_test_map1)));
1007 cl_assert_equal_i(val, MAP_TRUE);
1008 cl_git_pass(git_config_get_mapped(&val, cfg, "header.key8", _test_map1, ARRAY_SIZE(_test_map1)));
1009 cl_assert_equal_i(val, MAP_TRUE);
1010
1011 cl_git_pass(git_config_get_mapped(&val, cfg, "header.key4", _test_map1, ARRAY_SIZE(_test_map1)));
1012 cl_assert_equal_i(val, MAP_ALWAYS);
1013
1014 cl_git_pass(git_config_get_mapped(&val, cfg, "header.key5", _test_map1, ARRAY_SIZE(_test_map1)));
1015 cl_assert_equal_i(val, MAP_FALSE);
1016 cl_git_pass(git_config_get_mapped(&val, cfg, "header.key6", _test_map1, ARRAY_SIZE(_test_map1)));
1017 cl_assert_equal_i(val, MAP_FALSE);
1018 cl_git_pass(git_config_get_mapped(&val, cfg, "header.key9", _test_map1, ARRAY_SIZE(_test_map1)));
1019 cl_assert_equal_i(val, MAP_FALSE);
1020
1021 cl_git_fail(git_config_get_mapped(&val, cfg, "header.key7", _test_map1, ARRAY_SIZE(_test_map1)));
1022
1023 /* check parsing int values */
1024 cl_git_pass(git_config_get_mapped(&val, cfg, "header.key1", _test_map2, ARRAY_SIZE(_test_map2)));
1025 cl_git_pass(git_config_get_int32(&known_good, cfg, "header.key1"));
1026 cl_assert_equal_i(val, known_good);
1027 cl_git_pass(git_config_get_mapped(&val, cfg, "header.key6", _test_map2, ARRAY_SIZE(_test_map2)));
1028 cl_git_pass(git_config_get_int32(&known_good, cfg, "header.key6"));
1029 cl_assert_equal_i(val, known_good);
1030
1031 cl_git_fail(git_config_get_mapped(&val, cfg, "header.key2", _test_map2, ARRAY_SIZE(_test_map2)));
1032 cl_git_fail(git_config_get_mapped(&val, cfg, "header.key3", _test_map2, ARRAY_SIZE(_test_map2)));
1033 cl_git_fail(git_config_get_mapped(&val, cfg, "header.key4", _test_map2, ARRAY_SIZE(_test_map2)));
1034 cl_git_fail(git_config_get_mapped(&val, cfg, "header.key5", _test_map2, ARRAY_SIZE(_test_map2)));
1035 cl_git_fail(git_config_get_mapped(&val, cfg, "header.key7", _test_map2, ARRAY_SIZE(_test_map2)));
1036 cl_git_fail(git_config_get_mapped(&val, cfg, "header.key8", _test_map2, ARRAY_SIZE(_test_map2)));
1037 cl_git_fail(git_config_get_mapped(&val, cfg, "header.key9", _test_map2, ARRAY_SIZE(_test_map2)));
1038
1039 git_config_free(cfg);
1040 }