git_otype type,
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.
*
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)
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;
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;