Merge pull request #1061 from nulltoken/topic/explicit-head-errors repository: Refine repository_head() error report
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
diff --git a/include/git2/repository.h b/include/git2/repository.h
index 4d12226..d606cfa 100644
--- a/include/git2/repository.h
+++ b/include/git2/repository.h
@@ -273,7 +273,7 @@ GIT_EXTERN(int) git_repository_init_ext(
* @param repo a repository object
*
* @return 0 on success, GIT_EORPHANEDHEAD when HEAD points to a non existing
- * branch, an error code otherwise
+ * branch, GIT_ENOTFOUND when HEAD is missing; an error code otherwise
*/
GIT_EXTERN(int) git_repository_head(git_reference **head_out, git_repository *repo);
diff --git a/src/branch.c b/src/branch.c
index 62c4adb..c6173ca 100644
--- a/src/branch.c
+++ b/src/branch.c
@@ -317,7 +317,7 @@ int git_branch_is_head(
error = git_repository_head(&head, git_reference_owner(branch));
- if (error == GIT_EORPHANEDHEAD)
+ if (error == GIT_EORPHANEDHEAD || error == GIT_ENOTFOUND)
return false;
if (error < 0)
diff --git a/src/repository.c b/src/repository.c
index fbae893..101497c 100644
--- a/src/repository.c
+++ b/src/repository.c
@@ -1207,9 +1207,19 @@ int git_repository_head_detached(git_repository *repo)
int git_repository_head(git_reference **head_out, git_repository *repo)
{
+ git_reference *head;
int error;
- error = git_reference_lookup_resolved(head_out, repo, GIT_HEAD_FILE, -1);
+ if ((error = git_reference_lookup(&head, repo, GIT_HEAD_FILE)) < 0)
+ return error;
+
+ if (git_reference_type(head) == GIT_REF_OID) {
+ *head_out = head;
+ return 0;
+ }
+
+ error = git_reference_lookup_resolved(head_out, repo, git_reference_target(head), -1);
+ git_reference_free(head);
return error == GIT_ENOTFOUND ? GIT_EORPHANEDHEAD : error;
}
diff --git a/tests-clar/object/tree/duplicateentries.c b/tests-clar/object/tree/duplicateentries.c
index 27e1e2b..3052e29 100644
--- a/tests-clar/object/tree/duplicateentries.c
+++ b/tests-clar/object/tree/duplicateentries.c
@@ -116,7 +116,7 @@ void test_object_tree_duplicateentries__cannot_create_a_duplicate_entry_through_
tree_checker(&tid, "4e0883eeeeebc1fb1735161cea82f7cb5fab7e63", GIT_FILEMODE_TREE);
}
-void add_fake_conflicts(git_index *index)
+static void add_fake_conflicts(git_index *index)
{
git_index_entry ancestor_entry, our_entry, their_entry;
diff --git a/tests-clar/refs/branches/ishead.c b/tests-clar/refs/branches/ishead.c
index ab17482..52a0a19 100644
--- a/tests-clar/refs/branches/ishead.c
+++ b/tests-clar/refs/branches/ishead.c
@@ -39,6 +39,22 @@ void test_refs_branches_ishead__can_properly_handle_orphaned_HEAD(void)
repo = NULL;
}
+void test_refs_branches_ishead__can_properly_handle_missing_HEAD(void)
+{
+ git_repository_free(repo);
+
+ repo = cl_git_sandbox_init("testrepo.git");
+
+ delete_head(repo);
+
+ cl_git_pass(git_reference_lookup(&branch, repo, "refs/heads/master"));
+
+ cl_assert_equal_i(false, git_branch_is_head(branch));
+
+ cl_git_sandbox_cleanup();
+ repo = NULL;
+}
+
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"));
diff --git a/tests-clar/repo/head.c b/tests-clar/repo/head.c
index 58f525e..551e834 100644
--- a/tests-clar/repo/head.c
+++ b/tests-clar/repo/head.c
@@ -1,6 +1,7 @@
#include "clar_libgit2.h"
#include "refs.h"
#include "repo_helpers.h"
+#include "posix.h"
git_repository *repo;
@@ -178,6 +179,15 @@ void test_repo_head__retrieving_an_orphaned_head_returns_GIT_EORPHANEDHEAD(void)
cl_assert_equal_i(GIT_EORPHANEDHEAD, git_repository_head(&head, repo));
}
+void test_repo_head__retrieving_a_missing_head_returns_GIT_ENOTFOUND(void)
+{
+ git_reference *head;
+
+ delete_head(repo);
+
+ cl_assert_equal_i(GIT_ENOTFOUND, git_repository_head(&head, repo));
+}
+
void test_repo_head__can_tell_if_an_orphaned_head_is_detached(void)
{
make_head_orphaned(repo, NON_EXISTING_HEAD);
diff --git a/tests-clar/repo/repo_helpers.c b/tests-clar/repo/repo_helpers.c
index 35271fe..19ab38e 100644
--- a/tests-clar/repo/repo_helpers.c
+++ b/tests-clar/repo/repo_helpers.c
@@ -1,6 +1,7 @@
#include "clar_libgit2.h"
#include "refs.h"
#include "repo_helpers.h"
+#include "posix.h"
void make_head_orphaned(git_repository* repo, const char *target)
{
@@ -9,3 +10,13 @@ void make_head_orphaned(git_repository* repo, const char *target)
cl_git_pass(git_reference_create_symbolic(&head, repo, GIT_HEAD_FILE, target, 1));
git_reference_free(head);
}
+
+void delete_head(git_repository* repo)
+{
+ git_buf head_path = GIT_BUF_INIT;
+
+ cl_git_pass(git_buf_joinpath(&head_path, git_repository_path(repo), GIT_HEAD_FILE));
+ cl_git_pass(p_unlink(git_buf_cstr(&head_path)));
+
+ git_buf_free(&head_path);
+}
diff --git a/tests-clar/repo/repo_helpers.h b/tests-clar/repo/repo_helpers.h
index e6aeb48..09b5cac 100644
--- a/tests-clar/repo/repo_helpers.h
+++ b/tests-clar/repo/repo_helpers.h
@@ -3,3 +3,4 @@
#define NON_EXISTING_HEAD "refs/heads/hide/and/seek"
extern void make_head_orphaned(git_repository* repo, const char *target);
+extern void delete_head(git_repository* repo);