Re: [PATCH v3 2/5] config: read protected config with `git_protected_config()`
- From
Derrick Stolee <derrickstolee@github.com>
- Date
- Jun 2, 2022, 12:56 UTC
- Message-ID
- <802c3541-3301-43fc-c39e-edd44e61a4eb@github.com>
- In-Reply-To
- <7499a2809615d42eaf3649e1c33f38d099d27c1a.1653685761.git.gitgitgadget@gmail.com>
On 5/27/2022 5:09 PM, Glen Choo via GitGitGadget wrote:
Show 25 quoted lines
> From: Glen Choo <chooglen@google.com> > > Protected config is read using `read_very_early_config()`, which has > several downsides: > > - Every call to `read_very_early_config()` parses global and > system-level config files anew, but this can be optimized by just > parsing them once [1]. > - Protected variables should respect "-c" because we can reasonably > assume that it comes from the user. But, `read_very_early_config()` > can't use "-c" because it is called so early that it does not have > access to command line arguments. > > Introduce `git_protected_config()`, which reads protected config and > caches the values in `the_repository.protected_config`. Then, refactor > `safe.directory` to use `git_protected_config()`. > > This implementation can still be improved, however: > > - `git_protected_config()` iterates through every variable in > `the_repository.protected_config`, which may still be too expensive to > be called in every "git" invocation. There exist constant time lookup > functions for non-protected config (repo_config_get_*()), but for > simplicity, this commit does not implement similar functions for > protected config.
I originally thought that we should jump to that "right" solution, but the existing logic in ensure_valid_ownership() uses the iterator method, mostly because it uses a multi-valued string. There are helpers that allow iterating over a specific multi-valued key, but there is no reason to complicate the current patch with that amount of refactoring. That can be handled as a completely separate topic.
> - Protected config is stored in `the_repository` so that we don't need > to statically allocate it. But this might be confusing since protected > config ignores repository config by definition.
I agree with Junio's suggestion of keeping this as a static global in config.c, accessible only by the public methods from config.h. A future where we have "the_world" might be nice for inventory on all these globals. Definitely not something to hold up this series.
Show 19 quoted lines
> +/* Read protected config into the_repository->protected_config. */
> +static void read_protected_config(void)
> +{
> + char *xdg_config = NULL, *user_config = NULL, *system_config = NULL;
> +
> + CALLOC_ARRAY(the_repository->protected_config, 1);
> + git_configset_init(the_repository->protected_config);
> +
> + system_config = git_system_config();
> + git_global_config(&user_config, &xdg_config);
> +
> + git_configset_add_file(the_repository->protected_config, system_config);
> + git_configset_add_file(the_repository->protected_config, xdg_config);
> + git_configset_add_file(the_repository->protected_config, user_config);
> +
> + free(system_config);
> + free(xdg_config);
> + free(user_config);
> +}This loads the config from three files, including the xdg_config, which I wasn't thinking about before.
This implementation does not use the -c config yet, which you listed as a downside of read_very_early_config(). I see that you include that in your patch 4, but the commit message for this patch could list that as a step that will be handled by a later change.
(You could also do that as patch 3 and add a test near the existing safe.directory tests instead of waiting for discovery.bare.)
Show 15 quoted lines
> +
> +/* Ensure that the_repository->protected_config has been initialized. */
> +static void git_protected_config_check_init(void)
> +{
> + if (the_repository->protected_config &&
> + the_repository->protected_config->hash_initialized)
> + return;
> + read_protected_config();
> +}
> +
> +void git_protected_config(config_fn_t fn, void *data)
> +{
> + git_protected_config_check_init();
> + configset_iter(the_repository->protected_config, fn, data);
> +}These two methods are clearly correct.
..._check_init() is an OK name. I've seen us use "prepare_...()" in other areas as a way of making sure that we have the proper state (see prepare_packed_git() and the like), so maybe a rename here to match would be worthwhile. Feel free to ignore.
> + if (repo->protected_config) {
> + git_configset_clear(repo->protected_config);
> + FREE_AND_NULL(repo->protected_config);
> + }This will have no equivalent when protected_config is left as a static global, but that is fine. It only goes out of scope with the end of the process, anyway.
Show 6 quoted lines
> @@ -1128,7 +1128,7 @@ static int ensure_valid_ownership(const char *path) > is_path_owned_by_current_user(path)) > return 1; > > - read_very_early_config(safe_directory_cb, &data); > + git_protected_config(safe_directory_cb, &data);
Nice to have a very simple conversion here.
Thanks, -Stolee