From: nulltoken Date: Sat, 15 Sep 2012 20:07:09 +0000 (+0200) Subject: repository: introduce git_repository_set_head_detached() X-Git-Url: https://git.proxmox.com/?a=commitdiff_plain;h=4ebe38bd589b7b99427b2822ca7a486c8bb3bf02;p=libgit2.git repository: introduce git_repository_set_head_detached() --- diff --git a/include/git2/repository.h b/include/git2/repository.h index e68e0548f..59a7d2c98 100644 --- a/include/git2/repository.h +++ b/include/git2/repository.h @@ -506,6 +506,26 @@ GIT_EXTERN(int) git_repository_hashfile( git_otype type, const char *as_path); +/** + * Make the repository HEAD directly point to the Commit. + * + * If the provided committish cannot be found in the repository, the HEAD + * is unaltered and GIT_ENOTFOUND is returned. + * + * If the provided commitish cannot be peeled into a commit, the HEAD + * is unaltered and -1 is returned. + * + * Otherwise, the HEAD will eventually be detached and will directly point to + * the peeled Commit. + * + * @param repo Repository pointer + * @param commitish Object id of the Commit the HEAD should point to + * @return 0 on success, or an error code + */ +GIT_EXTERN(int) git_repository_set_head_detached( + git_repository* repo, + const git_oid* commitish); + /** * Detach the HEAD. * diff --git a/src/repository.c b/src/repository.c index def96816f..a3e781478 100644 --- a/src/repository.c +++ b/src/repository.c @@ -1442,6 +1442,32 @@ cleanup: return error; } +int git_repository_set_head_detached( + git_repository* repo, + const git_oid* commitish) +{ + int error; + git_object *object, + *peeled = NULL; + git_reference *new_head = NULL; + + assert(repo && commitish); + + if ((error = git_object_lookup(&object, repo, commitish, GIT_OBJ_ANY)) < 0) + return error; + + if ((error = git_object_peel(&peeled, object, GIT_OBJ_COMMIT)) < 0) + goto cleanup; + + error = git_reference_create_oid(&new_head, repo, GIT_HEAD_FILE, git_object_id(peeled), 1); + +cleanup: + git_object_free(object); + git_object_free(peeled); + git_reference_free(new_head); + return error; +} + int git_repository_detach_head( git_repository* repo) { diff --git a/tests-clar/repo/head.c b/tests-clar/repo/head.c index 74d2a1c88..372cdd61d 100644 --- a/tests-clar/repo/head.c +++ b/tests-clar/repo/head.c @@ -66,6 +66,40 @@ static void assert_head_is_correctly_detached(void) git_reference_free(head); } +void test_repo_head__set_head_detached_Return_ENOTFOUND_when_the_object_doesnt_exist(void) +{ + git_oid oid; + + cl_git_pass(git_oid_fromstr(&oid, "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef")); + + cl_assert_equal_i(GIT_ENOTFOUND, git_repository_set_head_detached(repo, &oid)); +} + +void test_repo_head__set_head_detached_Fails_when_the_object_isnt_a_commitish(void) +{ + git_object *blob; + + cl_git_pass(git_revparse_single(&blob, repo, "point_to_blob")); + + cl_git_fail(git_repository_set_head_detached(repo, git_object_id(blob))); + + git_object_free(blob); +} + +void test_repo_head__set_head_detached_Detaches_HEAD_and_make_it_point_to_the_peeled_commit(void) +{ + git_object *tag; + + cl_git_pass(git_revparse_single(&tag, repo, "tags/test")); + cl_assert_equal_i(GIT_OBJ_TAG, git_object_type(tag)); + + cl_git_pass(git_repository_set_head_detached(repo, git_object_id(tag))); + + assert_head_is_correctly_detached(); + + git_object_free(tag); +} + void test_repo_head__detach_head_Detaches_HEAD_and_make_it_point_to_the_peeled_commit(void) { cl_assert_equal_i(false, git_repository_head_detached(repo));