conflicts.c 15.3 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

static git_repository *repo;
static git_index *repo_index;

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

12
/* Fixture setup and teardown */
Edward Thomson committed
13 14 15 16 17 18 19 20 21
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_INDEX_ENTRY_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_INDEX_ENTRY_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_INDEX_ENTRY_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_INDEX_ENTRY_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_INDEX_ENTRY_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_INDEX_ENTRY_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 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
void test_index_conflicts__add_detects_invalid_filemode(void)
{
	git_index_entry ancestor_entry, our_entry, their_entry;
	git_index_entry *conflict_entry[3];
	int i;

	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));

	conflict_entry[0] = &ancestor_entry;
	conflict_entry[1] = &our_entry;
	conflict_entry[2] = &their_entry;

	for (i = 0; i < 3; i++) {
		ancestor_entry.path = "test-one.txt";
		ancestor_entry.mode = 0100644;
113
		GIT_INDEX_ENTRY_STAGE_SET(&ancestor_entry, 3);
114 115 116 117
		git_oid_fromstr(&ancestor_entry.id, CONFLICTS_ONE_ANCESTOR_OID);

		our_entry.path = "test-one.txt";
		our_entry.mode = 0100644;
118
		GIT_INDEX_ENTRY_STAGE_SET(&our_entry, 1);
119 120 121 122
		git_oid_fromstr(&our_entry.id, CONFLICTS_ONE_OUR_OID);

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

		/* Corrupt the conflict entry's mode */
		conflict_entry[i]->mode = 027431745;

		cl_git_fail(git_index_conflict_add(repo_index, &ancestor_entry, &our_entry, &their_entry));
	}

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


136 137
void test_index_conflicts__add_removes_stage_zero(void)
{
138
	git_index_entry ancestor_entry, our_entry, their_entry;
139 140 141 142 143 144 145 146
	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));

147 148
	cl_git_mkfile("./mergedrepo/test-one.txt", "new-file\n");
	cl_git_pass(git_index_add_bypath(repo_index, "test-one.txt"));
149 150 151 152
	cl_assert(git_index_entrycount(repo_index) == 9);

	ancestor_entry.path = "test-one.txt";
	ancestor_entry.mode = 0100644;
153
	GIT_INDEX_ENTRY_STAGE_SET(&ancestor_entry, 3);
154
	git_oid_fromstr(&ancestor_entry.id, CONFLICTS_ONE_ANCESTOR_OID);
155 156 157

	our_entry.path = "test-one.txt";
	our_entry.mode = 0100644;
158
	GIT_INDEX_ENTRY_STAGE_SET(&our_entry, 1);
159
	git_oid_fromstr(&our_entry.id, CONFLICTS_ONE_OUR_OID);
160 161 162

	their_entry.path = "test-one.txt";
	their_entry.mode = 0100644;
163
	GIT_INDEX_ENTRY_STAGE_SET(&their_entry, 2);
164
	git_oid_fromstr(&their_entry.id, CONFLICTS_ONE_THEIR_OID);
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181

	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
182 183
void test_index_conflicts__get(void)
{
184
	const git_index_entry *conflict_entry[3];
Edward Thomson committed
185 186 187 188 189
	git_oid oid;

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

190
	cl_assert_equal_s("conflicts-one.txt", conflict_entry[0]->path);
Edward Thomson committed
191 192

	git_oid_fromstr(&oid, CONFLICTS_ONE_ANCESTOR_OID);
193
	cl_assert_equal_oid(&oid, &conflict_entry[0]->id);
Edward Thomson committed
194 195

	git_oid_fromstr(&oid, CONFLICTS_ONE_OUR_OID);
196
	cl_assert_equal_oid(&oid, &conflict_entry[1]->id);
Edward Thomson committed
197 198

	git_oid_fromstr(&oid, CONFLICTS_ONE_THEIR_OID);
199
	cl_assert_equal_oid(&oid, &conflict_entry[2]->id);
Edward Thomson committed
200 201 202 203

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

204
	cl_assert_equal_s("conflicts-two.txt", conflict_entry[0]->path);
Edward Thomson committed
205 206

	git_oid_fromstr(&oid, CONFLICTS_TWO_ANCESTOR_OID);
207
	cl_assert_equal_oid(&oid, &conflict_entry[0]->id);
Edward Thomson committed
208 209

	git_oid_fromstr(&oid, CONFLICTS_TWO_OUR_OID);
210
	cl_assert_equal_oid(&oid, &conflict_entry[1]->id);
Edward Thomson committed
211 212

	git_oid_fromstr(&oid, CONFLICTS_TWO_THEIR_OID);
213
	cl_assert_equal_oid(&oid, &conflict_entry[2]->id);
Edward Thomson committed
214 215
}

216 217 218 219 220 221 222 223 224 225 226
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);
227
	cl_assert_equal_oid(&oid, &conflict_entry[0]->id);
228 229 230
	cl_assert(git__strcmp(conflict_entry[0]->path, "conflicts-one.txt") == 0);

	git_oid_fromstr(&oid, CONFLICTS_ONE_OUR_OID);
231
	cl_assert_equal_oid(&oid, &conflict_entry[1]->id);
232 233 234
	cl_assert(git__strcmp(conflict_entry[0]->path, "conflicts-one.txt") == 0);

	git_oid_fromstr(&oid, CONFLICTS_ONE_THEIR_OID);
235
	cl_assert_equal_oid(&oid, &conflict_entry[2]->id);
236 237 238 239 240
	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);
241
	cl_assert_equal_oid(&oid, &conflict_entry[0]->id);
242 243 244
	cl_assert(git__strcmp(conflict_entry[0]->path, "conflicts-two.txt") == 0);

	git_oid_fromstr(&oid, CONFLICTS_TWO_OUR_OID);
245
	cl_assert_equal_oid(&oid, &conflict_entry[1]->id);
246 247 248
	cl_assert(git__strcmp(conflict_entry[0]->path, "conflicts-two.txt") == 0);

	git_oid_fromstr(&oid, CONFLICTS_TWO_THEIR_OID);
249
	cl_assert_equal_oid(&oid, &conflict_entry[2]->id);
250 251 252 253 254 255 256 257 258 259 260
	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
261 262
void test_index_conflicts__remove(void)
{
Ben Straub committed
263
	const git_index_entry *entry;
Edward Thomson committed
264
	size_t i;
265

Edward Thomson committed
266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284
	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);
	}
}

285
void test_index_conflicts__moved_to_reuc_on_add(void)
Edward Thomson committed
286
{
Ben Straub committed
287
	const git_index_entry *entry;
Edward Thomson committed
288 289 290 291 292 293
	size_t i;

	cl_assert(git_index_entrycount(repo_index) == 8);

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

294
	cl_git_pass(git_index_add_bypath(repo_index, "conflicts-one.txt"));
Edward Thomson committed
295 296 297 298 299 300 301

	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)
302
			cl_assert(!git_index_entry_is_conflict(entry));
Edward Thomson committed
303 304 305
	}
}

306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324
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
325 326 327
void test_index_conflicts__remove_all_conflicts(void)
{
	size_t i;
Ben Straub committed
328
	const git_index_entry *entry;
Edward Thomson committed
329 330 331

	cl_assert(git_index_entrycount(repo_index) == 8);

332 333
	cl_assert_equal_i(true, git_index_has_conflicts(repo_index));

Edward Thomson committed
334 335
	git_index_conflict_cleanup(repo_index);

336 337
	cl_assert_equal_i(false, git_index_has_conflicts(repo_index));

Edward Thomson committed
338 339 340 341
	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));
342
		cl_assert(!git_index_entry_is_conflict(entry));
Edward Thomson committed
343 344 345 346 347 348
	}
}

void test_index_conflicts__partial(void)
{
	git_index_entry ancestor_entry, our_entry, their_entry;
349
	const git_index_entry *conflict_entry[3];
Edward Thomson committed
350 351 352 353 354 355 356 357

	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";
358
	ancestor_entry.mode = 0100644;
359
	GIT_INDEX_ENTRY_STAGE_SET(&ancestor_entry, 1);
360
	git_oid_fromstr(&ancestor_entry.id, CONFLICTS_ONE_ANCESTOR_OID);
Edward Thomson committed
361 362 363 364 365 366 367

	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"));

368
	cl_assert_equal_oid(&ancestor_entry.id, &conflict_entry[0]->id);
Edward Thomson committed
369 370 371
	cl_assert(conflict_entry[1] == NULL);
	cl_assert(conflict_entry[2] == NULL);
}
372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388

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;
389
	GIT_INDEX_ENTRY_STAGE_SET(&ancestor_entry, GIT_INDEX_STAGE_ANCESTOR);
390 391 392 393
	git_oid_fromstr(&ancestor_entry.id, CONFLICTS_ONE_ANCESTOR_OID);
	ancestor_entry.mode = GIT_FILEMODE_BLOB;

	our_entry.path = upper_case;
394
	GIT_INDEX_ENTRY_STAGE_SET(&our_entry, GIT_INDEX_STAGE_OURS);
395 396 397 398
	git_oid_fromstr(&our_entry.id, CONFLICTS_ONE_OUR_OID);
	our_entry.mode = GIT_FILEMODE_BLOB;

	their_entry.path = upper_case;
399
	GIT_INDEX_ENTRY_STAGE_SET(&their_entry, GIT_INDEX_STAGE_THEIRS);
400 401 402 403 404 405 406
	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;
407
	GIT_INDEX_ENTRY_STAGE_SET(&ancestor_entry, GIT_INDEX_STAGE_ANCESTOR);
408 409 410 411
	git_oid_fromstr(&ancestor_entry.id, CONFLICTS_TWO_ANCESTOR_OID);
	ancestor_entry.mode = GIT_FILEMODE_BLOB;

	our_entry.path = mixed_case;
412
	GIT_INDEX_ENTRY_STAGE_SET(&ancestor_entry, GIT_INDEX_STAGE_ANCESTOR);
413 414 415 416
	git_oid_fromstr(&our_entry.id, CONFLICTS_TWO_OUR_OID);
	ancestor_entry.mode = GIT_FILEMODE_BLOB;

	their_entry.path = mixed_case;
417
	GIT_INDEX_ENTRY_STAGE_SET(&their_entry, GIT_INDEX_STAGE_THEIRS);
418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462
	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);
}