config_file: refresh when creating an iterator When creating a new iterator for a config file backend, then we should always make sure that we're up to date by calling `config_refresh`. Otherwise, we might not notice when another process has modified the configuration file and thus will represent outdated values. Add two tests to config::stress that verify that we get up-to-date values when reading configuration entries via `git_config_iterator`.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
diff --git a/src/config_file.c b/src/config_file.c
index 1b674b1..88bba90 100644
--- a/src/config_file.c
+++ b/src/config_file.c
@@ -270,13 +270,12 @@ static int config_iterator_new(
struct git_config_backend *backend)
{
diskfile_header *bh = GIT_CONTAINER_OF(backend, diskfile_header, parent);
- git_config_entries *entries;
+ git_config_entries *entries = NULL;
int error;
- if ((error = git_config_entries_dup(&entries, bh->entries)) < 0)
- return error;
-
- if ((error = git_config_entries_iterator_new(iter, entries)) < 0)
+ if ((error = config_refresh(backend)) < 0 ||
+ (error = git_config_entries_dup(&entries, bh->entries)) < 0 ||
+ (error = git_config_entries_iterator_new(iter, entries)) < 0)
goto out;
out:
diff --git a/tests/config/stress.c b/tests/config/stress.c
index 4fb0f3b..4ee234f 100644
--- a/tests/config/stress.c
+++ b/tests/config/stress.c
@@ -131,3 +131,48 @@ void test_config_stress__quick_write(void)
git_config_free(config_r);
git_config_free(config_w);
}
+
+static int foreach_cb(const git_config_entry *entry, void *payload)
+{
+ if (!strcmp(entry->name, "key.value")) {
+ *(char **)payload = git__strdup(entry->value);
+ return 0;
+ }
+ return -1;
+}
+
+void test_config_stress__foreach_refreshes(void)
+{
+ git_config *config_w, *config_r;
+ char *value = NULL;
+
+ cl_git_pass(git_config_open_ondisk(&config_w, "./cfg"));
+ cl_git_pass(git_config_open_ondisk(&config_r, "./cfg"));
+
+ cl_git_pass(git_config_set_string(config_w, "key.value", "1"));
+ cl_git_pass(git_config_foreach_match(config_r, "key.value", foreach_cb, &value));
+
+ cl_assert_equal_s(value, "1");
+
+ git_config_free(config_r);
+ git_config_free(config_w);
+ git__free(value);
+}
+
+void test_config_stress__foreach_refreshes_snapshot(void)
+{
+ git_config *config, *snapshot;
+ char *value = NULL;
+
+ cl_git_pass(git_config_open_ondisk(&config, "./cfg"));
+
+ cl_git_pass(git_config_set_string(config, "key.value", "1"));
+ cl_git_pass(git_config_snapshot(&snapshot, config));
+ cl_git_pass(git_config_foreach_match(snapshot, "key.value", foreach_cb, &value));
+
+ cl_assert_equal_s(value, "1");
+
+ git_config_free(snapshot);
+ git_config_free(config);
+ git__free(value);
+}