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