create.c 5.97 KB
Newer Older
1 2
#include "clar_libgit2.h"
#include "refs.h"
3
#include "path.h"
4 5

static git_repository *repo;
Vicent Marti committed
6
static git_commit *target;
7
static git_reference *branch;
8 9 10

void test_refs_branches_create__initialize(void)
{
11
	repo = cl_git_sandbox_init("testrepo.git");
12
	branch = NULL;
13
	target = NULL;
14 15 16 17
}

void test_refs_branches_create__cleanup(void)
{
18
	git_reference_free(branch);
19
	branch = NULL;
20

Ben Straub committed
21
	git_commit_free(target);
22 23
	target = NULL;

24
	cl_git_sandbox_cleanup();
25
	repo = NULL;
26 27
}

Vicent Marti committed
28
static void retrieve_target_from_oid(git_commit **out, git_repository *repo, const char *sha)
29
{
30
	git_object *obj;
31

32 33 34
	cl_git_pass(git_revparse_single(&obj, repo, sha));
	cl_git_pass(git_commit_lookup(out, repo, git_object_id(obj)));
	git_object_free(obj);
35 36
}

Vicent Marti committed
37
static void retrieve_known_commit(git_commit **commit, git_repository *repo)
38
{
39
	retrieve_target_from_oid(commit, repo, "e90810b8df3");
40 41 42 43 44 45 46 47
}

#define NEW_BRANCH_NAME "new-branch-on-the-block"

void test_refs_branches_create__can_create_a_local_branch(void)
{
	retrieve_known_commit(&target, repo);

48
	cl_git_pass(git_branch_create(&branch, repo, NEW_BRANCH_NAME, target, 0, NULL, NULL));
Vicent Marti committed
49
	cl_git_pass(git_oid_cmp(git_reference_target(branch), git_commit_id(target)));
50 51 52 53 54 55
}

void test_refs_branches_create__can_not_create_a_branch_if_its_name_collide_with_an_existing_one(void)
{
	retrieve_known_commit(&target, repo);

56
	cl_assert_equal_i(GIT_EEXISTS, git_branch_create(&branch, repo, "br2", target, 0, NULL, NULL));
57 58 59 60 61 62
}

void test_refs_branches_create__can_force_create_over_an_existing_branch(void)
{
	retrieve_known_commit(&target, repo);

63
	cl_git_pass(git_branch_create(&branch, repo, "br2", target, 1, NULL, NULL));
Vicent Marti committed
64
	cl_git_pass(git_oid_cmp(git_reference_target(branch), git_commit_id(target)));
65
	cl_assert_equal_s("refs/heads/br2", git_reference_name(branch));
66
}
67

68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
void test_refs_branches_create__cannot_force_create_over_current_branch(void)
{
	const git_oid *oid;
	git_reference *branch2;
	retrieve_known_commit(&target, repo);

	cl_git_pass(git_branch_lookup(&branch2, repo, "master", GIT_BRANCH_LOCAL));
	cl_assert_equal_s("refs/heads/master", git_reference_name(branch2));
	cl_assert_equal_i(true, git_branch_is_head(branch2));
	oid = git_reference_target(branch2);

	cl_git_fail_with(-1, git_branch_create(&branch, repo, "master", target, 1, NULL, NULL));
	branch = NULL;
	cl_git_pass(git_branch_lookup(&branch, repo, "master", GIT_BRANCH_LOCAL));
	cl_assert_equal_s("refs/heads/master", git_reference_name(branch));
	cl_git_pass(git_oid_cmp(git_reference_target(branch), oid));
	git_reference_free(branch2);
}

87 88 89 90 91
void test_refs_branches_create__creating_a_branch_with_an_invalid_name_returns_EINVALIDSPEC(void)
{
	retrieve_known_commit(&target, repo);

	cl_assert_equal_i(GIT_EINVALIDSPEC,
92
		git_branch_create(&branch, repo, "inv@{id", target, 0, NULL, NULL));
Edward Thomson committed
93 94
}

Ben Straub committed
95 96 97 98
void test_refs_branches_create__creation_creates_new_reflog(void)
{
	git_reflog *log;
	const git_reflog_entry *entry;
99 100 101
	git_signature *sig;

	cl_git_pass(git_signature_now(&sig, "me", "foo@example.com"));
Ben Straub committed
102 103

	retrieve_known_commit(&target, repo);
104
	cl_git_pass(git_branch_create(&branch, repo, NEW_BRANCH_NAME, target, false, sig, "create!"));
Ben Straub committed
105 106 107 108
	cl_git_pass(git_reflog_read(&log, repo, "refs/heads/" NEW_BRANCH_NAME));

	cl_assert_equal_i(1, git_reflog_entrycount(log));
	entry = git_reflog_entry_byindex(log, 0);
109
	cl_assert_equal_s("create!", git_reflog_entry_message(entry));
110
	cl_assert_equal_s("foo@example.com", git_reflog_entry_committer(entry)->email);
111 112

	git_reflog_free(log);
113
	git_signature_free(sig);
114 115 116 117 118 119
}

void test_refs_branches_create__default_reflog_message(void)
{
	git_reflog *log;
	const git_reflog_entry *entry;
120
	git_signature *sig;
121 122 123 124 125 126
	git_config *cfg;

	cl_git_pass(git_repository_config(&cfg, repo));
	cl_git_pass(git_config_set_string(cfg, "user.name", "Foo Bar"));
	cl_git_pass(git_config_set_string(cfg, "user.email", "foo@example.com"));
	git_config_free(cfg);
127 128

	cl_git_pass(git_signature_default(&sig, repo));
129 130 131 132 133 134 135

	retrieve_known_commit(&target, repo);
	cl_git_pass(git_branch_create(&branch, repo, NEW_BRANCH_NAME, target, false, NULL, NULL));
	cl_git_pass(git_reflog_read(&log, repo, "refs/heads/" NEW_BRANCH_NAME));

	entry = git_reflog_entry_byindex(log, 0);
	cl_assert_equal_s("Branch: created", git_reflog_entry_message(entry));
136
	cl_assert_equal_s(sig->email, git_reflog_entry_committer(entry)->email);
137 138

	git_reflog_free(log);
139
	git_signature_free(sig);
Ben Straub committed
140
}
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169

static void assert_branch_matches_name(
	const char *expected, const char *lookup_as)
{
	git_reference *ref;
	git_buf b = GIT_BUF_INIT;

	cl_git_pass(git_branch_lookup(&ref, repo, lookup_as, GIT_BRANCH_LOCAL));

	cl_git_pass(git_buf_sets(&b, "refs/heads/"));
	cl_git_pass(git_buf_puts(&b, expected));
	cl_assert_equal_s(b.ptr, git_reference_name(ref));

	cl_git_pass(
		git_oid_cmp(git_reference_target(ref), git_commit_id(target)));

	git_reference_free(ref);
	git_buf_free(&b);
}

void test_refs_branches_create__can_create_branch_with_unicode(void)
{
	const char *nfc = "\xC3\x85\x73\x74\x72\xC3\xB6\x6D";
	const char *nfd = "\x41\xCC\x8A\x73\x74\x72\x6F\xCC\x88\x6D";
	const char *emoji = "\xF0\x9F\x8D\xB7";
	const char *names[] = { nfc, nfd, emoji };
	const char *alt[] = { nfd, nfc, NULL };
	const char *expected[] = { nfc, nfd, emoji };
	unsigned int i;
170 171
	bool fs_decompose_unicode =
		git_path_does_fs_decompose_unicode(git_repository_path(repo));
172 173 174 175 176 177

	retrieve_known_commit(&target, repo);

	if (cl_repo_get_bool(repo, "core.precomposeunicode"))
		expected[1] = nfc;
	/* test decomp. because not all Mac filesystems decompose unicode */
178
	else if (fs_decompose_unicode)
179 180 181
		expected[0] = nfd;

	for (i = 0; i < ARRAY_SIZE(names); ++i) {
182
		const char *name;
183 184 185 186 187
		cl_git_pass(git_branch_create(
			&branch, repo, names[i], target, 0, NULL, NULL));
		cl_git_pass(git_oid_cmp(
			git_reference_target(branch), git_commit_id(target)));

188 189
		cl_git_pass(git_branch_name(&name, branch));
		cl_assert_equal_s(expected[i], name);
190
		assert_branch_matches_name(expected[i], names[i]);
191
		if (fs_decompose_unicode && alt[i])
192 193 194 195 196 197 198
			assert_branch_matches_name(expected[i], alt[i]);

		cl_git_pass(git_branch_delete(branch));
		git_reference_free(branch);
		branch = NULL;
	}
}