1 #include "clar_libgit2.h"
4 #include "git2/sys/config.h"
7 void test_config_write__initialize(void)
9 cl_fixture_sandbox("config/config9");
10 cl_fixture_sandbox("config/config15");
11 cl_fixture_sandbox("config/config17");
14 void test_config_write__cleanup(void)
16 cl_fixture_cleanup("config9");
17 cl_fixture_cleanup("config15");
18 cl_fixture_cleanup("config17");
21 void test_config_write__replace_value(void)
25 int64_t l
, expected
= +9223372036854775803;
27 /* By freeing the config, we make sure we flush the values */
28 cl_git_pass(git_config_open_ondisk(&cfg
, "config9"));
29 cl_git_pass(git_config_set_int32(cfg
, "core.dummy", 5));
32 cl_git_pass(git_config_open_ondisk(&cfg
, "config9"));
33 cl_git_pass(git_config_get_int32(&i
, cfg
, "core.dummy"));
37 cl_git_pass(git_config_open_ondisk(&cfg
, "config9"));
38 cl_git_pass(git_config_set_int32(cfg
, "core.dummy", 1));
41 cl_git_pass(git_config_open_ondisk(&cfg
, "config9"));
42 cl_git_pass(git_config_set_int64(cfg
, "core.verylong", expected
));
45 cl_git_pass(git_config_open_ondisk(&cfg
, "config9"));
46 cl_git_pass(git_config_get_int64(&l
, cfg
, "core.verylong"));
47 cl_assert(l
== expected
);
50 cl_git_pass(git_config_open_ondisk(&cfg
, "config9"));
51 cl_must_fail(git_config_get_int32(&i
, cfg
, "core.verylong"));
54 cl_git_pass(git_config_open_ondisk(&cfg
, "config9"));
55 cl_git_pass(git_config_set_int64(cfg
, "core.verylong", 1));
59 void test_config_write__delete_value(void)
64 cl_git_pass(git_config_open_ondisk(&cfg
, "config9"));
65 cl_git_pass(git_config_set_int32(cfg
, "core.dummy", 5));
68 cl_git_pass(git_config_open_ondisk(&cfg
, "config9"));
69 cl_git_pass(git_config_delete_entry(cfg
, "core.dummy"));
72 cl_git_pass(git_config_open_ondisk(&cfg
, "config9"));
73 cl_assert(git_config_get_int32(&i
, cfg
, "core.dummy") == GIT_ENOTFOUND
);
74 cl_git_pass(git_config_set_int32(cfg
, "core.dummy", 1));
79 * At the beginning of the test:
80 * - config9 has: core.dummy2=42
81 * - config15 has: core.dummy2=7
83 void test_config_write__delete_value_at_specific_level(void)
85 git_config
*cfg
, *cfg_specific
;
88 cl_git_pass(git_config_open_ondisk(&cfg
, "config15"));
89 cl_git_pass(git_config_get_int32(&i
, cfg
, "core.dummy2"));
93 cl_git_pass(git_config_new(&cfg
));
94 cl_git_pass(git_config_add_file_ondisk(cfg
, "config9",
95 GIT_CONFIG_LEVEL_LOCAL
, NULL
, 0));
96 cl_git_pass(git_config_add_file_ondisk(cfg
, "config15",
97 GIT_CONFIG_LEVEL_GLOBAL
, NULL
, 0));
99 cl_git_pass(git_config_open_level(&cfg_specific
, cfg
, GIT_CONFIG_LEVEL_GLOBAL
));
101 cl_git_pass(git_config_delete_entry(cfg_specific
, "core.dummy2"));
102 git_config_free(cfg
);
104 cl_git_pass(git_config_open_ondisk(&cfg
, "config15"));
105 cl_assert(git_config_get_int32(&i
, cfg
, "core.dummy2") == GIT_ENOTFOUND
);
106 cl_git_pass(git_config_set_int32(cfg
, "core.dummy2", 7));
108 git_config_free(cfg_specific
);
109 git_config_free(cfg
);
113 * This test exposes a bug where duplicate empty section headers could prevent
114 * deletion of config entries.
116 void test_config_write__delete_value_with_duplicate_header(void)
118 const char *file_name
= "config-duplicate-header";
119 const char *entry_name
= "remote.origin.url";
121 git_config_entry
*entry
;
123 /* This config can occur after removing and re-adding the origin remote */
124 const char *file_content
=
125 "[remote \"origin\"]\n" \
126 "[branch \"master\"]\n" \
127 " remote = \"origin\"\n" \
128 "[remote \"origin\"]\n" \
131 /* Write the test config and make sure the expected entry exists */
132 cl_git_mkfile(file_name
, file_content
);
133 cl_git_pass(git_config_open_ondisk(&cfg
, file_name
));
134 cl_git_pass(git_config_get_entry(&entry
, cfg
, entry_name
));
136 /* Delete that entry */
137 cl_git_pass(git_config_delete_entry(cfg
, entry_name
));
139 /* Reopen the file and make sure the entry no longer exists */
140 git_config_entry_free(entry
);
141 git_config_free(cfg
);
142 cl_git_pass(git_config_open_ondisk(&cfg
, file_name
));
143 cl_git_fail(git_config_get_entry(&entry
, cfg
, entry_name
));
146 git_config_entry_free(entry
);
147 git_config_free(cfg
);
151 * This test exposes a bug where duplicate section headers could cause
152 * config_write to add a new entry when one already exists.
154 void test_config_write__add_value_with_duplicate_header(void)
156 const char *file_name
= "config-duplicate-insert";
157 const char *entry_name
= "foo.c";
158 const char *old_val
= "old";
159 const char *new_val
= "new";
161 git_config
*cfg
, *snapshot
;
163 /* c = old should be replaced by c = new.
164 * The bug causes c = new to be inserted under the first 'foo' header.
166 const char *file_content
=
174 /* Write the test config */
175 cl_git_mkfile(file_name
, file_content
);
176 cl_git_pass(git_config_open_ondisk(&cfg
, file_name
));
178 /* make sure the expected entry (foo.c) exists */
179 cl_git_pass(git_config_snapshot(&snapshot
, cfg
));
180 cl_git_pass(git_config_get_string(&str
, snapshot
, entry_name
));
181 cl_assert_equal_s(old_val
, str
);
182 git_config_free(snapshot
);
184 /* Try setting foo.c to something else */
185 cl_git_pass(git_config_set_string(cfg
, entry_name
, new_val
));
186 git_config_free(cfg
);
188 /* Reopen the file and make sure the new value was set */
189 cl_git_pass(git_config_open_ondisk(&cfg
, file_name
));
190 cl_git_pass(git_config_snapshot(&snapshot
, cfg
));
191 cl_git_pass(git_config_get_string(&str
, snapshot
, entry_name
));
192 cl_assert_equal_s(new_val
, str
);
195 git_config_free(snapshot
);
196 git_config_free(cfg
);
199 void test_config_write__overwrite_value_with_duplicate_header(void)
201 const char *file_name
= "config-duplicate-header";
202 const char *entry_name
= "remote.origin.url";
204 git_config_entry
*entry
;
206 /* This config can occur after removing and re-adding the origin remote */
207 const char *file_content
=
208 "[remote \"origin\"]\n" \
209 "[branch \"master\"]\n" \
210 " remote = \"origin\"\n" \
211 "[remote \"origin\"]\n" \
214 /* Write the test config and make sure the expected entry exists */
215 cl_git_mkfile(file_name
, file_content
);
216 cl_git_pass(git_config_open_ondisk(&cfg
, file_name
));
217 cl_git_pass(git_config_get_entry(&entry
, cfg
, entry_name
));
219 /* Update that entry */
220 cl_git_pass(git_config_set_string(cfg
, entry_name
, "newurl"));
222 /* Reopen the file and make sure the entry was updated */
223 git_config_entry_free(entry
);
224 git_config_free(cfg
);
225 cl_git_pass(git_config_open_ondisk(&cfg
, file_name
));
226 cl_git_pass(git_config_get_entry(&entry
, cfg
, entry_name
));
228 cl_assert_equal_s("newurl", entry
->value
);
231 git_config_entry_free(entry
);
232 git_config_free(cfg
);
235 static int multivar_cb(const git_config_entry
*entry
, void *data
)
237 int *n
= (int *)data
;
239 cl_assert_equal_s(entry
->value
, "newurl");
246 void test_config_write__overwrite_multivar_within_duplicate_header(void)
248 const char *file_name
= "config-duplicate-header";
249 const char *entry_name
= "remote.origin.url";
251 git_config_entry
*entry
;
254 /* This config can occur after removing and re-adding the origin remote */
255 const char *file_content
=
256 "[remote \"origin\"]\n" \
258 "[branch \"master\"]\n" \
259 " remote = \"origin\"\n" \
260 "[remote \"origin\"]\n" \
263 /* Write the test config and make sure the expected entry exists */
264 cl_git_mkfile(file_name
, file_content
);
265 cl_git_pass(git_config_open_ondisk(&cfg
, file_name
));
266 cl_git_pass(git_config_get_entry(&entry
, cfg
, entry_name
));
268 /* Update that entry */
269 cl_git_pass(git_config_set_multivar(cfg
, entry_name
, ".*", "newurl"));
270 git_config_entry_free(entry
);
271 git_config_free(cfg
);
273 /* Reopen the file and make sure the entry was updated */
274 cl_git_pass(git_config_open_ondisk(&cfg
, file_name
));
275 cl_git_pass(git_config_get_multivar_foreach(cfg
, entry_name
, NULL
, multivar_cb
, &n
));
276 cl_assert_equal_i(2, n
);
279 git_config_free(cfg
);
282 void test_config_write__write_subsection(void)
285 git_buf buf
= GIT_BUF_INIT
;
287 cl_git_pass(git_config_open_ondisk(&cfg
, "config9"));
288 cl_git_pass(git_config_set_string(cfg
, "my.own.var", "works"));
289 git_config_free(cfg
);
291 cl_git_pass(git_config_open_ondisk(&cfg
, "config9"));
292 cl_git_pass(git_config_get_string_buf(&buf
, cfg
, "my.own.var"));
293 cl_assert_equal_s("works", git_buf_cstr(&buf
));
295 git_buf_dispose(&buf
);
296 git_config_free(cfg
);
299 void test_config_write__delete_inexistent(void)
303 cl_git_pass(git_config_open_ondisk(&cfg
, "config9"));
304 cl_assert(git_config_delete_entry(cfg
, "core.imaginary") == GIT_ENOTFOUND
);
305 git_config_free(cfg
);
308 void test_config_write__value_containing_quotes(void)
311 git_buf buf
= GIT_BUF_INIT
;
313 cl_git_pass(git_config_open_ondisk(&cfg
, "config9"));
314 cl_git_pass(git_config_set_string(cfg
, "core.somevar", "this \"has\" quotes"));
315 cl_git_pass(git_config_get_string_buf(&buf
, cfg
, "core.somevar"));
316 cl_assert_equal_s("this \"has\" quotes", git_buf_cstr(&buf
));
318 git_config_free(cfg
);
320 cl_git_pass(git_config_open_ondisk(&cfg
, "config9"));
321 cl_git_pass(git_config_get_string_buf(&buf
, cfg
, "core.somevar"));
322 cl_assert_equal_s("this \"has\" quotes", git_buf_cstr(&buf
));
324 git_config_free(cfg
);
326 /* The code path for values that already exist is different, check that one as well */
327 cl_git_pass(git_config_open_ondisk(&cfg
, "config9"));
328 cl_git_pass(git_config_set_string(cfg
, "core.somevar", "this also \"has\" quotes"));
329 cl_git_pass(git_config_get_string_buf(&buf
, cfg
, "core.somevar"));
330 cl_assert_equal_s("this also \"has\" quotes", git_buf_cstr(&buf
));
332 git_config_free(cfg
);
334 cl_git_pass(git_config_open_ondisk(&cfg
, "config9"));
335 cl_git_pass(git_config_get_string_buf(&buf
, cfg
, "core.somevar"));
336 cl_assert_equal_s("this also \"has\" quotes", git_buf_cstr(&buf
));
337 git_buf_dispose(&buf
);
338 git_config_free(cfg
);
341 void test_config_write__escape_value(void)
344 git_buf buf
= GIT_BUF_INIT
;
346 cl_git_pass(git_config_open_ondisk(&cfg
, "config9"));
347 cl_git_pass(git_config_set_string(cfg
, "core.somevar", "this \"has\" quotes and \t"));
348 cl_git_pass(git_config_get_string_buf(&buf
, cfg
, "core.somevar"));
349 cl_assert_equal_s("this \"has\" quotes and \t", git_buf_cstr(&buf
));
351 git_config_free(cfg
);
353 cl_git_pass(git_config_open_ondisk(&cfg
, "config9"));
354 cl_git_pass(git_config_get_string_buf(&buf
, cfg
, "core.somevar"));
355 cl_assert_equal_s("this \"has\" quotes and \t", git_buf_cstr(&buf
));
356 git_buf_dispose(&buf
);
357 git_config_free(cfg
);
360 void test_config_write__add_value_at_specific_level(void)
362 git_config
*cfg
, *cfg_specific
;
364 int64_t l
, expected
= +9223372036854775803;
365 git_buf buf
= GIT_BUF_INIT
;
367 /* open config15 as global level config file */
368 cl_git_pass(git_config_new(&cfg
));
369 cl_git_pass(git_config_add_file_ondisk(cfg
, "config9",
370 GIT_CONFIG_LEVEL_LOCAL
, NULL
, 0));
371 cl_git_pass(git_config_add_file_ondisk(cfg
, "config15",
372 GIT_CONFIG_LEVEL_GLOBAL
, NULL
, 0));
374 cl_git_pass(git_config_open_level(&cfg_specific
, cfg
, GIT_CONFIG_LEVEL_GLOBAL
));
376 cl_git_pass(git_config_set_int32(cfg_specific
, "core.int32global", 28));
377 cl_git_pass(git_config_set_int64(cfg_specific
, "core.int64global", expected
));
378 cl_git_pass(git_config_set_bool(cfg_specific
, "core.boolglobal", true));
379 cl_git_pass(git_config_set_string(cfg_specific
, "core.stringglobal", "I'm a global config value!"));
380 git_config_free(cfg_specific
);
381 git_config_free(cfg
);
383 /* open config15 as local level config file */
384 cl_git_pass(git_config_open_ondisk(&cfg
, "config15"));
386 cl_git_pass(git_config_get_int32(&i
, cfg
, "core.int32global"));
387 cl_assert_equal_i(28, i
);
388 cl_git_pass(git_config_get_int64(&l
, cfg
, "core.int64global"));
389 cl_assert(l
== expected
);
390 cl_git_pass(git_config_get_bool(&i
, cfg
, "core.boolglobal"));
391 cl_assert_equal_b(true, i
);
392 cl_git_pass(git_config_get_string_buf(&buf
, cfg
, "core.stringglobal"));
393 cl_assert_equal_s("I'm a global config value!", git_buf_cstr(&buf
));
395 git_buf_dispose(&buf
);
396 git_config_free(cfg
);
399 void test_config_write__add_value_at_file_with_no_clrf_at_the_end(void)
404 cl_git_pass(git_config_open_ondisk(&cfg
, "config17"));
405 cl_git_pass(git_config_set_int32(cfg
, "core.newline", 7));
406 git_config_free(cfg
);
408 cl_git_pass(git_config_open_ondisk(&cfg
, "config17"));
409 cl_git_pass(git_config_get_int32(&i
, cfg
, "core.newline"));
410 cl_assert_equal_i(7, i
);
412 git_config_free(cfg
);
415 void test_config_write__add_section_at_file_with_no_clrf_at_the_end(void)
420 cl_git_pass(git_config_open_ondisk(&cfg
, "config17"));
421 cl_git_pass(git_config_set_int32(cfg
, "diff.context", 10));
422 git_config_free(cfg
);
424 cl_git_pass(git_config_open_ondisk(&cfg
, "config17"));
425 cl_git_pass(git_config_get_int32(&i
, cfg
, "diff.context"));
426 cl_assert_equal_i(10, i
);
428 git_config_free(cfg
);
431 void test_config_write__add_value_which_needs_quotes(void)
433 git_config
*cfg
, *base
;
440 cl_git_pass(git_config_open_ondisk(&cfg
, "config17"));
441 cl_git_pass(git_config_set_string(cfg
, "core.startwithspace", " Something"));
442 cl_git_pass(git_config_set_string(cfg
, "core.endwithspace", "Something "));
443 cl_git_pass(git_config_set_string(cfg
, "core.containscommentchar1", "some#thing"));
444 cl_git_pass(git_config_set_string(cfg
, "core.containscommentchar2", "some;thing"));
445 cl_git_pass(git_config_set_string(cfg
, "core.startwhithsapceandcontainsdoublequote", " some\"thing"));
446 git_config_free(cfg
);
448 cl_git_pass(git_config_open_ondisk(&base
, "config17"));
449 cl_git_pass(git_config_snapshot(&cfg
, base
));
450 cl_git_pass(git_config_get_string(&str1
, cfg
, "core.startwithspace"));
451 cl_assert_equal_s(" Something", str1
);
452 cl_git_pass(git_config_get_string(&str2
, cfg
, "core.endwithspace"));
453 cl_assert_equal_s("Something ", str2
);
454 cl_git_pass(git_config_get_string(&str3
, cfg
, "core.containscommentchar1"));
455 cl_assert_equal_s("some#thing", str3
);
456 cl_git_pass(git_config_get_string(&str4
, cfg
, "core.containscommentchar2"));
457 cl_assert_equal_s("some;thing", str4
);
458 cl_git_pass(git_config_get_string(&str5
, cfg
, "core.startwhithsapceandcontainsdoublequote"));
459 cl_assert_equal_s(" some\"thing", str5
);
460 git_config_free(cfg
);
461 git_config_free(base
);
464 void test_config_write__can_set_a_value_to_NULL(void)
466 git_repository
*repository
;
469 repository
= cl_git_sandbox_init("testrepo.git");
471 cl_git_pass(git_repository_config(&config
, repository
));
472 cl_git_fail(git_config_set_string(config
, "a.b.c", NULL
));
473 git_config_free(config
);
475 cl_git_sandbox_cleanup();
478 void test_config_write__can_set_an_empty_value(void)
480 git_repository
*repository
;
484 repository
= cl_git_sandbox_init("testrepo.git");
485 cl_git_pass(git_repository_config(&config
, repository
));
487 cl_git_pass(git_config_set_string(config
, "core.somevar", ""));
488 cl_git_pass(git_config_get_string_buf(&buf
, config
, "core.somevar"));
489 cl_assert_equal_s("", buf
.ptr
);
491 git_buf_dispose(&buf
);
492 git_config_free(config
);
493 cl_git_sandbox_cleanup();
496 void test_config_write__updating_a_locked_config_file_returns_ELOCKED(void)
500 cl_git_pass(git_config_open_ondisk(&cfg
, "config9"));
502 cl_git_mkfile("config9.lock", "[core]\n");
504 cl_git_fail_with(git_config_set_string(cfg
, "core.dump", "boom"), GIT_ELOCKED
);
506 git_config_free(cfg
);
509 void test_config_write__outside_change(void)
513 const char *filename
= "config-ext-change";
515 cl_git_mkfile(filename
, "[old]\nvalue = 5\n");
517 cl_git_pass(git_config_open_ondisk(&cfg
, filename
));
519 cl_git_pass(git_config_get_int32(&tmp
, cfg
, "old.value"));
521 /* Change the value on the file itself (simulate external process) */
522 cl_git_mkfile(filename
, "[old]\nvalue = 6\n");
524 cl_git_pass(git_config_set_int32(cfg
, "new.value", 7));
526 cl_git_pass(git_config_get_int32(&tmp
, cfg
, "old.value"));
527 cl_assert_equal_i(6, tmp
);
529 git_config_free(cfg
);
532 #define FOO_COMMENT \
533 "; another comment!\n"
535 #define SECTION_FOO \
538 " [section \"foo\"] \n" \
539 " # here's a comment\n" \
540 "\tname = \"value\"\n" \
541 " name2 = \"value2\"\n" \
543 #define SECTION_FOO_WITH_COMMENT SECTION_FOO FOO_COMMENT
545 #define SECTION_BAR \
546 "[section \"bar\"]\t\n" \
548 " barname=\"value\"\n"
551 void test_config_write__preserves_whitespace_and_comments(void)
553 const char *file_name
= "config-duplicate-header";
556 git_buf newfile
= GIT_BUF_INIT
;
558 /* This config can occur after removing and re-adding the origin remote */
559 const char *file_content
= SECTION_FOO_WITH_COMMENT SECTION_BAR
;
561 /* Write the test config and make sure the expected entry exists */
562 cl_git_mkfile(file_name
, file_content
);
563 cl_git_pass(git_config_open_ondisk(&cfg
, file_name
));
564 cl_git_pass(git_config_set_string(cfg
, "section.foo.other", "otherval"));
565 cl_git_pass(git_config_set_string(cfg
, "newsection.newname", "new_value"));
567 /* Ensure that we didn't needlessly mangle the config file */
568 cl_git_pass(git_futils_readbuffer(&newfile
, file_name
));
571 cl_assert_equal_strn(SECTION_FOO
, n
, strlen(SECTION_FOO
));
572 n
+= strlen(SECTION_FOO
);
573 cl_assert_equal_strn("\tother = otherval\n", n
, strlen("\tother = otherval\n"));
574 n
+= strlen("\tother = otherval\n");
575 cl_assert_equal_strn(FOO_COMMENT
, n
, strlen(FOO_COMMENT
));
576 n
+= strlen(FOO_COMMENT
);
578 cl_assert_equal_strn(SECTION_BAR
, n
, strlen(SECTION_BAR
));
579 n
+= strlen(SECTION_BAR
);
581 cl_assert_equal_s("[newsection]\n\tnewname = new_value\n", n
);
583 git_buf_dispose(&newfile
);
584 git_config_free(cfg
);
587 void test_config_write__preserves_entry_with_name_only(void)
589 const char *file_name
= "config-empty-value";
591 git_buf newfile
= GIT_BUF_INIT
;
593 /* Write the test config and make sure the expected entry exists */
594 cl_git_mkfile(file_name
, "[section \"foo\"]\n\tname\n");
595 cl_git_pass(git_config_open_ondisk(&cfg
, file_name
));
596 cl_git_pass(git_config_set_string(cfg
, "newsection.newname", "new_value"));
597 cl_git_pass(git_config_set_string(cfg
, "section.foo.other", "otherval"));
599 cl_git_pass(git_futils_readbuffer(&newfile
, file_name
));
600 cl_assert_equal_s("[section \"foo\"]\n\tname\n\tother = otherval\n[newsection]\n\tnewname = new_value\n", newfile
.ptr
);
602 git_buf_dispose(&newfile
);
603 git_config_free(cfg
);
606 void test_config_write__to_empty_file(void)
609 const char *filename
= "config-file";
610 git_buf result
= GIT_BUF_INIT
;
612 cl_git_mkfile(filename
, "");
613 cl_git_pass(git_config_open_ondisk(&cfg
, filename
));
614 cl_git_pass(git_config_set_string(cfg
, "section.name", "value"));
615 git_config_free(cfg
);
617 cl_git_pass(git_futils_readbuffer(&result
, "config-file"));
618 cl_assert_equal_s("[section]\n\tname = value\n", result
.ptr
);
620 git_buf_dispose(&result
);
623 void test_config_write__to_file_with_only_comment(void)
626 const char *filename
= "config-file";
627 git_buf result
= GIT_BUF_INIT
;
629 cl_git_mkfile(filename
, "\n\n");
630 cl_git_pass(git_config_open_ondisk(&cfg
, filename
));
631 cl_git_pass(git_config_set_string(cfg
, "section.name", "value"));
632 git_config_free(cfg
);
634 cl_git_pass(git_futils_readbuffer(&result
, "config-file"));
635 cl_assert_equal_s("\n\n[section]\n\tname = value\n", result
.ptr
);
637 git_buf_dispose(&result
);
640 void test_config_write__locking(void)
642 git_config
*cfg
, *cfg2
;
643 git_config_entry
*entry
;
645 const char *filename
= "locked-file";
647 /* Open the config and lock it */
648 cl_git_mkfile(filename
, "[section]\n\tname = value\n");
649 cl_git_pass(git_config_open_ondisk(&cfg
, filename
));
650 cl_git_pass(git_config_get_entry(&entry
, cfg
, "section.name"));
651 cl_assert_equal_s("value", entry
->value
);
652 git_config_entry_free(entry
);
653 cl_git_pass(git_config_lock(&tx
, cfg
));
655 /* Change entries in the locked backend */
656 cl_git_pass(git_config_set_string(cfg
, "section.name", "other value"));
657 cl_git_pass(git_config_set_string(cfg
, "section2.name3", "more value"));
659 /* We can see that the file we read from hasn't changed */
660 cl_git_pass(git_config_open_ondisk(&cfg2
, filename
));
661 cl_git_pass(git_config_get_entry(&entry
, cfg2
, "section.name"));
662 cl_assert_equal_s("value", entry
->value
);
663 git_config_entry_free(entry
);
664 cl_git_fail_with(GIT_ENOTFOUND
, git_config_get_entry(&entry
, cfg2
, "section2.name3"));
665 git_config_free(cfg2
);
667 /* And we also get the old view when we read from the locked config */
668 cl_git_pass(git_config_get_entry(&entry
, cfg
, "section.name"));
669 cl_assert_equal_s("value", entry
->value
);
670 git_config_entry_free(entry
);
671 cl_git_fail_with(GIT_ENOTFOUND
, git_config_get_entry(&entry
, cfg
, "section2.name3"));
673 cl_git_pass(git_transaction_commit(tx
));
674 git_transaction_free(tx
);
676 /* Now that we've unlocked it, we should see both updates */
677 cl_git_pass(git_config_get_entry(&entry
, cfg
, "section.name"));
678 cl_assert_equal_s("other value", entry
->value
);
679 git_config_entry_free(entry
);
680 cl_git_pass(git_config_get_entry(&entry
, cfg
, "section2.name3"));
681 cl_assert_equal_s("more value", entry
->value
);
682 git_config_entry_free(entry
);
684 git_config_free(cfg
);
686 /* We should also see the changes after reopening the config */
687 cl_git_pass(git_config_open_ondisk(&cfg
, filename
));
688 cl_git_pass(git_config_get_entry(&entry
, cfg
, "section.name"));
689 cl_assert_equal_s("other value", entry
->value
);
690 git_config_entry_free(entry
);
691 cl_git_pass(git_config_get_entry(&entry
, cfg
, "section2.name3"));
692 cl_assert_equal_s("more value", entry
->value
);
693 git_config_entry_free(entry
);
695 git_config_free(cfg
);
698 void test_config_write__repeated(void)
700 const char *filename
= "config-repeated";
702 git_buf result
= GIT_BUF_INIT
;
703 const char *expected
= "[sample \"prefix\"]\n\
704 \tsetting1 = someValue1\n\
705 \tsetting2 = someValue2\n\
706 \tsetting3 = someValue3\n\
707 \tsetting4 = someValue4\n\
709 cl_git_pass(git_config_open_ondisk(&cfg
, filename
));
710 cl_git_pass(git_config_set_string(cfg
, "sample.prefix.setting1", "someValue1"));
711 cl_git_pass(git_config_set_string(cfg
, "sample.prefix.setting2", "someValue2"));
712 cl_git_pass(git_config_set_string(cfg
, "sample.prefix.setting3", "someValue3"));
713 cl_git_pass(git_config_set_string(cfg
, "sample.prefix.setting4", "someValue4"));
714 git_config_free(cfg
);
716 cl_git_pass(git_config_open_ondisk(&cfg
, filename
));
718 cl_git_pass(git_futils_readbuffer(&result
, filename
));
719 cl_assert_equal_s(expected
, result
.ptr
);
720 git_buf_dispose(&result
);
722 git_config_free(cfg
);
725 void test_config_write__preserve_case(void)
727 const char *filename
= "config-preserve-case";
729 git_buf result
= GIT_BUF_INIT
;
730 const char *expected
= "[sOMe]\n" \
734 cl_git_pass(git_config_open_ondisk(&cfg
, filename
));
735 cl_git_pass(git_config_set_string(cfg
, "sOMe.ThInG", "foo"));
736 cl_git_pass(git_config_set_string(cfg
, "SomE.OtheR", "thing"));
737 git_config_free(cfg
);
739 cl_git_pass(git_config_open_ondisk(&cfg
, filename
));
741 cl_git_pass(git_futils_readbuffer(&result
, filename
));
742 cl_assert_equal_s(expected
, result
.ptr
);
743 git_buf_dispose(&result
);
745 git_config_free(cfg
);