Skip to content

Commit 4bf136b

Browse files
author
Nicolas Cavallari
committed
config: fix included configs not refreshed more than once
If an included config is refreshed twice, the second update is not taken into account. This is because the list of included files is cleared after re-reading the new configuration, instead of being cleared before. Fix it and add a test case to check for this bug.
1 parent 0d0150d commit 4bf136b

File tree

2 files changed

+38
-6
lines changed

2 files changed

+38
-6
lines changed

src/config_file.c

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -164,23 +164,27 @@ static int config_file_is_modified(int *modified, config_file *file)
164164
return error;
165165
}
166166

167+
static void config_file_clear_includes(config_file_backend* cfg)
168+
{
169+
config_file *include;
170+
uint32_t i;
171+
172+
git_array_foreach(cfg->file.includes, i, include)
173+
config_file_clear(include);
174+
git_array_clear(cfg->file.includes);
175+
}
176+
167177
static int config_file_set_entries(git_config_backend *cfg, git_config_entries *entries)
168178
{
169179
config_file_backend *b = GIT_CONTAINER_OF(cfg, config_file_backend, parent);
170180
git_config_entries *old = NULL;
171-
config_file *include;
172181
int error;
173-
uint32_t i;
174182

175183
if (b->parent.readonly) {
176184
git_error_set(GIT_ERROR_CONFIG, "this backend is read-only");
177185
return -1;
178186
}
179187

180-
git_array_foreach(b->file.includes, i, include)
181-
config_file_clear(include);
182-
git_array_clear(b->file.includes);
183-
184188
if ((error = git_mutex_lock(&b->values_mutex)) < 0) {
185189
git_error_set(GIT_ERROR_OS, "failed to lock config backend");
186190
goto out;
@@ -202,6 +206,8 @@ static int config_file_refresh_from_buffer(git_config_backend *cfg, const char *
202206
git_config_entries *entries = NULL;
203207
int error;
204208

209+
config_file_clear_includes(b);
210+
205211
if ((error = git_config_entries_new(&entries)) < 0 ||
206212
(error = config_file_read_buffer(entries, b->repo, &b->file,
207213
b->level, 0, buf, buflen)) < 0 ||
@@ -229,6 +235,8 @@ static int config_file_refresh(git_config_backend *cfg)
229235
if (!modified)
230236
return 0;
231237

238+
config_file_clear_includes(b);
239+
232240
if ((error = git_config_entries_new(&entries)) < 0 ||
233241
(error = config_file_read(entries, b->repo, &b->file, b->level, 0)) < 0 ||
234242
(error = config_file_set_entries(cfg, entries)) < 0)

tests/config/include.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,30 @@ void test_config_include__rewriting_include_refreshes_values(void)
178178
cl_git_pass(p_unlink("second"));
179179
}
180180

181+
void test_config_include__rewriting_include_twice_refreshes_values(void)
182+
{
183+
cl_git_mkfile("top-level", "[include]\npath = included");
184+
cl_git_mkfile("included", "[foo]\nbar = first-value");
185+
186+
cl_git_pass(git_config_open_ondisk(&cfg, "top-level"));
187+
cl_git_pass(git_config_get_string_buf(&buf, cfg, "foo.bar"));
188+
189+
git_buf_clear(&buf);
190+
cl_git_mkfile("included", "[foo]\nother = value2");
191+
cl_git_fail(git_config_get_string_buf(&buf, cfg, "foo.bar"));
192+
cl_git_pass(git_config_get_string_buf(&buf, cfg, "foo.other"));
193+
cl_assert_equal_s(buf.ptr, "value2");
194+
195+
git_buf_clear(&buf);
196+
cl_git_mkfile("included", "[foo]\nanother = bar");
197+
cl_git_fail(git_config_get_string_buf(&buf, cfg, "foo.other"));
198+
cl_git_pass(git_config_get_string_buf(&buf, cfg, "foo.another"));
199+
cl_assert_equal_s(buf.ptr, "bar");
200+
201+
cl_git_pass(p_unlink("top-level"));
202+
cl_git_pass(p_unlink("included"));
203+
}
204+
181205
void test_config_include__included_variables_cannot_be_deleted(void)
182206
{
183207
cl_git_mkfile("top-level", "[include]\npath = included\n");

0 commit comments

Comments
 (0)