diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh index a3a21c54cf63aa..f3e720dc10da46 100755 --- a/t/t3200-branch.sh +++ b/t/t3200-branch.sh @@ -410,6 +410,20 @@ test_expect_success 'bare main worktree has HEAD at branch deleted by secondary git -C secondary branch -D main ' +test_expect_success 'secondary worktrees recognize core.bare=true in main config.worktree' ' + test_when_finished "rm -rf bare_repo non_bare_repo secondary_worktree" && + git init -b main non_bare_repo && + test_commit -C non_bare_repo x && + + git clone --bare non_bare_repo bare_repo && + git -C bare_repo config extensions.worktreeConfig true && + git -C bare_repo config unset core.bare && + git -C bare_repo config --worktree core.bare true && + + git -C bare_repo worktree add ../secondary_worktree && + git -C secondary_worktree checkout main +' + test_expect_success 'git branch --list -v with --abbrev' ' test_when_finished "git branch -D t" && git branch t && diff --git a/worktree.c b/worktree.c index 248bbb39d43ae8..6df4ccf97f7817 100644 --- a/worktree.c +++ b/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// +* 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,11 @@ 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() || + (!worktree->is_current && is_main_worktree_bare(the_repository)); + if (!skip_reading_head) add_head_info(worktree); return worktree;