Commit 0c78f685ebeed293c666815b1668b8209f4ff258

nulltoken 2012-10-06T10:41:53

branch: introduce git_branch_is_head()

diff --git a/include/git2/branch.h b/include/git2/branch.h
index f072799..f06609a 100644
--- a/include/git2/branch.h
+++ b/include/git2/branch.h
@@ -148,6 +148,17 @@ GIT_EXTERN(int) git_branch_tracking(
 		git_reference **tracking_out,
 		git_reference *branch);
 
+/**
+ * Determine if the current local branch is pointed at by HEAD.
+ *
+ * @param branch Current underlying reference of the branch.
+ *
+ * @return 1 if HEAD points at the branch, 0 if it isn't,
+ * error code otherwise.
+ */
+GIT_EXTERN(int) git_branch_is_head(
+		git_reference *branch);
+
 /** @} */
 GIT_END_DECL
 #endif
diff --git a/src/branch.c b/src/branch.c
index 103dfe6..3cee956 100644
--- a/src/branch.c
+++ b/src/branch.c
@@ -271,3 +271,26 @@ cleanup:
 	git_buf_free(&buf);
 	return error;
 }
+
+int git_branch_is_head(
+		git_reference *branch)
+{
+	git_reference *head;
+	bool is_same = false;
+
+	assert(branch);
+
+	if (!git_reference_is_branch(branch))
+		return false;
+
+	if (git_repository_head(&head, git_reference_owner(branch)) < 0)
+		return -1;
+
+	is_same = strcmp(
+		git_reference_name(branch),
+		git_reference_name(head)) == 0;
+
+	git_reference_free(head);
+
+	return is_same;
+}
diff --git a/tests-clar/refs/branches/ishead.c b/tests-clar/refs/branches/ishead.c
new file mode 100644
index 0000000..c40a431
--- /dev/null
+++ b/tests-clar/refs/branches/ishead.c
@@ -0,0 +1,80 @@
+#include "clar_libgit2.h"
+#include "refs.h"
+
+static git_repository *repo;
+static git_reference *branch;
+
+void test_refs_branches_ishead__initialize(void)
+{
+	cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git")));
+}
+
+void test_refs_branches_ishead__cleanup(void)
+{
+	git_reference_free(branch);
+	git_repository_free(repo);
+}
+
+void test_refs_branches_ishead__can_tell_if_a_branch_is_pointed_at_by_HEAD(void)
+{
+	cl_git_pass(git_reference_lookup(&branch, repo, "refs/heads/master"));
+
+	cl_assert_equal_i(true, git_branch_is_head(branch));
+}
+
+void test_refs_branches_ishead__can_tell_if_a_branch_is_not_pointed_at_by_HEAD(void)
+{
+	cl_git_pass(git_reference_lookup(&branch, repo, "refs/heads/br2"));
+
+	cl_assert_equal_i(false, git_branch_is_head(branch));
+}
+
+void test_refs_branches_ishead__wont_be_fooled_by_a_non_branch(void)
+{
+	cl_git_pass(git_reference_lookup(&branch, repo, "refs/tags/e90810b"));
+
+	cl_assert_equal_i(false, git_branch_is_head(branch));
+}
+
+/*
+ * $ git init .
+ * Initialized empty Git repository in d:/temp/tempee/.git/
+ * 
+ * $ touch a && git add a
+ * $ git commit -m" boom"
+ * [master (root-commit) b47b758]  boom
+ *  0 files changed
+ *  create mode 100644 a
+ * 
+ * $ echo "ref: refs/heads/master" > .git/refs/heads/linked
+ * $ echo "ref: refs/heads/linked" > .git/refs/heads/super
+ * $ echo "ref: refs/heads/super" > .git/HEAD
+ * 
+ * $ git branch
+ *   linked -> master
+ * * master
+ *   super -> master
+ */
+void test_refs_branches_ishead__only_direct_references_are_considered(void)
+{
+	git_reference *linked, *super, *head;
+
+	git_repository_free(repo);
+	repo = cl_git_sandbox_init("testrepo.git");
+
+	cl_git_pass(git_reference_create_symbolic(&linked, repo, "refs/heads/linked", "refs/heads/master", 0));
+	cl_git_pass(git_reference_create_symbolic(&super, repo, "refs/heads/super", "refs/heads/linked", 0));
+	cl_git_pass(git_reference_create_symbolic(&head, repo, GIT_HEAD_FILE, "refs/heads/super", 1));
+
+	cl_assert_equal_i(false, git_branch_is_head(linked));
+	cl_assert_equal_i(false, git_branch_is_head(super));
+
+	cl_git_pass(git_repository_head(&branch, repo));
+	cl_assert_equal_s("refs/heads/master", git_reference_name(branch));
+
+	git_reference_free(linked);
+	git_reference_free(super);
+	git_reference_free(head);
+	cl_git_sandbox_cleanup();
+	repo = NULL;
+}