From b1a3a70ed1ca45bb155ec4c10b40a047d27614f3 Mon Sep 17 00:00:00 2001 From: nulltoken Date: Mon, 12 Nov 2012 00:14:51 +0100 Subject: [PATCH] repository: Refine repository_head() error report --- include/git2/repository.h | 2 +- src/branch.c | 2 +- src/repository.c | 12 +++++++++++- tests-clar/refs/branches/ishead.c | 16 ++++++++++++++++ tests-clar/repo/head.c | 10 ++++++++++ tests-clar/repo/repo_helpers.c | 11 +++++++++++ tests-clar/repo/repo_helpers.h | 1 + 7 files changed, 51 insertions(+), 3 deletions(-) diff --git a/include/git2/repository.h b/include/git2/repository.h index 4d122265c..d606cfa2a 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 62c4adbf4..c6173caca 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 fbae8935b..101497c4d 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/refs/branches/ishead.c b/tests-clar/refs/branches/ishead.c index ab17482b8..52a0a1941 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 58f525e2b..551e834f2 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 35271feaa..19ab38ee3 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 e6aeb4873..09b5cac84 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);