From: nulltoken Date: Thu, 22 Nov 2012 17:51:06 +0000 (+0100) Subject: repo: Make git_repository_head_tree() return error codes X-Git-Url: https://git.proxmox.com/?a=commitdiff_plain;h=5cec896a3b7b85190a7862fb09f8ba20b2241f76;p=libgit2.git repo: Make git_repository_head_tree() return error codes --- diff --git a/src/checkout.c b/src/checkout.c index eff14813d..c4e4f999a 100644 --- a/src/checkout.c +++ b/src/checkout.c @@ -440,7 +440,9 @@ static int checkout_get_actions( const git_index_entry *he; /* if there is no HEAD, that's okay - we'll make an empty iterator */ - (void)git_repository_head_tree(&head, data->repo); + if (((error = git_repository_head_tree(&head, data->repo)) < 0) && + !(error == GIT_ENOTFOUND || error == GIT_EORPHANEDHEAD)) + return -1; if ((error = git_iterator_for_tree_range( &hiter, data->repo, head, pfx, pfx)) < 0) diff --git a/src/object.c b/src/object.c index 2e45eb86a..3d953039c 100644 --- a/src/object.c +++ b/src/object.c @@ -304,46 +304,6 @@ size_t git_object__size(git_otype type) return git_objects_table[type].size; } -int git_object__resolve_to_type(git_object **obj, git_otype type) -{ - int error = 0; - git_object *scan, *next; - - if (type == GIT_OBJ_ANY) - return 0; - - scan = *obj; - - while (!error && scan && git_object_type(scan) != type) { - - switch (git_object_type(scan)) { - case GIT_OBJ_COMMIT: - { - git_tree *tree = NULL; - error = git_commit_tree(&tree, (git_commit *)scan); - next = (git_object *)tree; - break; - } - - case GIT_OBJ_TAG: - error = git_tag_target(&next, (git_tag *)scan); - break; - - default: - giterr_set(GITERR_REFERENCE, "Object does not resolve to type"); - error = -1; - next = NULL; - break; - } - - git_object_free(scan); - scan = next; - } - - *obj = scan; - return error; -} - static int peel_error(int error, const char* msg) { giterr_set(GITERR_INVALID, "The given object cannot be peeled - %s", msg); diff --git a/src/repository.c b/src/repository.c index f82dc108b..deab77192 100644 --- a/src/repository.c +++ b/src/repository.c @@ -1384,22 +1384,21 @@ int git_repository_is_bare(git_repository *repo) int git_repository_head_tree(git_tree **tree, git_repository *repo) { - git_oid head_oid; - git_object *obj = NULL; + git_reference *head; + git_object *obj; + int error; - if (git_reference_name_to_oid(&head_oid, repo, GIT_HEAD_FILE) < 0) { - /* cannot resolve HEAD - probably brand new repo */ - giterr_clear(); - *tree = NULL; - return 0; - } + if ((error = git_repository_head(&head, repo)) < 0) + return error; - if (git_object_lookup(&obj, repo, &head_oid, GIT_OBJ_ANY) < 0 || - git_object__resolve_to_type(&obj, GIT_OBJ_TREE) < 0) - return -1; + if ((error = git_reference_peel(&obj, head, GIT_OBJ_TREE)) < 0) + goto cleanup; *tree = (git_tree *)obj; - return 0; + +cleanup: + git_reference_free(head); + return error; } int git_repository_message(char *buffer, size_t len, git_repository *repo) diff --git a/src/status.c b/src/status.c index b8c15ef92..b832cfe64 100644 --- a/src/status.c +++ b/src/status.c @@ -121,8 +121,10 @@ int git_status_foreach_ext( (err = git_repository__ensure_not_bare(repo, "status")) < 0) return err; - if ((err = git_repository_head_tree(&head, repo)) < 0) - return err; + /* if there is no HEAD, that's okay - we'll make an empty iterator */ + if (((err = git_repository_head_tree(&head, repo)) < 0) && + !(err == GIT_ENOTFOUND || err == GIT_EORPHANEDHEAD)) + return err; memset(&diffopt, 0, sizeof(diffopt)); memcpy(&diffopt.pathspec, &opts->pathspec, sizeof(diffopt.pathspec)); diff --git a/tests-clar/repo/headtree.c b/tests-clar/repo/headtree.c new file mode 100644 index 000000000..0e7fe93e5 --- /dev/null +++ b/tests-clar/repo/headtree.c @@ -0,0 +1,53 @@ +#include "clar_libgit2.h" +#include "repository.h" +#include "repo_helpers.h" +#include "posix.h" + +static git_repository *repo; +static git_tree *tree; + +void test_repo_headtree__initialize(void) +{ + repo = cl_git_sandbox_init("testrepo.git"); + tree = NULL; +} + +void test_repo_headtree__cleanup(void) +{ + git_tree_free(tree); + cl_git_sandbox_cleanup(); +} + +void test_repo_headtree__can_retrieve_the_root_tree_from_a_detached_head(void) +{ + cl_git_pass(git_repository_detach_head(repo)); + + cl_git_pass(git_repository_head_tree(&tree, repo)); + + cl_assert(git_oid_streq(git_tree_id(tree), "az")); +} + +void test_repo_headtree__can_retrieve_the_root_tree_from_a_non_detached_head(void) +{ + cl_assert_equal_i(false, git_repository_head_detached(repo)); + + cl_git_pass(git_repository_head_tree(&tree, repo)); + + cl_assert(git_oid_streq(git_tree_id(tree), "az")); +} + +void test_repo_headtree__when_head_is_orphaned_returns_EORPHANEDHEAD(void) +{ + make_head_orphaned(repo, NON_EXISTING_HEAD); + + cl_assert_equal_i(true, git_repository_head_orphan(repo)); + + cl_assert_equal_i(GIT_EORPHANEDHEAD, git_repository_head_tree(&tree, repo)); +} + +void test_repo_headtree__when_head_is_missing_returns_ENOTFOUND(void) +{ + delete_head(repo); + + cl_assert_equal_i(GIT_ENOTFOUND, git_repository_head_tree(&tree, repo)); +}