config: skip worktree config in get_backend_for_use

It would seem that `get_backend_for_use` is primarily used when
writing config data -- either to set keys or delete them (based on the
possible values of `backend_use`). When git-config(1) is used for
side-effects, it will modify only the local (repository-level)
configuration unless explicitly overridden.

From git-config(1):

    --local
        For writing options: write to the repository .git/config file.
	This is the default behavior.

`get_backend_for_use` does not have the ability to specify a config
level and typically is expected (it seems) to 'do the right thing'.
Taking its cue from git-config(1), don't update worktree-specific
config unless it's the only option.

If that functionality is needed by consumers, I assume they would find
the appropriate backend with `git_config_open_level` and feed that
`git_config` object through to the `git_config_set_*` functions (as
demonstrated in the provided test).
This commit is contained in:
Sean Allred
2024-02-20 21:39:11 -06:00
parent 42e7e681de
commit ea66ab0773
2 changed files with 41 additions and 2 deletions

View File

@@ -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;
}

View File

@@ -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);
}