#include "clar_libgit2.h"
#include "fileops.h"
#include "git2/reflog.h"
#include "reflog.h"
#include "refs.h"
#include "ref_helpers.h"
static const char *loose_tag_ref_name = "refs/tags/e90810b";
static const char *packed_head_name = "refs/heads/packed";
static const char *packed_test_head_name = "refs/heads/packed-test";
static const char *ref_one_name = "refs/heads/one/branch";
static const char *ref_one_name_new = "refs/heads/two/branch";
static const char *ref_two_name = "refs/heads/two";
static const char *ref_master_name = "refs/heads/master";
static const char *ref_two_name_new = "refs/heads/two/two";
static git_repository *g_repo;
void test_refs_rename__initialize(void)
{
g_repo = cl_git_sandbox_init("testrepo");
cl_git_pass(git_repository_set_ident(g_repo, "me", "foo@example.com"));
}
void test_refs_rename__cleanup(void)
{
cl_git_sandbox_cleanup();
}
void test_refs_rename__loose(void)
{
git_reference *looked_up_ref, *new_ref, *another_looked_up_ref;
git_buf temp_path = GIT_BUF_INIT;
const char *new_name = "refs/tags/Nemo/knows/refs.kung-fu";
cl_git_pass(git_buf_joinpath(&temp_path, git_repository_path(g_repo), new_name));
cl_assert(!git_path_exists(temp_path.ptr));
cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, loose_tag_ref_name));
cl_assert(reference_is_packed(looked_up_ref) == 0);
cl_git_pass(git_reference_rename(&new_ref, looked_up_ref, new_name, 0, NULL));
cl_assert_equal_s(new_ref->name, new_name);
git_reference_free(looked_up_ref);
cl_git_fail(git_reference_lookup(&another_looked_up_ref, g_repo, loose_tag_ref_name));
cl_git_pass(git_reference_lookup(&another_looked_up_ref, g_repo, new_name));
cl_assert_equal_s(new_ref->name, new_name);
cl_assert(reference_is_packed(another_looked_up_ref) == 0);
cl_assert(reference_is_packed(new_ref) == 0);
cl_git_pass(git_buf_joinpath(&temp_path, git_repository_path(g_repo), new_name));
cl_assert(git_path_exists(temp_path.ptr));
git_reference_free(new_ref);
git_reference_free(another_looked_up_ref);
git_buf_free(&temp_path);
}
void test_refs_rename__packed(void)
{
git_reference *looked_up_ref, *new_ref, *another_looked_up_ref;
git_buf temp_path = GIT_BUF_INIT;
const char *brand_new_name = "refs/heads/brand_new_name";
cl_git_pass(git_buf_joinpath(&temp_path, git_repository_path(g_repo), packed_head_name));
cl_assert(!git_path_exists(temp_path.ptr));
cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, packed_head_name));
cl_assert(reference_is_packed(looked_up_ref) != 0);
cl_git_pass(git_reference_rename(&new_ref, looked_up_ref, brand_new_name, 0, NULL));
cl_assert_equal_s(new_ref->name, brand_new_name);
git_reference_free(looked_up_ref);
cl_git_fail(git_reference_lookup(&another_looked_up_ref, g_repo, packed_head_name));
cl_git_pass(git_reference_lookup(&another_looked_up_ref, g_repo, brand_new_name));
cl_assert_equal_s(another_looked_up_ref->name, brand_new_name);
cl_assert(reference_is_packed(another_looked_up_ref) == 0);
cl_assert(reference_is_packed(new_ref) == 0);
cl_git_pass(git_buf_joinpath(&temp_path, git_repository_path(g_repo), brand_new_name));
cl_assert(git_path_exists(temp_path.ptr));
git_reference_free(new_ref);
git_reference_free(another_looked_up_ref);
git_buf_free(&temp_path);
}
void test_refs_rename__packed_doesnt_pack_others(void)
{
git_reference *looked_up_ref, *another_looked_up_ref, *renamed_ref;
git_buf temp_path = GIT_BUF_INIT;
const char *brand_new_name = "refs/heads/brand_new_name";
cl_git_pass(git_buf_joinpath(&temp_path, git_repository_path(g_repo), packed_test_head_name));
cl_assert(git_path_exists(temp_path.ptr));
cl_git_pass(git_reference_lookup(&another_looked_up_ref, g_repo, packed_test_head_name));
cl_assert(reference_is_packed(another_looked_up_ref) == 0);
git_reference_free(another_looked_up_ref);
cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, packed_head_name));
cl_assert(reference_is_packed(looked_up_ref) != 0);
cl_git_pass(git_reference_rename(&renamed_ref, looked_up_ref, brand_new_name, 0, NULL));
git_reference_free(looked_up_ref);
cl_git_pass(git_reference_lookup(&another_looked_up_ref, g_repo, packed_test_head_name));
cl_assert(reference_is_packed(another_looked_up_ref) == 0);
cl_assert(git_path_exists(temp_path.ptr));
git_reference_free(renamed_ref);
git_reference_free(another_looked_up_ref);
git_buf_free(&temp_path);
}
void test_refs_rename__name_collision(void)
{
git_reference *looked_up_ref, *renamed_ref;
cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, packed_head_name));
cl_git_fail(git_reference_rename(&renamed_ref, looked_up_ref, packed_test_head_name, 0, NULL));
git_reference_free(looked_up_ref);
cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, packed_head_name));
cl_assert_equal_s(looked_up_ref->name, packed_head_name);
git_reference_free(looked_up_ref);
}
void test_refs_rename__invalid_name(void)
{
git_reference *looked_up_ref, *renamed_ref;
cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, packed_test_head_name));
cl_assert_equal_i(
GIT_EINVALIDSPEC,
git_reference_rename(&renamed_ref, looked_up_ref, "Hello! I'm a very invalid name.", 0, NULL));
cl_assert_equal_i(GIT_EINVALIDSPEC, git_reference_rename(&renamed_ref, looked_up_ref, "i-will-sudo-you", 0, NULL));
git_reference_free(looked_up_ref);
cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, packed_test_head_name));
cl_assert_equal_s(looked_up_ref->name, packed_test_head_name);
git_reference_free(looked_up_ref);
}
void test_refs_rename__force_loose_packed(void)
{
git_reference *looked_up_ref, *renamed_ref;
git_oid oid;
cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, packed_head_name));
git_oid_cpy(&oid, git_reference_target(looked_up_ref));
cl_git_pass(git_reference_rename(&renamed_ref, looked_up_ref, packed_test_head_name, 1, NULL));
git_reference_free(looked_up_ref);
git_reference_free(renamed_ref);
cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, packed_test_head_name));
cl_assert_equal_s(looked_up_ref->name, packed_test_head_name);
cl_assert_equal_oid(&oid, git_reference_target(looked_up_ref));
git_reference_free(looked_up_ref);
cl_git_fail(git_reference_lookup(&looked_up_ref, g_repo, packed_head_name));
}
void test_refs_rename__force_loose(void)
{
git_reference *looked_up_ref, *renamed_ref;
git_oid oid;
cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, "refs/heads/br2"));
git_oid_cpy(&oid, git_reference_target(looked_up_ref));
cl_git_pass(git_reference_rename(&renamed_ref, looked_up_ref, "refs/heads/test", 1, NULL));
git_reference_free(looked_up_ref);
git_reference_free(renamed_ref);
cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, "refs/heads/test"));
cl_assert_equal_s(looked_up_ref->name, "refs/heads/test");
cl_assert_equal_oid(&oid, git_reference_target(looked_up_ref));
git_reference_free(looked_up_ref);
cl_git_fail(git_reference_lookup(&looked_up_ref, g_repo, "refs/heads/br2"));
git_reference_free(looked_up_ref);
}
void test_refs_rename__overwrite(void)
{
git_reference *ref, *ref_one, *ref_one_new, *ref_two;
git_refdb *refdb;
git_oid id;
cl_git_pass(git_reference_lookup(&ref, g_repo, ref_master_name));
cl_assert(git_reference_type(ref) & GIT_REF_OID);
git_oid_cpy(&id, git_reference_target(ref));
cl_git_pass(git_reference_create(&ref_one, g_repo, ref_one_name, &id, 0, NULL));
cl_git_pass(git_reference_create(&ref_two, g_repo, ref_two_name, &id, 0, NULL));
cl_git_pass(git_repository_refdb(&refdb, g_repo));
cl_git_pass(git_refdb_compress(refdb));
cl_git_fail(git_reference_create(&ref_one_new, g_repo, ref_one_name_new, &id, 0, NULL));
cl_git_fail(git_reference_lookup(&ref_one_new, g_repo, ref_one_name_new));
git_reference_free(ref);
git_reference_free(ref_one);
git_reference_free(ref_one_new);
git_reference_free(ref_two);
git_refdb_free(refdb);
}
void test_refs_rename__prefix(void)
{
git_reference *ref, *ref_two, *looked_up_ref, *renamed_ref;
git_oid id;
cl_git_pass(git_reference_lookup(&ref, g_repo, ref_master_name));
cl_assert(git_reference_type(ref) & GIT_REF_OID);
git_oid_cpy(&id, git_reference_target(ref));
cl_git_pass(git_reference_create(&ref_two, g_repo, ref_two_name, &id, 0, NULL));
cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, ref_two_name));
cl_git_pass(git_reference_rename(&renamed_ref, looked_up_ref, ref_two_name_new, 0, NULL));
git_reference_free(looked_up_ref);
git_reference_free(renamed_ref);
cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, ref_two_name_new));
cl_assert_equal_s(looked_up_ref->name, ref_two_name_new);
git_reference_free(looked_up_ref);
cl_git_fail(git_reference_lookup(&looked_up_ref, g_repo, ref_two_name));
git_reference_free(ref);
git_reference_free(ref_two);
git_reference_free(looked_up_ref);
}
void test_refs_rename__move_up(void)
{
git_reference *ref, *ref_two, *looked_up_ref, *renamed_ref;
git_oid id;
cl_git_pass(git_reference_lookup(&ref, g_repo, ref_master_name));
cl_assert(git_reference_type(ref) & GIT_REF_OID);
git_oid_cpy(&id, git_reference_target(ref));
cl_git_pass(git_reference_create(&ref_two, g_repo, ref_two_name_new, &id, 0, NULL));
git_reference_free(ref_two);
cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, ref_two_name_new));
cl_git_pass(git_reference_rename(&renamed_ref, looked_up_ref, ref_two_name, 0, NULL));
git_reference_free(looked_up_ref);
git_reference_free(renamed_ref);
cl_git_pass(git_reference_lookup(&looked_up_ref, g_repo, ref_two_name));
cl_assert_equal_s(looked_up_ref->name, ref_two_name);
git_reference_free(looked_up_ref);
cl_git_fail(git_reference_lookup(&looked_up_ref, g_repo, ref_two_name_new));
git_reference_free(ref);
git_reference_free(looked_up_ref);
}
void test_refs_rename__propagate_eexists(void)
{
git_reference *ref, *new_ref;
cl_git_pass(git_reference_lookup(&ref, g_repo, packed_head_name));
cl_assert_equal_i(GIT_EEXISTS, git_reference_rename(&new_ref, ref, packed_test_head_name, 0, NULL));
git_reference_free(ref);
}
void test_refs_rename__writes_to_reflog(void)
{
git_reference *ref, *new_ref;
git_reflog *log;
const git_reflog_entry *entry;
cl_git_pass(git_reference_lookup(&ref, g_repo, ref_master_name));
cl_git_pass(git_reference_rename(&new_ref, ref, ref_one_name_new, false,
"message"));
cl_git_pass(git_reflog_read(&log, g_repo, git_reference_name(new_ref)));
entry = git_reflog_entry_byindex(log, 0);
cl_assert_equal_s("message", git_reflog_entry_message(entry));
cl_assert_equal_s("foo@example.com", git_reflog_entry_committer(entry)->email);
git_reflog_free(log);
git_reference_free(ref);
git_reference_free(new_ref);
}