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