From e3acd37b70dc6d8f1ff256b99a26b4e0f13701ef Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 6 Nov 2015 12:08:15 +0100 Subject: [PATCH] branch: implement `git_branch_is_checked_out` Implement a new function that is able to determine if a branch is checked out in any repository connected to the current repository. In particular, this is required to check if for a given repository and branch, there exists any working tree connected to that repository that is referencing this branch. --- include/git2/branch.h | 12 +++++++++ src/branch.c | 57 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+) diff --git a/include/git2/branch.h b/include/git2/branch.h index 34354f4e5..88fe723a0 100644 --- a/include/git2/branch.h +++ b/include/git2/branch.h @@ -245,6 +245,18 @@ GIT_EXTERN(int) git_branch_upstream_name( GIT_EXTERN(int) git_branch_is_head( const git_reference *branch); +/** + * Determine if the current branch is checked out in any linked + * repository. + * + * @param branch Reference to the branch. + * + * @return 1 if branch is checked out, 0 if it isn't, + * error code otherwise. + */ +GIT_EXTERN(int) git_branch_is_checked_out( + const git_reference *branch); + /** * Return the name of remote that the remote tracking branch belongs to. * diff --git a/src/branch.c b/src/branch.c index 7ddcb3da7..e48cb1f68 100644 --- a/src/branch.c +++ b/src/branch.c @@ -13,6 +13,7 @@ #include "refs.h" #include "remote.h" #include "annotated_commit.h" +#include "worktree.h" #include "git2/branch.h" @@ -126,6 +127,62 @@ int git_branch_create_from_annotated( repository, branch_name, commit->commit, commit->description, force); } +int git_branch_is_checked_out( + const git_reference *branch) +{ + git_buf path = GIT_BUF_INIT, buf = GIT_BUF_INIT; + git_strarray worktrees; + git_reference *ref = NULL; + git_repository *repo; + const char *worktree; + int found = false; + size_t i; + + assert(branch && git_reference_is_branch(branch)); + + repo = git_reference_owner(branch); + + if (git_worktree_list(&worktrees, repo) < 0) + return -1; + + for (i = 0; i < worktrees.count; i++) { + worktree = worktrees.strings[i]; + + if (git_repository_head_for_worktree(&ref, repo, worktree) < 0) + continue; + + if (git__strcmp(ref->name, branch->name) == 0) { + found = true; + git_reference_free(ref); + break; + } + + git_reference_free(ref); + } + git_strarray_free(&worktrees); + + if (found) + return found; + + /* Check HEAD of parent */ + if (git_buf_joinpath(&path, repo->commondir, GIT_HEAD_FILE) < 0) + goto out; + if (git_futils_readbuffer(&buf, path.ptr) < 0) + goto out; + if (git__prefixcmp(buf.ptr, "ref: ") == 0) + git_buf_consume(&buf, buf.ptr + strlen("ref: ")); + git_buf_rtrim(&buf); + + found = git__strcmp(buf.ptr, branch->name) == 0; + +out: + git_buf_free(&buf); + git_buf_free(&path); + + return found; +} + + int git_branch_delete(git_reference *branch) { int is_head;