1 #include "clar_libgit2.h"
4 #include "git2/sys/config.h"
5 #include "config_file.h"
8 void test_config_write__initialize(void)
10 cl_fixture_sandbox("config/config9");
11 cl_fixture_sandbox("config/config15");
12 cl_fixture_sandbox("config/config17");
15 void test_config_write__cleanup(void)
17 cl_fixture_cleanup("config9");
18 cl_fixture_cleanup("config15");
19 cl_fixture_cleanup("config17");
22 void test_config_write__replace_value(void)
26 int64_t l
, expected
= +9223372036854775803;
28 /* By freeing the config, we make sure we flush the values */
29 cl_git_pass(git_config_open_ondisk(&cfg
, "config9"));
30 cl_git_pass(git_config_set_int32(cfg
, "core.dummy", 5));
33 cl_git_pass(git_config_open_ondisk(&cfg
, "config9"));
34 cl_git_pass(git_config_get_int32(&i
, cfg
, "core.dummy"));
38 cl_git_pass(git_config_open_ondisk(&cfg
, "config9"));
39 cl_git_pass(git_config_set_int32(cfg
, "core.dummy", 1));
42 cl_git_pass(git_config_open_ondisk(&cfg
, "config9"));
43 cl_git_pass(git_config_set_int64(cfg
, "core.verylong", expected
));
46 cl_git_pass(git_config_open_ondisk(&cfg
, "config9"));
47 cl_git_pass(git_config_get_int64(&l
, cfg
, "core.verylong"));
48 cl_assert(l
== expected
);
51 cl_git_pass(git_config_open_ondisk(&cfg
, "config9"));
52 cl_must_fail(git_config_get_int32(&i
, cfg
, "core.verylong"));
55 cl_git_pass(git_config_open_ondisk(&cfg
, "config9"));
56 cl_git_pass(git_config_set_int64(cfg
, "core.verylong", 1));
60 void test_config_write__delete_value(void)
65 cl_git_pass(git_config_open_ondisk(&cfg
, "config9"));
66 cl_git_pass(git_config_set_int32(cfg
, "core.dummy", 5));
69 cl_git_pass(git_config_open_ondisk(&cfg
, "config9"));
70 cl_git_pass(git_config_delete_entry(cfg
, "core.dummy"));
73 cl_git_pass(git_config_open_ondisk(&cfg
, "config9"));
74 cl_assert(git_config_get_int32(&i
, cfg
, "core.dummy") == GIT_ENOTFOUND
);
75 cl_git_pass(git_config_set_int32(cfg
, "core.dummy", 1));
80 * At the beginning of the test:
81 * - config9 has: core.dummy2=42
82 * - config15 has: core.dummy2=7
84 void test_config_write__delete_value_at_specific_level(void)
86 git_config
*cfg
, *cfg_specific
;
89 cl_git_pass(git_config_open_ondisk(&cfg
, "config15"));
90 cl_git_pass(git_config_get_int32(&i
, cfg
, "core.dummy2"));
94 cl_git_pass(git_config_new(&cfg
));
95 cl_git_pass(git_config_add_file_ondisk(cfg
, "config9",
96 GIT_CONFIG_LEVEL_LOCAL
, 0));
97 cl_git_pass(git_config_add_file_ondisk(cfg
, "config15",
98 GIT_CONFIG_LEVEL_GLOBAL
, 0));
100 cl_git_pass(git_config_open_level(&cfg_specific
, cfg
, GIT_CONFIG_LEVEL_GLOBAL
));
102 cl_git_pass(git_config_delete_entry(cfg_specific
, "core.dummy2"));
103 git_config_free(cfg
);
105 cl_git_pass(git_config_open_ondisk(&cfg
, "config15"));
106 cl_assert(git_config_get_int32(&i
, cfg
, "core.dummy2") == GIT_ENOTFOUND
);
107 cl_git_pass(git_config_set_int32(cfg
, "core.dummy2", 7));
109 git_config_free(cfg_specific
);
110 git_config_free(cfg
);
114 * This test exposes a bug where duplicate empty section headers could prevent
115 * deletion of config entries.
117 void test_config_write__delete_value_with_duplicate_header(void)
119 const char *file_name
= "config-duplicate-header";
120 const char *entry_name
= "remote.origin.url";
122 git_config_entry
*entry
;
124 /* This config can occur after removing and re-adding the origin remote */
125 const char *file_content
=
126 "[remote \"origin\"]\n" \
127 "[branch \"master\"]\n" \
128 " remote = \"origin\"\n" \
129 "[remote \"origin\"]\n" \
132 /* Write the test config and make sure the expected entry exists */
133 cl_git_mkfile(file_name
, file_content
);
134 cl_git_pass(git_config_open_ondisk(&cfg
, file_name
));
135 cl_git_pass(git_config_get_entry(&entry
, cfg
, entry_name
));
137 /* Delete that entry */
138 cl_git_pass(git_config_delete_entry(cfg
, entry_name
));
140 /* Reopen the file and make sure the entry no longer exists */
141 git_config_entry_free(entry
);
142 git_config_free(cfg
);
143 cl_git_pass(git_config_open_ondisk(&cfg
, file_name
));
144 cl_git_fail(git_config_get_entry(&entry
, cfg
, entry_name
));
147 git_config_entry_free(entry
);
148 git_config_free(cfg
);
152 * This test exposes a bug where duplicate section headers could cause
153 * config_write to add a new entry when one already exists.
155 void test_config_write__add_value_with_duplicate_header(void)
157 const char *file_name
= "config-duplicate-insert";
158 const char *entry_name
= "foo.c";
159 const char *old_val
= "old";
160 const char *new_val
= "new";
162 git_config
*cfg
, *snapshot
;
164 /* c = old should be replaced by c = new.
165 * The bug causes c = new to be inserted under the first 'foo' header.
167 const char *file_content
=
175 /* Write the test config */
176 cl_git_mkfile(file_name
, file_content
);
177 cl_git_pass(git_config_open_ondisk(&cfg
, file_name
));
179 /* make sure the expected entry (foo.c) exists */
180 cl_git_pass(git_config_snapshot(&snapshot
, cfg
));
181 cl_git_pass(git_config_get_string(&str
, snapshot
, entry_name
));
182 cl_assert_equal_s(old_val
, str
);
183 git_config_free(snapshot
);
185 /* Try setting foo.c to something else */
186 cl_git_pass(git_config_set_string(cfg
, entry_name
, new_val
));
187 git_config_free(cfg
);
189 /* Reopen the file and make sure the new value was set */
190 cl_git_pass(git_config_open_ondisk(&cfg
, file_name
));
191 cl_git_pass(git_config_snapshot(&snapshot
, cfg
));
192 cl_git_pass(git_config_get_string(&str
, snapshot
, entry_name
));
193 cl_assert_equal_s(new_val
, str
);
196 git_config_free(snapshot
);
197 git_config_free(cfg
);
200 void test_config_write__overwrite_value_with_duplicate_header(void)
202 const char *file_name
= "config-duplicate-header";
203 const char *entry_name
= "remote.origin.url";
205 git_config_entry
*entry
;
207 /* This config can occur after removing and re-adding the origin remote */
208 const char *file_content
=
209 "[remote \"origin\"]\n" \
210 "[branch \"master\"]\n" \
211 " remote = \"origin\"\n" \
212 "[remote \"origin\"]\n" \
215 /* Write the test config and make sure the expected entry exists */
216 cl_git_mkfile(file_name
, file_content
);
217 cl_git_pass(git_config_open_ondisk(&cfg
, file_name
));
218 cl_git_pass(git_config_get_entry(&entry
, cfg
, entry_name
));
220 /* Update that entry */
221 cl_git_pass(git_config_set_string(cfg
, entry_name
, "newurl"));
223 /* Reopen the file and make sure the entry was updated */
224 git_config_entry_free(entry
);
225 git_config_free(cfg
);
226 cl_git_pass(git_config_open_ondisk(&cfg
, file_name
));
227 cl_git_pass(git_config_get_entry(&entry
, cfg
, entry_name
));
229 cl_assert_equal_s("newurl", entry
->value
);
232 git_config_entry_free(entry
);
233 git_config_free(cfg
);
236 static int multivar_cb(const git_config_entry
*entry
, void *data
)
238 int *n
= (int *)data
;
240 cl_assert_equal_s(entry
->value
, "newurl");
247 void test_config_write__overwrite_multivar_within_duplicate_header(void)
249 const char *file_name
= "config-duplicate-header";
250 const char *entry_name
= "remote.origin.url";
252 git_config_entry
*entry
;
255 /* This config can occur after removing and re-adding the origin remote */
256 const char *file_content
=
257 "[remote \"origin\"]\n" \
259 "[branch \"master\"]\n" \
260 " remote = \"origin\"\n" \
261 "[remote \"origin\"]\n" \
264 /* Write the test config and make sure the expected entry exists */
265 cl_git_mkfile(file_name
, file_content
);
266 cl_git_pass(git_config_open_ondisk(&cfg
, file_name
));
267 cl_git_pass(git_config_get_entry(&entry
, cfg
, entry_name
));
269 /* Update that entry */
270 cl_git_pass(git_config_set_multivar(cfg
, entry_name
, ".*", "newurl"));
271 git_config_entry_free(entry
);
272 git_config_free(cfg
);
274 /* Reopen the file and make sure the entry was updated */
275 cl_git_pass(git_config_open_ondisk(&cfg
, file_name
));
276 cl_git_pass(git_config_get_multivar_foreach(cfg
, entry_name
, NULL
, multivar_cb
, &n
));
277 cl_assert_equal_i(2, n
);
280 git_config_free(cfg
);
283 void test_config_write__write_subsection(void)
286 git_buf buf
= GIT_BUF_INIT
;
288 cl_git_pass(git_config_open_ondisk(&cfg
, "config9"));
289 cl_git_pass(git_config_set_string(cfg
, "my.own.var", "works"));
290 git_config_free(cfg
);
292 cl_git_pass(git_config_open_ondisk(&cfg
, "config9"));
293 cl_git_pass(git_config_get_string_buf(&buf
, cfg
, "my.own.var"));
294 cl_assert_equal_s("works", git_buf_cstr(&buf
));
297 git_config_free(cfg
);
300 void test_config_write__delete_inexistent(void)
304 cl_git_pass(git_config_open_ondisk(&cfg
, "config9"));
305 cl_assert(git_config_delete_entry(cfg
, "core.imaginary") == GIT_ENOTFOUND
);
306 git_config_free(cfg
);
309 void test_config_write__value_containing_quotes(void)
312 git_buf buf
= GIT_BUF_INIT
;
314 cl_git_pass(git_config_open_ondisk(&cfg
, "config9"));
315 cl_git_pass(git_config_set_string(cfg
, "core.somevar", "this \"has\" quotes"));
316 cl_git_pass(git_config_get_string_buf(&buf
, cfg
, "core.somevar"));
317 cl_assert_equal_s("this \"has\" quotes", git_buf_cstr(&buf
));
319 git_config_free(cfg
);
321 cl_git_pass(git_config_open_ondisk(&cfg
, "config9"));
322 cl_git_pass(git_config_get_string_buf(&buf
, cfg
, "core.somevar"));
323 cl_assert_equal_s("this \"has\" quotes", git_buf_cstr(&buf
));
325 git_config_free(cfg
);
327 /* The code path for values that already exist is different, check that one as well */
328 cl_git_pass(git_config_open_ondisk(&cfg
, "config9"));
329 cl_git_pass(git_config_set_string(cfg
, "core.somevar", "this also \"has\" quotes"));
330 cl_git_pass(git_config_get_string_buf(&buf
, cfg
, "core.somevar"));
331 cl_assert_equal_s("this also \"has\" quotes", git_buf_cstr(&buf
));
333 git_config_free(cfg
);
335 cl_git_pass(git_config_open_ondisk(&cfg
, "config9"));
336 cl_git_pass(git_config_get_string_buf(&buf
, cfg
, "core.somevar"));
337 cl_assert_equal_s("this also \"has\" quotes", git_buf_cstr(&buf
));
339 git_config_free(cfg
);
342 void test_config_write__escape_value(void)
345 git_buf buf
= GIT_BUF_INIT
;
347 cl_git_pass(git_config_open_ondisk(&cfg
, "config9"));
348 cl_git_pass(git_config_set_string(cfg
, "core.somevar", "this \"has\" quotes and \t"));
349 cl_git_pass(git_config_get_string_buf(&buf
, cfg
, "core.somevar"));
350 cl_assert_equal_s("this \"has\" quotes and \t", git_buf_cstr(&buf
));
352 git_config_free(cfg
);
354 cl_git_pass(git_config_open_ondisk(&cfg
, "config9"));
355 cl_git_pass(git_config_get_string_buf(&buf
, cfg
, "core.somevar"));
356 cl_assert_equal_s("this \"has\" quotes and \t", git_buf_cstr(&buf
));
358 git_config_free(cfg
);
361 void test_config_write__add_value_at_specific_level(void)
363 git_config
*cfg
, *cfg_specific
;
365 int64_t l
, expected
= +9223372036854775803;
366 git_buf buf
= GIT_BUF_INIT
;
368 // open config15 as global level config file
369 cl_git_pass(git_config_new(&cfg
));
370 cl_git_pass(git_config_add_file_ondisk(cfg
, "config9",
371 GIT_CONFIG_LEVEL_LOCAL
, 0));
372 cl_git_pass(git_config_add_file_ondisk(cfg
, "config15",
373 GIT_CONFIG_LEVEL_GLOBAL
, 0));
375 cl_git_pass(git_config_open_level(&cfg_specific
, cfg
, GIT_CONFIG_LEVEL_GLOBAL
));
377 cl_git_pass(git_config_set_int32(cfg_specific
, "core.int32global", 28));
378 cl_git_pass(git_config_set_int64(cfg_specific
, "core.int64global", expected
));
379 cl_git_pass(git_config_set_bool(cfg_specific
, "core.boolglobal", true));
380 cl_git_pass(git_config_set_string(cfg_specific
, "core.stringglobal", "I'm a global config value!"));
381 git_config_free(cfg_specific
);
382 git_config_free(cfg
);
384 // open config15 as local level config file
385 cl_git_pass(git_config_open_ondisk(&cfg
, "config15"));
387 cl_git_pass(git_config_get_int32(&i
, cfg
, "core.int32global"));
388 cl_assert_equal_i(28, i
);
389 cl_git_pass(git_config_get_int64(&l
, cfg
, "core.int64global"));
390 cl_assert(l
== expected
);
391 cl_git_pass(git_config_get_bool(&i
, cfg
, "core.boolglobal"));
392 cl_assert_equal_b(true, i
);
393 cl_git_pass(git_config_get_string_buf(&buf
, cfg
, "core.stringglobal"));
394 cl_assert_equal_s("I'm a global config value!", git_buf_cstr(&buf
));
397 git_config_free(cfg
);
400 void test_config_write__add_value_at_file_with_no_clrf_at_the_end(void)
405 cl_git_pass(git_config_open_ondisk(&cfg
, "config17"));
406 cl_git_pass(git_config_set_int32(cfg
, "core.newline", 7));
407 git_config_free(cfg
);
409 cl_git_pass(git_config_open_ondisk(&cfg
, "config17"));
410 cl_git_pass(git_config_get_int32(&i
, cfg
, "core.newline"));
411 cl_assert_equal_i(7, i
);
413 git_config_free(cfg
);
416 void test_config_write__add_section_at_file_with_no_clrf_at_the_end(void)
421 cl_git_pass(git_config_open_ondisk(&cfg
, "config17"));
422 cl_git_pass(git_config_set_int32(cfg
, "diff.context", 10));
423 git_config_free(cfg
);
425 cl_git_pass(git_config_open_ondisk(&cfg
, "config17"));
426 cl_git_pass(git_config_get_int32(&i
, cfg
, "diff.context"));
427 cl_assert_equal_i(10, i
);
429 git_config_free(cfg
);
432 void test_config_write__add_value_which_needs_quotes(void)
434 git_config
*cfg
, *base
;
441 cl_git_pass(git_config_open_ondisk(&cfg
, "config17"));
442 cl_git_pass(git_config_set_string(cfg
, "core.startwithspace", " Something"));
443 cl_git_pass(git_config_set_string(cfg
, "core.endwithspace", "Something "));
444 cl_git_pass(git_config_set_string(cfg
, "core.containscommentchar1", "some#thing"));
445 cl_git_pass(git_config_set_string(cfg
, "core.containscommentchar2", "some;thing"));
446 cl_git_pass(git_config_set_string(cfg
, "core.startwhithsapceandcontainsdoublequote", " some\"thing"));
447 git_config_free(cfg
);
449 cl_git_pass(git_config_open_ondisk(&base
, "config17"));
450 cl_git_pass(git_config_snapshot(&cfg
, base
));
451 cl_git_pass(git_config_get_string(&str1
, cfg
, "core.startwithspace"));
452 cl_assert_equal_s(" Something", str1
);
453 cl_git_pass(git_config_get_string(&str2
, cfg
, "core.endwithspace"));
454 cl_assert_equal_s("Something ", str2
);
455 cl_git_pass(git_config_get_string(&str3
, cfg
, "core.containscommentchar1"));
456 cl_assert_equal_s("some#thing", str3
);
457 cl_git_pass(git_config_get_string(&str4
, cfg
, "core.containscommentchar2"));
458 cl_assert_equal_s("some;thing", str4
);
459 cl_git_pass(git_config_get_string(&str5
, cfg
, "core.startwhithsapceandcontainsdoublequote"));
460 cl_assert_equal_s(" some\"thing", str5
);
461 git_config_free(cfg
);
462 git_config_free(base
);
465 void test_config_write__can_set_a_value_to_NULL(void)
467 git_repository
*repository
;
470 repository
= cl_git_sandbox_init("testrepo.git");
472 cl_git_pass(git_repository_config(&config
, repository
));
473 cl_git_fail(git_config_set_string(config
, "a.b.c", NULL
));
474 git_config_free(config
);
476 cl_git_sandbox_cleanup();
479 void test_config_write__can_set_an_empty_value(void)
481 git_repository
*repository
;
485 repository
= cl_git_sandbox_init("testrepo.git");
486 cl_git_pass(git_repository_config(&config
, repository
));
488 cl_git_pass(git_config_set_string(config
, "core.somevar", ""));
489 cl_git_pass(git_config_get_string_buf(&buf
, config
, "core.somevar"));
490 cl_assert_equal_s("", buf
.ptr
);
493 git_config_free(config
);
494 cl_git_sandbox_cleanup();
497 void test_config_write__updating_a_locked_config_file_returns_ELOCKED(void)
501 cl_git_pass(git_config_open_ondisk(&cfg
, "config9"));
503 cl_git_mkfile("config9.lock", "[core]\n");
505 cl_git_fail_with(git_config_set_string(cfg
, "core.dump", "boom"), GIT_ELOCKED
);
507 git_config_free(cfg
);
510 void test_config_write__outside_change(void)
514 const char *filename
= "config-ext-change";
516 cl_git_mkfile(filename
, "[old]\nvalue = 5\n");
518 cl_git_pass(git_config_open_ondisk(&cfg
, filename
));
520 cl_git_pass(git_config_get_int32(&tmp
, cfg
, "old.value"));
522 /* Change the value on the file itself (simulate external process) */
523 cl_git_mkfile(filename
, "[old]\nvalue = 6\n");
525 cl_git_pass(git_config_set_int32(cfg
, "new.value", 7));
527 cl_git_pass(git_config_get_int32(&tmp
, cfg
, "old.value"));
528 cl_assert_equal_i(6, tmp
);
530 git_config_free(cfg
);
533 #define FOO_COMMENT \
534 "; another comment!\n"
536 #define SECTION_FOO \
539 " [section \"foo\"] \n" \
540 " # here's a comment\n" \
541 "\tname = \"value\"\n" \
542 " name2 = \"value2\"\n" \
544 #define SECTION_FOO_WITH_COMMENT SECTION_FOO FOO_COMMENT
546 #define SECTION_BAR \
547 "[section \"bar\"]\t\n" \
549 " barname=\"value\"\n"
552 void test_config_write__preserves_whitespace_and_comments(void)
554 const char *file_name
= "config-duplicate-header";
557 git_buf newfile
= GIT_BUF_INIT
;
559 /* This config can occur after removing and re-adding the origin remote */
560 const char *file_content
= SECTION_FOO_WITH_COMMENT SECTION_BAR
;
562 /* Write the test config and make sure the expected entry exists */
563 cl_git_mkfile(file_name
, file_content
);
564 cl_git_pass(git_config_open_ondisk(&cfg
, file_name
));
565 cl_git_pass(git_config_set_string(cfg
, "section.foo.other", "otherval"));
566 cl_git_pass(git_config_set_string(cfg
, "newsection.newname", "new_value"));
568 /* Ensure that we didn't needlessly mangle the config file */
569 cl_git_pass(git_futils_readbuffer(&newfile
, file_name
));
572 cl_assert_equal_strn(SECTION_FOO
, n
, strlen(SECTION_FOO
));
573 n
+= strlen(SECTION_FOO
);
574 cl_assert_equal_strn("\tother = otherval\n", n
, strlen("\tother = otherval\n"));
575 n
+= strlen("\tother = otherval\n");
576 cl_assert_equal_strn(FOO_COMMENT
, n
, strlen(FOO_COMMENT
));
577 n
+= strlen(FOO_COMMENT
);
579 cl_assert_equal_strn(SECTION_BAR
, n
, strlen(SECTION_BAR
));
580 n
+= strlen(SECTION_BAR
);
582 cl_assert_equal_s("[newsection]\n\tnewname = new_value\n", n
);
584 git_buf_free(&newfile
);
585 git_config_free(cfg
);
588 void test_config_write__preserves_entry_with_name_only(void)
590 const char *file_name
= "config-empty-value";
592 git_buf newfile
= GIT_BUF_INIT
;
594 /* Write the test config and make sure the expected entry exists */
595 cl_git_mkfile(file_name
, "[section \"foo\"]\n\tname\n");
596 cl_git_pass(git_config_open_ondisk(&cfg
, file_name
));
597 cl_git_pass(git_config_set_string(cfg
, "newsection.newname", "new_value"));
598 cl_git_pass(git_config_set_string(cfg
, "section.foo.other", "otherval"));
600 cl_git_pass(git_futils_readbuffer(&newfile
, file_name
));
601 cl_assert_equal_s("[section \"foo\"]\n\tname\n\tother = otherval\n[newsection]\n\tnewname = new_value\n", newfile
.ptr
);
603 git_buf_free(&newfile
);
604 git_config_free(cfg
);
607 void test_config_write__to_empty_file(void)
610 const char *filename
= "config-file";
611 git_buf result
= GIT_BUF_INIT
;
613 cl_git_mkfile(filename
, "");
614 cl_git_pass(git_config_open_ondisk(&cfg
, filename
));
615 cl_git_pass(git_config_set_string(cfg
, "section.name", "value"));
616 git_config_free(cfg
);
618 cl_git_pass(git_futils_readbuffer(&result
, "config-file"));
619 cl_assert_equal_s("[section]\n\tname = value\n", result
.ptr
);
621 git_buf_free(&result
);
624 void test_config_write__to_file_with_only_comment(void)
627 const char *filename
= "config-file";
628 git_buf result
= GIT_BUF_INIT
;
630 cl_git_mkfile(filename
, "\n\n");
631 cl_git_pass(git_config_open_ondisk(&cfg
, filename
));
632 cl_git_pass(git_config_set_string(cfg
, "section.name", "value"));
633 git_config_free(cfg
);
635 cl_git_pass(git_futils_readbuffer(&result
, "config-file"));
636 cl_assert_equal_s("\n\n[section]\n\tname = value\n", result
.ptr
);
638 git_buf_free(&result
);
641 void test_config_write__locking(void)
643 git_config
*cfg
, *cfg2
;
644 git_config_entry
*entry
;
646 const char *filename
= "locked-file";
648 /* Open the config and lock it */
649 cl_git_mkfile(filename
, "[section]\n\tname = value\n");
650 cl_git_pass(git_config_open_ondisk(&cfg
, filename
));
651 cl_git_pass(git_config_get_entry(&entry
, cfg
, "section.name"));
652 cl_assert_equal_s("value", entry
->value
);
653 git_config_entry_free(entry
);
654 cl_git_pass(git_config_lock(&tx
, cfg
));
656 /* Change entries in the locked backend */
657 cl_git_pass(git_config_set_string(cfg
, "section.name", "other value"));
658 cl_git_pass(git_config_set_string(cfg
, "section2.name3", "more value"));
660 /* We can see that the file we read from hasn't changed */
661 cl_git_pass(git_config_open_ondisk(&cfg2
, filename
));
662 cl_git_pass(git_config_get_entry(&entry
, cfg2
, "section.name"));
663 cl_assert_equal_s("value", entry
->value
);
664 git_config_entry_free(entry
);
665 cl_git_fail_with(GIT_ENOTFOUND
, git_config_get_entry(&entry
, cfg2
, "section2.name3"));
666 git_config_free(cfg2
);
668 /* And we also get the old view when we read from the locked config */
669 cl_git_pass(git_config_get_entry(&entry
, cfg
, "section.name"));
670 cl_assert_equal_s("value", entry
->value
);
671 git_config_entry_free(entry
);
672 cl_git_fail_with(GIT_ENOTFOUND
, git_config_get_entry(&entry
, cfg
, "section2.name3"));
674 cl_git_pass(git_transaction_commit(tx
));
675 git_transaction_free(tx
);
677 /* Now that we've unlocked it, we should see both updates */
678 cl_git_pass(git_config_get_entry(&entry
, cfg
, "section.name"));
679 cl_assert_equal_s("other value", entry
->value
);
680 git_config_entry_free(entry
);
681 cl_git_pass(git_config_get_entry(&entry
, cfg
, "section2.name3"));
682 cl_assert_equal_s("more value", entry
->value
);
683 git_config_entry_free(entry
);
685 git_config_free(cfg
);
687 /* We should also see the changes after reopening the config */
688 cl_git_pass(git_config_open_ondisk(&cfg
, filename
));
689 cl_git_pass(git_config_get_entry(&entry
, cfg
, "section.name"));
690 cl_assert_equal_s("other value", entry
->value
);
691 git_config_entry_free(entry
);
692 cl_git_pass(git_config_get_entry(&entry
, cfg
, "section2.name3"));
693 cl_assert_equal_s("more value", entry
->value
);
694 git_config_entry_free(entry
);
696 git_config_free(cfg
);
699 void test_config_write__repeated(void)
701 const char *filename
= "config-repeated";
703 git_buf result
= GIT_BUF_INIT
;
704 const char *expected
= "[sample \"prefix\"]\n\
705 \tsetting1 = someValue1\n\
706 \tsetting2 = someValue2\n\
707 \tsetting3 = someValue3\n\
708 \tsetting4 = someValue4\n\
710 cl_git_pass(git_config_open_ondisk(&cfg
, filename
));
711 cl_git_pass(git_config_set_string(cfg
, "sample.prefix.setting1", "someValue1"));
712 cl_git_pass(git_config_set_string(cfg
, "sample.prefix.setting2", "someValue2"));
713 cl_git_pass(git_config_set_string(cfg
, "sample.prefix.setting3", "someValue3"));
714 cl_git_pass(git_config_set_string(cfg
, "sample.prefix.setting4", "someValue4"));
715 git_config_free(cfg
);
717 cl_git_pass(git_config_open_ondisk(&cfg
, filename
));
719 cl_git_pass(git_futils_readbuffer(&result
, filename
));
720 cl_assert_equal_s(expected
, result
.ptr
);
721 git_buf_free(&result
);
723 git_config_free(cfg
);