diff options
author | Patrick Steinhardt <ps@pks.im> | 2020-06-17 14:56:36 +0200 |
---|---|---|
committer | Patrick Steinhardt <ps@pks.im> | 2020-07-12 18:12:16 +0200 |
commit | 658954100c138fa28222f5cb3198d9f1335fa556 (patch) | |
tree | 7f938f8cb3114294f34bca1e10fd49b4eae19050 | |
parent | d1f210fc323b501b9f9a3a8872b05ce76525a4e1 (diff) | |
download | libgit2-658954100c138fa28222f5cb3198d9f1335fa556.tar.gz |
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.
-rw-r--r-- | src/repository.c | 34 | ||||
-rw-r--r-- | tests/worktree/repository.c | 5 |
2 files changed, 17 insertions, 22 deletions
diff --git a/src/repository.c b/src/repository.c index 89d8ab132..ebb9daa01 100644 --- a/src/repository.c +++ b/src/repository.c @@ -2177,12 +2177,6 @@ int git_repository_head_detached(git_repository *repo) return exists; } -static int get_worktree_file_path(git_buf *out, git_repository *repo, const char *worktree, const char *file) -{ - git_buf_clear(out); - return git_buf_printf(out, "%s/worktrees/%s/%s", repo->commondir, worktree, file); -} - int git_repository_head_detached_for_worktree(git_repository *repo, const char *name) { git_reference *ref = NULL; @@ -2223,7 +2217,8 @@ int git_repository_head(git_reference **head_out, git_repository *repo) int git_repository_head_for_worktree(git_reference **out, git_repository *repo, const char *name) { - git_buf path = GIT_BUF_INIT; + git_repository *worktree_repo = NULL; + git_worktree *worktree = NULL; git_reference *head = NULL; int error; @@ -2231,26 +2226,23 @@ int git_repository_head_for_worktree(git_reference **out, git_repository *repo, *out = NULL; - if ((error = get_worktree_file_path(&path, repo, name, GIT_HEAD_FILE)) < 0 || - (error = git_reference__read_head(&head, repo, path.ptr)) < 0) + if ((error = git_worktree_lookup(&worktree, repo, name)) < 0 || + (error = git_repository_open_from_worktree(&worktree_repo, worktree)) < 0 || + (error = git_reference_lookup(&head, worktree_repo, GIT_HEAD_FILE)) < 0) goto out; if (git_reference_type(head) != GIT_REFERENCE_DIRECT) { - git_reference *resolved; - - error = git_reference_lookup_resolved(&resolved, repo, git_reference_symbolic_target(head), -1); - git_reference_free(head); - head = resolved; + if ((error = git_reference_lookup_resolved(out, worktree_repo, git_reference_symbolic_target(head), -1)) < 0) + goto out; + } else { + *out = head; + head = NULL; } - *out = head; - out: - if (error) - git_reference_free(head); - - git_buf_dispose(&path); - + git_reference_free(head); + git_worktree_free(worktree); + git_repository_free(worktree_repo); return error; } diff --git a/tests/worktree/repository.c b/tests/worktree/repository.c index ca56413b7..c4eeadd35 100644 --- a/tests/worktree/repository.c +++ b/tests/worktree/repository.c @@ -50,9 +50,12 @@ void test_worktree_repository__head_detached(void) cl_assert(git_repository_head_detached(fixture.worktree)); cl_assert(git_repository_head_detached_for_worktree(fixture.repo, "testrepo-worktree")); - cl_git_fail(git_repository_head_for_worktree(&head, fixture.repo, "testrepo-worktree")); + cl_git_pass(git_repository_head_for_worktree(&head, fixture.repo, "testrepo-worktree")); + + cl_assert_equal_oid(&ref->target.oid, &head->target.oid); git_reference_free(ref); + git_reference_free(head); } void test_worktree_repository__head_detached_fails_for_invalid_worktree(void) |