conflicts.c 14 KB
Newer Older
Edward Thomson committed
1 2 3
#include "clar_libgit2.h"
#include "index.h"
#include "git2/repository.h"
4
#include "conflicts.h"
Edward Thomson committed
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21

static git_repository *repo;
static git_index *repo_index;

#define TEST_REPO_PATH "mergedrepo"
#define TEST_INDEX_PATH TEST_REPO_PATH "/.git/index"

// Fixture setup and teardown
void test_index_conflicts__initialize(void)
{
	repo = cl_git_sandbox_init("mergedrepo");
	git_repository_index(&repo_index, repo);
}

void test_index_conflicts__cleanup(void)
{
	git_index_free(repo_index);
22 23
	repo_index = NULL;

Edward Thomson committed
24 25 26 27 28 29 30 31 32 33 34 35 36 37
	cl_git_sandbox_cleanup();
}

void test_index_conflicts__add(void)
{
	git_index_entry ancestor_entry, our_entry, their_entry;

	cl_assert(git_index_entrycount(repo_index) == 8);

	memset(&ancestor_entry, 0x0, sizeof(git_index_entry));
	memset(&our_entry, 0x0, sizeof(git_index_entry));
	memset(&their_entry, 0x0, sizeof(git_index_entry));

	ancestor_entry.path = "test-one.txt";
38
	ancestor_entry.mode = 0100644;
39
	GIT_IDXENTRY_STAGE_SET(&ancestor_entry, 1);
40
	git_oid_fromstr(&ancestor_entry.id, CONFLICTS_ONE_ANCESTOR_OID);
Edward Thomson committed
41 42

	our_entry.path = "test-one.txt";
43
	our_entry.mode = 0100644;
44
	GIT_IDXENTRY_STAGE_SET(&our_entry, 2);
45
	git_oid_fromstr(&our_entry.id, CONFLICTS_ONE_OUR_OID);
Edward Thomson committed
46 47

	their_entry.path = "test-one.txt";
48
	their_entry.mode = 0100644;
49
	GIT_IDXENTRY_STAGE_SET(&ancestor_entry, 2);
50
	git_oid_fromstr(&their_entry.id, CONFLICTS_ONE_THEIR_OID);
Edward Thomson committed
51 52 53 54 55 56 57 58 59

	cl_git_pass(git_index_conflict_add(repo_index, &ancestor_entry, &our_entry, &their_entry));

	cl_assert(git_index_entrycount(repo_index) == 11);
}

void test_index_conflicts__add_fixes_incorrect_stage(void)
{
	git_index_entry ancestor_entry, our_entry, their_entry;
60
	const git_index_entry *conflict_entry[3];
Edward Thomson committed
61 62 63 64 65 66 67 68

	cl_assert(git_index_entrycount(repo_index) == 8);

	memset(&ancestor_entry, 0x0, sizeof(git_index_entry));
	memset(&our_entry, 0x0, sizeof(git_index_entry));
	memset(&their_entry, 0x0, sizeof(git_index_entry));

	ancestor_entry.path = "test-one.txt";
69
	ancestor_entry.mode = 0100644;
70
	GIT_IDXENTRY_STAGE_SET(&ancestor_entry, 3);
71
	git_oid_fromstr(&ancestor_entry.id, CONFLICTS_ONE_ANCESTOR_OID);
Edward Thomson committed
72 73

	our_entry.path = "test-one.txt";
74
	our_entry.mode = 0100644;
75
	GIT_IDXENTRY_STAGE_SET(&our_entry, 1);
76
	git_oid_fromstr(&our_entry.id, CONFLICTS_ONE_OUR_OID);
Edward Thomson committed
77 78

	their_entry.path = "test-one.txt";
79
	their_entry.mode = 0100644;
80
	GIT_IDXENTRY_STAGE_SET(&their_entry, 2);
81
	git_oid_fromstr(&their_entry.id, CONFLICTS_ONE_THEIR_OID);
Edward Thomson committed
82 83 84 85 86 87 88 89 90 91 92 93

	cl_git_pass(git_index_conflict_add(repo_index, &ancestor_entry, &our_entry, &their_entry));

	cl_assert(git_index_entrycount(repo_index) == 11);

	cl_git_pass(git_index_conflict_get(&conflict_entry[0], &conflict_entry[1], &conflict_entry[2], repo_index, "test-one.txt"));

	cl_assert(git_index_entry_stage(conflict_entry[0]) == 1);
	cl_assert(git_index_entry_stage(conflict_entry[1]) == 2);
	cl_assert(git_index_entry_stage(conflict_entry[2]) == 3);
}

94 95
void test_index_conflicts__add_removes_stage_zero(void)
{
96
	git_index_entry ancestor_entry, our_entry, their_entry;
97 98 99 100 101 102 103 104
	const git_index_entry *conflict_entry[3];

	cl_assert(git_index_entrycount(repo_index) == 8);

	memset(&ancestor_entry, 0x0, sizeof(git_index_entry));
	memset(&our_entry, 0x0, sizeof(git_index_entry));
	memset(&their_entry, 0x0, sizeof(git_index_entry));

105 106
	cl_git_mkfile("./mergedrepo/test-one.txt", "new-file\n");
	cl_git_pass(git_index_add_bypath(repo_index, "test-one.txt"));
107 108 109 110
	cl_assert(git_index_entrycount(repo_index) == 9);

	ancestor_entry.path = "test-one.txt";
	ancestor_entry.mode = 0100644;
111
	GIT_IDXENTRY_STAGE_SET(&ancestor_entry, 3);
112
	git_oid_fromstr(&ancestor_entry.id, CONFLICTS_ONE_ANCESTOR_OID);
113 114 115

	our_entry.path = "test-one.txt";
	our_entry.mode = 0100644;
116
	GIT_IDXENTRY_STAGE_SET(&our_entry, 1);
117
	git_oid_fromstr(&our_entry.id, CONFLICTS_ONE_OUR_OID);
118 119 120

	their_entry.path = "test-one.txt";
	their_entry.mode = 0100644;
121
	GIT_IDXENTRY_STAGE_SET(&their_entry, 2);
122
	git_oid_fromstr(&their_entry.id, CONFLICTS_ONE_THEIR_OID);
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139

	cl_git_pass(git_index_conflict_add(repo_index, &ancestor_entry, &our_entry, &their_entry));

	cl_assert(git_index_entrycount(repo_index) == 11);

	cl_assert_equal_p(NULL, git_index_get_bypath(repo_index, "test-one.txt", 0));

	cl_git_pass(git_index_conflict_get(&conflict_entry[0], &conflict_entry[1], &conflict_entry[2], repo_index, "test-one.txt"));

	cl_assert_equal_oid(&ancestor_entry.id, &conflict_entry[0]->id);
	cl_assert_equal_i(1, git_index_entry_stage(conflict_entry[0]));
	cl_assert_equal_oid(&our_entry.id, &conflict_entry[1]->id);
	cl_assert_equal_i(2, git_index_entry_stage(conflict_entry[1]));
	cl_assert_equal_oid(&their_entry.id, &conflict_entry[2]->id);
	cl_assert_equal_i(3, git_index_entry_stage(conflict_entry[2]));
}

Edward Thomson committed
140 141
void test_index_conflicts__get(void)
{
142
	const git_index_entry *conflict_entry[3];
Edward Thomson committed
143 144 145 146 147
	git_oid oid;

	cl_git_pass(git_index_conflict_get(&conflict_entry[0], &conflict_entry[1],
		&conflict_entry[2], repo_index, "conflicts-one.txt"));

148
	cl_assert_equal_s("conflicts-one.txt", conflict_entry[0]->path);
Edward Thomson committed
149 150

	git_oid_fromstr(&oid, CONFLICTS_ONE_ANCESTOR_OID);
151
	cl_assert_equal_oid(&oid, &conflict_entry[0]->id);
Edward Thomson committed
152 153

	git_oid_fromstr(&oid, CONFLICTS_ONE_OUR_OID);
154
	cl_assert_equal_oid(&oid, &conflict_entry[1]->id);
Edward Thomson committed
155 156

	git_oid_fromstr(&oid, CONFLICTS_ONE_THEIR_OID);
157
	cl_assert_equal_oid(&oid, &conflict_entry[2]->id);
Edward Thomson committed
158 159 160 161

	cl_git_pass(git_index_conflict_get(&conflict_entry[0], &conflict_entry[1],
		&conflict_entry[2], repo_index, "conflicts-two.txt"));

162
	cl_assert_equal_s("conflicts-two.txt", conflict_entry[0]->path);
Edward Thomson committed
163 164

	git_oid_fromstr(&oid, CONFLICTS_TWO_ANCESTOR_OID);
165
	cl_assert_equal_oid(&oid, &conflict_entry[0]->id);
Edward Thomson committed
166 167

	git_oid_fromstr(&oid, CONFLICTS_TWO_OUR_OID);
168
	cl_assert_equal_oid(&oid, &conflict_entry[1]->id);
Edward Thomson committed
169 170

	git_oid_fromstr(&oid, CONFLICTS_TWO_THEIR_OID);
171
	cl_assert_equal_oid(&oid, &conflict_entry[2]->id);
Edward Thomson committed
172 173
}

174 175 176 177 178 179 180 181 182 183 184
void test_index_conflicts__iterate(void)
{
	git_index_conflict_iterator *iterator;
	const git_index_entry *conflict_entry[3];
	git_oid oid;

	cl_git_pass(git_index_conflict_iterator_new(&iterator, repo_index));

	cl_git_pass(git_index_conflict_next(&conflict_entry[0], &conflict_entry[1], &conflict_entry[2], iterator));

	git_oid_fromstr(&oid, CONFLICTS_ONE_ANCESTOR_OID);
185
	cl_assert_equal_oid(&oid, &conflict_entry[0]->id);
186 187 188
	cl_assert(git__strcmp(conflict_entry[0]->path, "conflicts-one.txt") == 0);

	git_oid_fromstr(&oid, CONFLICTS_ONE_OUR_OID);
189
	cl_assert_equal_oid(&oid, &conflict_entry[1]->id);
190 191 192
	cl_assert(git__strcmp(conflict_entry[0]->path, "conflicts-one.txt") == 0);

	git_oid_fromstr(&oid, CONFLICTS_ONE_THEIR_OID);
193
	cl_assert_equal_oid(&oid, &conflict_entry[2]->id);
194 195 196 197 198
	cl_assert(git__strcmp(conflict_entry[0]->path, "conflicts-one.txt") == 0);

	cl_git_pass(git_index_conflict_next(&conflict_entry[0], &conflict_entry[1], &conflict_entry[2], iterator));

	git_oid_fromstr(&oid, CONFLICTS_TWO_ANCESTOR_OID);
199
	cl_assert_equal_oid(&oid, &conflict_entry[0]->id);
200 201 202
	cl_assert(git__strcmp(conflict_entry[0]->path, "conflicts-two.txt") == 0);

	git_oid_fromstr(&oid, CONFLICTS_TWO_OUR_OID);
203
	cl_assert_equal_oid(&oid, &conflict_entry[1]->id);
204 205 206
	cl_assert(git__strcmp(conflict_entry[0]->path, "conflicts-two.txt") == 0);

	git_oid_fromstr(&oid, CONFLICTS_TWO_THEIR_OID);
207
	cl_assert_equal_oid(&oid, &conflict_entry[2]->id);
208 209 210 211 212 213 214 215 216 217 218
	cl_assert(git__strcmp(conflict_entry[0]->path, "conflicts-two.txt") == 0);

	cl_assert(git_index_conflict_next(&conflict_entry[0], &conflict_entry[1], &conflict_entry[2], iterator) == GIT_ITEROVER);

	cl_assert(conflict_entry[0] == NULL);
	cl_assert(conflict_entry[2] == NULL);
	cl_assert(conflict_entry[2] == NULL);

	git_index_conflict_iterator_free(iterator);
}

Edward Thomson committed
219 220
void test_index_conflicts__remove(void)
{
Ben Straub committed
221
	const git_index_entry *entry;
Edward Thomson committed
222
	size_t i;
223

Edward Thomson committed
224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242
	cl_assert(git_index_entrycount(repo_index) == 8);

	cl_git_pass(git_index_conflict_remove(repo_index, "conflicts-one.txt"));
	cl_assert(git_index_entrycount(repo_index) == 5);

	for (i = 0; i < git_index_entrycount(repo_index); i++) {
		cl_assert(entry = git_index_get_byindex(repo_index, i));
		cl_assert(strcmp(entry->path, "conflicts-one.txt") != 0);
	}

	cl_git_pass(git_index_conflict_remove(repo_index, "conflicts-two.txt"));
	cl_assert(git_index_entrycount(repo_index) == 2);

	for (i = 0; i < git_index_entrycount(repo_index); i++) {
		cl_assert(entry = git_index_get_byindex(repo_index, i));
		cl_assert(strcmp(entry->path, "conflicts-two.txt") != 0);
	}
}

243
void test_index_conflicts__moved_to_reuc_on_add(void)
Edward Thomson committed
244
{
Ben Straub committed
245
	const git_index_entry *entry;
Edward Thomson committed
246 247 248 249 250 251
	size_t i;

	cl_assert(git_index_entrycount(repo_index) == 8);

	cl_git_mkfile("./mergedrepo/conflicts-one.txt", "new-file\n");

252
	cl_git_pass(git_index_add_bypath(repo_index, "conflicts-one.txt"));
Edward Thomson committed
253 254 255 256 257 258 259

	cl_assert(git_index_entrycount(repo_index) == 6);

	for (i = 0; i < git_index_entrycount(repo_index); i++) {
		cl_assert(entry = git_index_get_byindex(repo_index, i));

		if (strcmp(entry->path, "conflicts-one.txt") == 0)
260
			cl_assert(!git_index_entry_is_conflict(entry));
Edward Thomson committed
261 262 263
	}
}

264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282
void test_index_conflicts__moved_to_reuc_on_remove(void)
{
	const git_index_entry *entry;
	size_t i;

	cl_assert(git_index_entrycount(repo_index) == 8);

	cl_git_pass(p_unlink("./mergedrepo/conflicts-one.txt"));

	cl_git_pass(git_index_remove_bypath(repo_index, "conflicts-one.txt"));

	cl_assert(git_index_entrycount(repo_index) == 5);

	for (i = 0; i < git_index_entrycount(repo_index); i++) {
		cl_assert(entry = git_index_get_byindex(repo_index, i));
		cl_assert(strcmp(entry->path, "conflicts-one.txt") != 0);
	}
}

Edward Thomson committed
283 284 285
void test_index_conflicts__remove_all_conflicts(void)
{
	size_t i;
Ben Straub committed
286
	const git_index_entry *entry;
Edward Thomson committed
287 288 289

	cl_assert(git_index_entrycount(repo_index) == 8);

290 291
	cl_assert_equal_i(true, git_index_has_conflicts(repo_index));

Edward Thomson committed
292 293
	git_index_conflict_cleanup(repo_index);

294 295
	cl_assert_equal_i(false, git_index_has_conflicts(repo_index));

Edward Thomson committed
296 297 298 299
	cl_assert(git_index_entrycount(repo_index) == 2);

	for (i = 0; i < git_index_entrycount(repo_index); i++) {
		cl_assert(entry = git_index_get_byindex(repo_index, i));
300
		cl_assert(!git_index_entry_is_conflict(entry));
Edward Thomson committed
301 302 303 304 305 306
	}
}

void test_index_conflicts__partial(void)
{
	git_index_entry ancestor_entry, our_entry, their_entry;
307
	const git_index_entry *conflict_entry[3];
Edward Thomson committed
308 309 310 311 312 313 314 315

	cl_assert(git_index_entrycount(repo_index) == 8);

	memset(&ancestor_entry, 0x0, sizeof(git_index_entry));
	memset(&our_entry, 0x0, sizeof(git_index_entry));
	memset(&their_entry, 0x0, sizeof(git_index_entry));

	ancestor_entry.path = "test-one.txt";
316
	ancestor_entry.mode = 0100644;
317
	GIT_IDXENTRY_STAGE_SET(&ancestor_entry, 1);
318
	git_oid_fromstr(&ancestor_entry.id, CONFLICTS_ONE_ANCESTOR_OID);
Edward Thomson committed
319 320 321 322 323 324 325

	cl_git_pass(git_index_conflict_add(repo_index, &ancestor_entry, NULL, NULL));
	cl_assert(git_index_entrycount(repo_index) == 9);

	cl_git_pass(git_index_conflict_get(&conflict_entry[0], &conflict_entry[1],
		&conflict_entry[2], repo_index, "test-one.txt"));

326
	cl_assert_equal_oid(&ancestor_entry.id, &conflict_entry[0]->id);
Edward Thomson committed
327 328 329
	cl_assert(conflict_entry[1] == NULL);
	cl_assert(conflict_entry[2] == NULL);
}
330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420

void test_index_conflicts__case_matters(void)
{
	const git_index_entry *conflict_entry[3];
	git_oid oid;
	const char *upper_case = "DIFFERS-IN-CASE.TXT";
	const char *mixed_case = "Differs-In-Case.txt";
	const char *correct_case;
	bool ignorecase = cl_repo_get_bool(repo, "core.ignorecase");

	git_index_entry ancestor_entry, our_entry, their_entry;

	memset(&ancestor_entry, 0x0, sizeof(git_index_entry));
	memset(&our_entry, 0x0, sizeof(git_index_entry));
	memset(&their_entry, 0x0, sizeof(git_index_entry));

	ancestor_entry.path = upper_case;
	GIT_IDXENTRY_STAGE_SET(&ancestor_entry, GIT_INDEX_STAGE_ANCESTOR);
	git_oid_fromstr(&ancestor_entry.id, CONFLICTS_ONE_ANCESTOR_OID);
	ancestor_entry.mode = GIT_FILEMODE_BLOB;

	our_entry.path = upper_case;
	GIT_IDXENTRY_STAGE_SET(&our_entry, GIT_INDEX_STAGE_OURS);
	git_oid_fromstr(&our_entry.id, CONFLICTS_ONE_OUR_OID);
	our_entry.mode = GIT_FILEMODE_BLOB;

	their_entry.path = upper_case;
	GIT_IDXENTRY_STAGE_SET(&their_entry, GIT_INDEX_STAGE_THEIRS);
	git_oid_fromstr(&their_entry.id, CONFLICTS_ONE_THEIR_OID);
	their_entry.mode = GIT_FILEMODE_BLOB;

	cl_git_pass(git_index_conflict_add(repo_index,
		&ancestor_entry, &our_entry, &their_entry));

	ancestor_entry.path = mixed_case;
	GIT_IDXENTRY_STAGE_SET(&ancestor_entry, GIT_INDEX_STAGE_ANCESTOR);
	git_oid_fromstr(&ancestor_entry.id, CONFLICTS_TWO_ANCESTOR_OID);
	ancestor_entry.mode = GIT_FILEMODE_BLOB;

	our_entry.path = mixed_case;
	GIT_IDXENTRY_STAGE_SET(&ancestor_entry, GIT_INDEX_STAGE_ANCESTOR);
	git_oid_fromstr(&our_entry.id, CONFLICTS_TWO_OUR_OID);
	ancestor_entry.mode = GIT_FILEMODE_BLOB;

	their_entry.path = mixed_case;
	GIT_IDXENTRY_STAGE_SET(&their_entry, GIT_INDEX_STAGE_THEIRS);
	git_oid_fromstr(&their_entry.id, CONFLICTS_TWO_THEIR_OID);
	their_entry.mode = GIT_FILEMODE_BLOB;

	cl_git_pass(git_index_conflict_add(repo_index,
		&ancestor_entry, &our_entry, &their_entry));

	cl_git_pass(git_index_conflict_get(&conflict_entry[0], &conflict_entry[1],
		&conflict_entry[2], repo_index, upper_case));

	/*
	 * We inserted with mixed case last, so on a case-insensitive
	 * fs we should get the mixed case.
	 */
	if (ignorecase)
		correct_case = mixed_case;
	else
		correct_case = upper_case;

	cl_assert_equal_s(correct_case, conflict_entry[0]->path);
	git_oid_fromstr(&oid, ignorecase ? CONFLICTS_TWO_ANCESTOR_OID : CONFLICTS_ONE_ANCESTOR_OID);
	cl_assert_equal_oid(&oid, &conflict_entry[0]->id);

	cl_assert_equal_s(correct_case, conflict_entry[1]->path);
	git_oid_fromstr(&oid, ignorecase ? CONFLICTS_TWO_OUR_OID : CONFLICTS_ONE_OUR_OID);
	cl_assert_equal_oid(&oid, &conflict_entry[1]->id);

	cl_assert_equal_s(correct_case, conflict_entry[2]->path);
	git_oid_fromstr(&oid, ignorecase ? CONFLICTS_TWO_THEIR_OID : CONFLICTS_ONE_THEIR_OID);
	cl_assert_equal_oid(&oid, &conflict_entry[2]->id);

	cl_git_pass(git_index_conflict_get(&conflict_entry[0], &conflict_entry[1],
		&conflict_entry[2], repo_index, mixed_case));

	cl_assert_equal_s(mixed_case, conflict_entry[0]->path);
	git_oid_fromstr(&oid, CONFLICTS_TWO_ANCESTOR_OID);
	cl_assert_equal_oid(&oid, &conflict_entry[0]->id);

	cl_assert_equal_s(mixed_case, conflict_entry[1]->path);
	git_oid_fromstr(&oid, CONFLICTS_TWO_OUR_OID);
	cl_assert_equal_oid(&oid, &conflict_entry[1]->id);

	cl_assert_equal_s(mixed_case, conflict_entry[2]->path);
	git_oid_fromstr(&oid, CONFLICTS_TWO_THEIR_OID);
	cl_assert_equal_oid(&oid, &conflict_entry[2]->id);
}