mirror of
https://github.com/git/git.git
synced 2026-01-09 01:34:00 +00:00
worktree: detect from secondary worktree if main worktree is bare
When extensions.worktreeConfig is true and the main worktree is bare -- that is, its config.worktree file contains core.bare=true -- commands run from secondary worktrees incorrectly see the main worktree as not bare. As such, those commands incorrectly think that the repository's default branch (typically "main" or "master") is checked out in the bare repository even though it's not. This makes it impossible, for instance, to checkout or delete the default branch from a secondary worktree, among other shortcomings. This problem occurs because, when extensions.worktreeConfig is true, commands run in secondary worktrees only consult $commondir/config and $commondir/worktrees/<id>/config.worktree, thus they never see the main worktree's core.bare=true setting in $commondir/config.worktree. Fix this problem by consulting the main worktree's config.worktree file when checking whether it is bare. (This extra work is performed only when running from a secondary worktree.) Helped-by: Eric Sunshine <sunshine@sunshineco.com> Signed-off-by: Olga Pilipenco <olga.pilipenco@shopify.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
committed by
Junio C Hamano
parent
58b5801aa9
commit
78a95e0d80
41
worktree.c
41
worktree.c
@@ -65,6 +65,28 @@ static int is_current_worktree(struct worktree *wt)
|
||||
return is_current;
|
||||
}
|
||||
|
||||
/*
|
||||
* When in a secondary worktree, and when extensions.worktreeConfig
|
||||
* is true, only $commondir/config and $commondir/worktrees/<id>/
|
||||
* config.worktree are consulted, hence any core.bare=true setting in
|
||||
* $commondir/config.worktree gets overlooked. Thus, check it manually
|
||||
* to determine if the repository is bare.
|
||||
*/
|
||||
static int is_main_worktree_bare(struct repository *repo)
|
||||
{
|
||||
int bare = 0;
|
||||
struct config_set cs = {0};
|
||||
char *worktree_config = xstrfmt("%s/config.worktree", repo_get_common_dir(repo));
|
||||
|
||||
git_configset_init(&cs);
|
||||
git_configset_add_file(&cs, worktree_config);
|
||||
git_configset_get_bool(&cs, "core.bare", &bare);
|
||||
|
||||
git_configset_clear(&cs);
|
||||
free(worktree_config);
|
||||
return bare;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the main worktree
|
||||
*/
|
||||
@@ -79,16 +101,17 @@ static struct worktree *get_main_worktree(int skip_reading_head)
|
||||
CALLOC_ARRAY(worktree, 1);
|
||||
worktree->repo = the_repository;
|
||||
worktree->path = strbuf_detach(&worktree_path, NULL);
|
||||
/*
|
||||
* NEEDSWORK: If this function is called from a secondary worktree and
|
||||
* config.worktree is present, is_bare_repository_cfg will reflect the
|
||||
* contents of config.worktree, not the contents of the main worktree.
|
||||
* This means that worktree->is_bare may be set to 0 even if the main
|
||||
* worktree is configured to be bare.
|
||||
*/
|
||||
worktree->is_bare = (is_bare_repository_cfg == 1) ||
|
||||
is_bare_repository();
|
||||
worktree->is_current = is_current_worktree(worktree);
|
||||
worktree->is_bare = (is_bare_repository_cfg == 1) ||
|
||||
is_bare_repository() ||
|
||||
/*
|
||||
* When in a secondary worktree we have to also verify if the main
|
||||
* worktree is bare in $commondir/config.worktree.
|
||||
* This check is unnecessary if we're currently in the main worktree,
|
||||
* as prior checks already consulted all configs of the current worktree.
|
||||
*/
|
||||
(!worktree->is_current && is_main_worktree_bare(the_repository));
|
||||
|
||||
if (!skip_reading_head)
|
||||
add_head_info(worktree);
|
||||
return worktree;
|
||||
|
||||
Reference in New Issue
Block a user