Skip to content

Commit 6589541

Browse files
committed
repository: retrieve worktree HEAD via refdb
The function `git_repository_head_for_worktree` currently uses `git_reference__read_head` to directly read a given worktree's HEAD from the filesystem. This is broken in case the repository uses a different refdb implementation than the filesystem-based one, so let's instead open the worktree as a real repository and use `git_reference_lookup`. This also fixes the case where the worktree's HEAD is not a symref, but a detached HEAD, which would have resulted in an error previously.
1 parent d1f210f commit 6589541

File tree

2 files changed

+17
-22
lines changed

2 files changed

+17
-22
lines changed

src/repository.c

Lines changed: 13 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2177,12 +2177,6 @@ int git_repository_head_detached(git_repository *repo)
21772177
return exists;
21782178
}
21792179

2180-
static int get_worktree_file_path(git_buf *out, git_repository *repo, const char *worktree, const char *file)
2181-
{
2182-
git_buf_clear(out);
2183-
return git_buf_printf(out, "%s/worktrees/%s/%s", repo->commondir, worktree, file);
2184-
}
2185-
21862180
int git_repository_head_detached_for_worktree(git_repository *repo, const char *name)
21872181
{
21882182
git_reference *ref = NULL;
@@ -2223,34 +2217,32 @@ int git_repository_head(git_reference **head_out, git_repository *repo)
22232217

22242218
int git_repository_head_for_worktree(git_reference **out, git_repository *repo, const char *name)
22252219
{
2226-
git_buf path = GIT_BUF_INIT;
2220+
git_repository *worktree_repo = NULL;
2221+
git_worktree *worktree = NULL;
22272222
git_reference *head = NULL;
22282223
int error;
22292224

22302225
assert(out && repo && name);
22312226

22322227
*out = NULL;
22332228

2234-
if ((error = get_worktree_file_path(&path, repo, name, GIT_HEAD_FILE)) < 0 ||
2235-
(error = git_reference__read_head(&head, repo, path.ptr)) < 0)
2229+
if ((error = git_worktree_lookup(&worktree, repo, name)) < 0 ||
2230+
(error = git_repository_open_from_worktree(&worktree_repo, worktree)) < 0 ||
2231+
(error = git_reference_lookup(&head, worktree_repo, GIT_HEAD_FILE)) < 0)
22362232
goto out;
22372233

22382234
if (git_reference_type(head) != GIT_REFERENCE_DIRECT) {
2239-
git_reference *resolved;
2240-
2241-
error = git_reference_lookup_resolved(&resolved, repo, git_reference_symbolic_target(head), -1);
2242-
git_reference_free(head);
2243-
head = resolved;
2235+
if ((error = git_reference_lookup_resolved(out, worktree_repo, git_reference_symbolic_target(head), -1)) < 0)
2236+
goto out;
2237+
} else {
2238+
*out = head;
2239+
head = NULL;
22442240
}
22452241

2246-
*out = head;
2247-
22482242
out:
2249-
if (error)
2250-
git_reference_free(head);
2251-
2252-
git_buf_dispose(&path);
2253-
2243+
git_reference_free(head);
2244+
git_worktree_free(worktree);
2245+
git_repository_free(worktree_repo);
22542246
return error;
22552247
}
22562248

tests/worktree/repository.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,12 @@ void test_worktree_repository__head_detached(void)
5050

5151
cl_assert(git_repository_head_detached(fixture.worktree));
5252
cl_assert(git_repository_head_detached_for_worktree(fixture.repo, "testrepo-worktree"));
53-
cl_git_fail(git_repository_head_for_worktree(&head, fixture.repo, "testrepo-worktree"));
53+
cl_git_pass(git_repository_head_for_worktree(&head, fixture.repo, "testrepo-worktree"));
54+
55+
cl_assert_equal_oid(&ref->target.oid, &head->target.oid);
5456

5557
git_reference_free(ref);
58+
git_reference_free(head);
5659
}
5760

5861
void test_worktree_repository__head_detached_fails_for_invalid_worktree(void)

0 commit comments

Comments
 (0)