diff --git a/src/libgit2/config.c b/src/libgit2/config.c index e67839c36..732d10830 100644 --- a/src/libgit2/config.c +++ b/src/libgit2/config.c @@ -593,12 +593,14 @@ static int get_backend_for_use(git_config_backend **out, git_config *cfg, const char *name, backend_use use) { size_t i; + size_t len; backend_internal *backend; int error = 0; *out = NULL; - if (git_vector_length(&cfg->backends) == 0) { + len = git_vector_length(&cfg->backends); + if (len == 0) { git_error_set(GIT_ERROR_CONFIG, "cannot %s value for '%s' when no config backends exist", uses[use], name); @@ -609,6 +611,15 @@ static int get_backend_for_use(git_config_backend **out, if (backend->backend->readonly) continue; + /* git-config doesn't update worktree-level config + unless specifically requested; follow suit. If you + specifically want to update that level, open the + single config level with git_config_open_level and + provide that as the config. In this case, there + will only be one backend in the config. */ + if (len > 1 && backend->level == GIT_CONFIG_LEVEL_WORKTREE) + continue; + *out = backend->backend; goto cleanup; } diff --git a/tests/libgit2/worktree/config.c b/tests/libgit2/worktree/config.c index 81dcfe1fa..c23cd044f 100644 --- a/tests/libgit2/worktree/config.c +++ b/tests/libgit2/worktree/config.c @@ -27,7 +27,7 @@ void test_worktree_config__open(void) git_config_free(cfg); } -void test_worktree_config__set(void) +void test_worktree_config__set_level_local(void) { git_config *cfg; int32_t val; @@ -45,3 +45,31 @@ void test_worktree_config__set(void) cl_assert_equal_i(val, 5); git_config_free(cfg); } + +void test_worktree_config__set_level_worktree(void) +{ + git_config *cfg; + git_config *wtcfg; + int32_t val; + + cl_git_pass(git_repository_config(&cfg, fixture.repo)); + cl_git_pass(git_config_open_level(&wtcfg, cfg, GIT_CONFIG_LEVEL_WORKTREE)); + cl_git_pass(git_config_set_int32(wtcfg, "worktree.specific", 42)); + + cl_git_pass(git_config_get_int32(&val, cfg, "worktree.specific")); + cl_assert_equal_i(val, 42); + + /* reopen to verify config has been set */ + git_config_free(cfg); + cl_git_pass(git_repository_config(&cfg, fixture.repo)); + cl_git_pass(git_config_get_int32(&val, cfg, "worktree.specific")); + cl_assert_equal_i(val, 42); + + cl_assert(git_config_delete_entry(cfg, "worktree.specific") == GIT_ENOTFOUND); + + cl_git_pass(git_config_delete_entry(wtcfg, "worktree.specific")); + cl_assert(git_config_get_int32(&val, cfg, "worktree.specific") == GIT_ENOTFOUND); + + git_config_free(cfg); + git_config_free(wtcfg); +}