diff mbox series

[RFC,v2,2/4] config: load the correct config.worktree file

Message ID 882310b69fd3df0acc6823a2c73bbe1801d9f6c4.1589058209.git.matheus.bernardino@usp.br (mailing list archive)
State New, archived
Headers show
Series grep: honor sparse checkout and add option to ignore it | expand

Commit Message

Matheus Tavares May 10, 2020, 12:41 a.m. UTC
One of the steps in do_git_config_sequence() is to load the
worktree-specific config file. Although the function receives a git_dir
string, it relies on git_pathdup(), which uses the_repository->git_dir,
to make the path to the file. Thus, when a submodule has a worktree
setting, a command executed in the superproject that recurses into the
submodule won't find the said setting. Such a scenario might not be
needed now, but it will be in the following patch. git-grep will learn
to honor sparse checkouts and, when running with --recurse-submodules,
the submodule's sparse checkout settings must be loaded. As these
settings are stored in the config.worktree file, they would be ignored
without this patch.

The fix is simple, we replace git_pathdup() with mkpathdup(), to format
the path with the given git_dir. This is the same idea used to make the
config.worktree path in setup.c:check_repository_format_gently().

Signed-off-by: Matheus Tavares <matheus.bernardino@usp.br>
---
 config.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

Comments

Junio C Hamano May 11, 2020, 7:10 p.m. UTC | #1
Matheus Tavares <matheus.bernardino@usp.br> writes:

> One of the steps in do_git_config_sequence() is to load the
> worktree-specific config file. Although the function receives a git_dir
> string, it relies on git_pathdup(), which uses the_repository->git_dir,
> to make the path to the file. Thus, when a submodule has a worktree
> setting, a command executed in the superproject that recurses into the
> submodule won't find the said setting.

This has far wider ramifications than just "git grep" and it may be
an important fix.  Anything that wants to read from a per-worktree
configuration is not working as expected when run from a secondary
worktree, right?

Can we add a test or two to protect this fix from future breakages?


>  	current_parsing_scope = CONFIG_SCOPE_WORKTREE;
> -	if (!opts->ignore_worktree && repository_format_worktree_config) {
> -		char *path = git_pathdup("config.worktree");
> +	if (!opts->ignore_worktree && repository_format_worktree_config &&
> +	    opts->git_dir) {
> +		char *path = mkpathdup("%s/config.worktree", opts->git_dir);
>  		if (!access_or_die(path, R_OK, 0))
>  			ret += git_config_from_file(fn, path, data);
>  		free(path);
Matheus Tavares May 12, 2020, 10:55 p.m. UTC | #2
On Mon, May 11, 2020 at 4:10 PM Junio C Hamano <gitster@pobox.com> wrote:
>
> Matheus Tavares <matheus.bernardino@usp.br> writes:
>
> > One of the steps in do_git_config_sequence() is to load the
> > worktree-specific config file. Although the function receives a git_dir
> > string, it relies on git_pathdup(), which uses the_repository->git_dir,
> > to make the path to the file. Thus, when a submodule has a worktree
> > setting, a command executed in the superproject that recurses into the
> > submodule won't find the said setting.
>
> This has far wider ramifications than just "git grep" and it may be
> an important fix.  Anything that wants to read from a per-worktree
> configuration is not working as expected when run from a secondary
> worktree, right?

Hmm, I think the code should be able to retrieve the per-worktree
configuration, in this case, as the_repository->gitdir will be
pointing to the secondary worktree's gitdir. But when we want to read
a per-worktree configuration from a repo other than the_repository,
then the code doesn't find the setting (even if it is in the main
worktree of the subrepo).

> Can we add a test or two to protect this fix from future breakages?

Sure! There are already a couple tests, in the following patch, that
check this behavior *indirectly*. As we recurse into submodules, in
grep, we try to retrieve the core.sparseCheckout setting for each
submodule (which is stored in the subrepo's config.worktree file). The
said tests make sure we can get this setting, and they indeed fail
without this patch. But would it be better to also add a more direct
test, in this patch? I think we could do so by adding a new test
helper that prints submodules' configs, from the superproject, and
then testing the presence of per-worktree configs in the output.
Junio C Hamano May 12, 2020, 11:22 p.m. UTC | #3
Matheus Tavares Bernardino <matheus.bernardino@usp.br> writes:

>> Can we add a test or two to protect this fix from future breakages?
>
> Sure! There are already a couple tests, in the following patch, that
> check this behavior *indirectly*. As we recurse into submodules, in
> grep, we try to retrieve the core.sparseCheckout setting for each
> submodule (which is stored in the subrepo's config.worktree file). The
> said tests make sure we can get this setting, and they indeed fail
> without this patch. But would it be better to also add a more direct
> test, in this patch? I think we could do so by adding a new test
> helper that prints submodules' configs, from the superproject, and
> then testing the presence of per-worktree configs in the output.

Sounds like a plan.  Yes, checking by observing how grep that
recurses into submodules behave is doable but is indirect, and if
any other subcommand that may want to do the recursion will have the
same issue that gets fixed by this patch, it's better to ensure that
the fix applies to any subcommand in a more direct way.

Thanks.
diff mbox series

Patch

diff --git a/config.c b/config.c
index 8db9c77098..a3d0a0d266 100644
--- a/config.c
+++ b/config.c
@@ -1747,8 +1747,9 @@  static int do_git_config_sequence(const struct config_options *opts,
 		ret += git_config_from_file(fn, repo_config, data);
 
 	current_parsing_scope = CONFIG_SCOPE_WORKTREE;
-	if (!opts->ignore_worktree && repository_format_worktree_config) {
-		char *path = git_pathdup("config.worktree");
+	if (!opts->ignore_worktree && repository_format_worktree_config &&
+	    opts->git_dir) {
+		char *path = mkpathdup("%s/config.worktree", opts->git_dir);
 		if (!access_or_die(path, R_OK, 0))
 			ret += git_config_from_file(fn, path, data);
 		free(path);