@@ -411,6 +411,20 @@ test_expect_success 'bare main worktree has HEAD at branch deleted by secondary
git -C secondary branch -D main
'
+test_expect_success 'secondary worktree can switch to main if common dir is bare 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 &&
@@ -64,6 +64,28 @@ static int is_current_worktree(struct worktree *wt)
return is_current;
}
+static int is_bare_git_dir(const char *git_dir)
+{
+ int bare = 0;
+ struct config_set cs = { { 0 } };
+ char *config_file;
+ char *worktree_config_file;
+
+ config_file = xstrfmt("%s/config", git_dir);
+ worktree_config_file = xstrfmt("%s/config.worktree", git_dir);
+
+ git_configset_init(&cs);
+ git_configset_add_file(&cs, config_file);
+ git_configset_add_file(&cs, worktree_config_file);
+
+ git_configset_get_bool(&cs, "core.bare", &bare);
+
+ git_configset_clear(&cs);
+ free(config_file);
+ free(worktree_config_file);
+ return bare;
+}
+
/**
* get the main worktree
*/
@@ -76,18 +98,16 @@ static struct worktree *get_main_worktree(int skip_reading_head)
strbuf_strip_suffix(&worktree_path, "/.git");
CALLOC_ARRAY(worktree, 1);
+ /*
+ * NEEDSWORK: the_repository is not always main worktree's repository
+ */
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_bare_git_dir(repo_get_common_dir(the_repository)));
+
if (!skip_reading_head)
add_head_info(worktree);
return worktree;