Commit 4ebe38bd by nulltoken

repository: introduce git_repository_set_head_detached()

parent 3f4c3072
......@@ -507,6 +507,26 @@ GIT_EXTERN(int) git_repository_hashfile(
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.
*
* If the HEAD is already detached and points to a Commit, 0 is returned.
......
......@@ -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)
{
......
......@@ -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));
......
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