summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Steinhardt <ps@pks.im>2020-06-17 14:43:27 +0200
committerPatrick Steinhardt <ps@pks.im>2020-07-12 18:12:16 +0200
commitac5fbe31edac2f126b21df69672b76077ee66933 (patch)
treee2d13da0c3a56f5d398acd0e3bf4fe18ad6a993d
parent7216b048f5bd3cdad6416295d128f0173cb74533 (diff)
downloadlibgit2-ac5fbe31edac2f126b21df69672b76077ee66933.tar.gz
branch: determine whether a branch is checked out via refdb
We currently determine whether a branch is checked out via `git_repository_foreach_head`. As this function reads references directly from the disk, it breaks our refdb abstraction in case the repository uses a different reference backend implementation than the filesystem-based one. So let's use `git_repository_foreach_worktree` instead -- while it's less efficient, it is at least correct in all corner cases.
-rw-r--r--src/branch.c38
1 files changed, 18 insertions, 20 deletions
diff --git a/src/branch.c b/src/branch.c
index 770c9a1ee..715f6cf99 100644
--- a/src/branch.c
+++ b/src/branch.c
@@ -134,39 +134,37 @@ int git_branch_create_from_annotated(
repository, branch_name, commit->commit, commit->description, force);
}
-static int branch_equals(git_repository *repo, const char *path, void *payload)
+static int branch_is_checked_out(git_repository *worktree, void *payload)
{
git_reference *branch = (git_reference *) payload;
git_reference *head = NULL;
- int equal = 0;
+ int error;
- if (git_reference__read_head(&head, repo, path) < 0 ||
- git_reference_type(head) != GIT_REFERENCE_SYMBOLIC)
- goto done;
+ if (git_repository_is_bare(worktree))
+ return 0;
- equal = !git__strcmp(head->target.symbolic, branch->name);
+ if ((error = git_reference_lookup(&head, worktree, GIT_HEAD_FILE)) < 0) {
+ if (error == GIT_ENOTFOUND)
+ error = 0;
+ goto out;
+ }
-done:
+ if (git_reference_type(head) != GIT_REFERENCE_SYMBOLIC)
+ goto out;
+
+ error = !git__strcmp(head->target.symbolic, branch->name);
+
+out:
git_reference_free(head);
- return equal;
+ return error;
}
int git_branch_is_checked_out(const git_reference *branch)
{
- git_repository *repo;
- int flags = 0;
-
- assert(branch);
-
if (!git_reference_is_branch(branch))
return 0;
-
- repo = git_reference_owner(branch);
-
- if (git_repository_is_bare(repo))
- flags |= GIT_REPOSITORY_FOREACH_HEAD_SKIP_REPO;
-
- return git_repository_foreach_head(repo, branch_equals, flags, (void *) branch) == 1;
+ return git_repository_foreach_worktree(git_reference_owner(branch),
+ branch_is_checked_out, (void *)branch) == 1;
}
int git_branch_delete(git_reference *branch)