Commit 3f4c3072 by nulltoken

repository: introduce git_repository_detach_head()

parent cc548c7b
......@@ -506,6 +506,25 @@ GIT_EXTERN(int) git_repository_hashfile(
git_otype type,
const char *as_path);
/**
* Detach the HEAD.
*
* If the HEAD is already detached and points to a Commit, 0 is returned.
*
* If the HEAD is already detached and points to a Tag, the HEAD is
* updated into making it point to the peeled Commit, and 0 is returned.
*
* If the HEAD is already detached and points to a non commitish, the HEAD is
* unaletered, and -1 is returned.
*
* Otherwise, the HEAD will be detached and point to the peeled Commit.
*
* @param repo Repository pointer
* @return 0 on success, or an error code
*/
GIT_EXTERN(int) git_repository_detach_head(
git_repository* repo);
/** @} */
GIT_END_DECL
#endif
......@@ -1442,3 +1442,27 @@ cleanup:
return error;
}
int git_repository_detach_head(
git_repository* repo)
{
git_reference *old_head = NULL,
*new_head = NULL;
git_object *object = NULL;
int error = -1;
assert(repo);
if (git_repository_head(&old_head, repo) < 0)
return -1;
if (git_object_lookup(&object, repo, git_reference_oid(old_head), GIT_OBJ_COMMIT) < 0)
goto cleanup;
error = git_reference_create_oid(&new_head, repo, GIT_HEAD_FILE, git_reference_oid(old_head), 1);
cleanup:
git_object_free(object);
git_reference_free(old_head);
git_reference_free(new_head);
return error;
}
......@@ -50,3 +50,38 @@ void test_repo_head__head_orphan(void)
git_reference_free(ref);
}
static void assert_head_is_correctly_detached(void)
{
git_reference *head;
git_object *commit;
cl_assert_equal_i(true, git_repository_head_detached(repo));
cl_git_pass(git_repository_head(&head, repo));
cl_git_pass(git_object_lookup(&commit, repo, git_reference_oid(head), GIT_OBJ_COMMIT));
git_object_free(commit);
git_reference_free(head);
}
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));
cl_git_pass(git_repository_detach_head(repo));
assert_head_is_correctly_detached();
}
void test_repo_head__detach_head_Fails_if_HEAD_and_point_to_a_non_commitish(void)
{
git_reference *head;
cl_git_pass(git_reference_create_symbolic(&head, repo, GIT_HEAD_FILE, "refs/tags/point_to_blob", 1));
cl_git_fail(git_repository_detach_head(repo));
git_reference_free(head);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment