Commit 44af67a8 by nulltoken

repository: introduce git_repository_set_head()

parent 4ebe38bd
......@@ -507,6 +507,28 @@ GIT_EXTERN(int) git_repository_hashfile(
const char *as_path);
/**
* Make the repository HEAD point to the specified reference.
*
* If the provided reference points to a Tree or a Blob, the HEAD is
* unaltered and -1 is returned.
*
* If the provided reference points to a branch, the HEAD will point
* to that branch, staying attached, or become attached if it isn't yet.
* If the branch doesn't exist yet, no error will be return. The HEAD
* will then be attached to an unborn branch.
*
* Otherwise, the HEAD will be detached and will directly point to
* the Commit.
*
* @param repo Repository pointer
* @param refname Canonical name of the reference the HEAD should point at
* @return 0 on success, or an error code
*/
GIT_EXTERN(int) git_repository_set_head(
git_repository* repo,
const char* refname);
/**
* Make the repository HEAD directly point to the Commit.
*
* If the provided committish cannot be found in the repository, the HEAD
......
......@@ -1442,6 +1442,38 @@ cleanup:
return error;
}
static bool looks_like_a_branch(const char *refname)
{
return git__prefixcmp(refname, GIT_REFS_HEADS_DIR) == 0;
}
int git_repository_set_head(
git_repository* repo,
const char* refname)
{
git_reference *ref,
*new_head = NULL;
int error;
assert(repo && refname);
error = git_reference_lookup(&ref, repo, refname);
if (error < 0 && error != GIT_ENOTFOUND)
return error;
if (!error) {
if (git_reference_is_branch(ref))
error = git_reference_create_symbolic(&new_head, repo, GIT_HEAD_FILE, git_reference_name(ref), 1);
else
error = git_repository_set_head_detached(repo, git_reference_oid(ref));
} else if (looks_like_a_branch(refname))
error = git_reference_create_symbolic(&new_head, repo, GIT_HEAD_FILE, refname, 1);
git_reference_free(ref);
git_reference_free(new_head);
return error;
}
int git_repository_set_head_detached(
git_repository* repo,
const git_oid* commitish)
......
......@@ -51,6 +51,41 @@ void test_repo_head__head_orphan(void)
git_reference_free(ref);
}
void test_repo_head__set_head_Attaches_HEAD_to_un_unborn_branch_when_the_branch_doesnt_exist(void)
{
git_reference *head;
cl_git_pass(git_repository_set_head(repo, "refs/heads/doesnt/exist/yet"));
cl_assert_equal_i(false, git_repository_head_detached(repo));
cl_assert_equal_i(GIT_ENOTFOUND, git_repository_head(&head, repo));
}
void test_repo_head__set_head_Returns_ENOTFOUND_when_the_reference_doesnt_exist(void)
{
cl_assert_equal_i(GIT_ENOTFOUND, git_repository_set_head(repo, "refs/tags/doesnt/exist/yet"));
}
void test_repo_head__set_head_Fails_when_the_reference_points_to_a_non_commitish(void)
{
cl_git_fail(git_repository_set_head(repo, "refs/tags/point_to_blob"));
}
void test_repo_head__set_head_Attaches_HEAD_when_the_reference_points_to_a_branch(void)
{
git_reference *head;
cl_git_pass(git_repository_set_head(repo, "refs/heads/br2"));
cl_assert_equal_i(false, git_repository_head_detached(repo));
cl_git_pass(git_repository_head(&head, repo));
cl_assert_equal_s("refs/heads/br2", git_reference_name(head));
git_reference_free(head);
}
static void assert_head_is_correctly_detached(void)
{
git_reference *head;
......@@ -66,6 +101,15 @@ static void assert_head_is_correctly_detached(void)
git_reference_free(head);
}
void test_repo_head__set_head_Detaches_HEAD_when_the_reference_doesnt_point_to_a_branch(void)
{
cl_git_pass(git_repository_set_head(repo, "refs/tags/test"));
cl_assert_equal_i(true, git_repository_head_detached(repo));
assert_head_is_correctly_detached();
}
void test_repo_head__set_head_detached_Return_ENOTFOUND_when_the_object_doesnt_exist(void)
{
git_oid oid;
......
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