fromfile.c 11.6 KB
Newer Older
1 2 3 4
#include "clar_libgit2.h"
#include "git2/sys/repository.h"

#include "apply.h"
5
#include "patch.h"
6
#include "patch_parse.h"
7 8 9
#include "repository.h"
#include "buf_text.h"

10
#include "../patch/patch_common.h"
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25

static git_repository *repo = NULL;

void test_apply_fromfile__initialize(void)
{
	repo = cl_git_sandbox_init("renames");
}

void test_apply_fromfile__cleanup(void)
{
	cl_git_sandbox_cleanup();
}

static int apply_patchfile(
	const char *old,
26
	size_t old_len,
27
	const char *new,
28
	size_t new_len,
29 30 31 32 33 34 35 36 37 38 39
	const char *patchfile,
	const char *filename_expected,
	unsigned int mode_expected)
{
	git_patch *patch;
	git_buf result = GIT_BUF_INIT;
	git_buf patchbuf = GIT_BUF_INIT;
	char *filename;
	unsigned int mode;
	int error;

40
	cl_git_pass(git_patch_from_buffer(&patch, patchfile, strlen(patchfile), NULL));
41

42
	error = git_apply__patch(&result, &filename, &mode, old, old_len, patch);
43 44

	if (error == 0) {
45 46
		cl_assert_equal_i(new_len, result.size);
		cl_assert(memcmp(new, result.ptr, new_len) == 0);
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61

		cl_assert_equal_s(filename_expected, filename);
		cl_assert_equal_i(mode_expected, mode);
	}

	git__free(filename);
	git_buf_free(&result);
	git_buf_free(&patchbuf);
	git_patch_free(patch);

	return error;
}

static int validate_and_apply_patchfile(
	const char *old,
62
	size_t old_len,
63
	const char *new,
64
	size_t new_len,
65 66 67 68 69 70 71 72 73 74
	const char *patchfile,
	const git_diff_options *diff_opts,
	const char *filename_expected,
	unsigned int mode_expected)
{
	git_patch *patch_fromdiff;
	git_buf validated = GIT_BUF_INIT;
	int error;

	cl_git_pass(git_patch_from_buffers(&patch_fromdiff,
75 76
		old, old_len, "file.txt",
		new, new_len, "file.txt",
77 78 79 80 81
		diff_opts));
	cl_git_pass(git_patch_to_buf(&validated, patch_fromdiff));

	cl_assert_equal_s(patchfile, validated.ptr);

82
	error = apply_patchfile(old, old_len, new, new_len, patchfile, filename_expected, mode_expected);
83 84 85 86 87 88 89 90 91

	git_buf_free(&validated);
	git_patch_free(patch_fromdiff);

	return error;
}

void test_apply_fromfile__change_middle(void)
{
92 93 94 95
	cl_git_pass(validate_and_apply_patchfile(
		FILE_ORIGINAL, strlen(FILE_ORIGINAL),
		FILE_CHANGE_MIDDLE, strlen(FILE_CHANGE_MIDDLE),
		PATCH_ORIGINAL_TO_CHANGE_MIDDLE, NULL,
96
		"file.txt", 0100644));
97 98 99 100 101 102 103
}

void test_apply_fromfile__change_middle_nocontext(void)
{
	git_diff_options diff_opts = GIT_DIFF_OPTIONS_INIT;
	diff_opts.context_lines = 0;

104 105 106 107
	cl_git_pass(validate_and_apply_patchfile(
		FILE_ORIGINAL, strlen(FILE_ORIGINAL),
		FILE_CHANGE_MIDDLE, strlen(FILE_CHANGE_MIDDLE),
		PATCH_ORIGINAL_TO_CHANGE_MIDDLE_NOCONTEXT,
108
		&diff_opts, "file.txt", 0100644));
109 110
}

111

112 113
void test_apply_fromfile__change_firstline(void)
{
114 115 116 117
	cl_git_pass(validate_and_apply_patchfile(
		FILE_ORIGINAL, strlen(FILE_ORIGINAL),
		FILE_CHANGE_FIRSTLINE, strlen(FILE_CHANGE_FIRSTLINE),
		PATCH_ORIGINAL_TO_CHANGE_FIRSTLINE, NULL,
118
		"file.txt", 0100644));
119 120 121 122
}

void test_apply_fromfile__lastline(void)
{
123 124 125 126
	cl_git_pass(validate_and_apply_patchfile(
		FILE_ORIGINAL, strlen(FILE_ORIGINAL),
		FILE_CHANGE_LASTLINE, strlen(FILE_CHANGE_LASTLINE),
		PATCH_ORIGINAL_TO_CHANGE_LASTLINE, NULL,
127
		"file.txt", 0100644));
128 129
}

130 131 132 133 134 135 136 137 138 139 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 170 171
void test_apply_fromfile__change_middle_shrink(void)
{
	cl_git_pass(validate_and_apply_patchfile(
		FILE_ORIGINAL, strlen(FILE_ORIGINAL),
		FILE_CHANGE_MIDDLE_SHRINK, strlen(FILE_CHANGE_MIDDLE_SHRINK),
		PATCH_ORIGINAL_TO_CHANGE_MIDDLE_SHRINK, NULL,
		"file.txt", 0100644));
}

void test_apply_fromfile__change_middle_shrink_nocontext(void)
{
	git_diff_options diff_opts = GIT_DIFF_OPTIONS_INIT;
	diff_opts.context_lines = 0;

	cl_git_pass(validate_and_apply_patchfile(
		FILE_ORIGINAL, strlen(FILE_ORIGINAL),
		FILE_CHANGE_MIDDLE_SHRINK, strlen(FILE_CHANGE_MIDDLE_SHRINK),
		PATCH_ORIGINAL_TO_MIDDLE_SHRINK_NOCONTEXT, &diff_opts,
		"file.txt", 0100644));
}

void test_apply_fromfile__change_middle_grow(void)
{
	cl_git_pass(validate_and_apply_patchfile(
		FILE_ORIGINAL, strlen(FILE_ORIGINAL),
		FILE_CHANGE_MIDDLE_GROW, strlen(FILE_CHANGE_MIDDLE_GROW),
		PATCH_ORIGINAL_TO_CHANGE_MIDDLE_GROW, NULL,
		"file.txt", 0100644));
}

void test_apply_fromfile__change_middle_grow_nocontext(void)
{
	git_diff_options diff_opts = GIT_DIFF_OPTIONS_INIT;
	diff_opts.context_lines = 0;

	cl_git_pass(validate_and_apply_patchfile(
		FILE_ORIGINAL, strlen(FILE_ORIGINAL),
		FILE_CHANGE_MIDDLE_GROW, strlen(FILE_CHANGE_MIDDLE_GROW),
		PATCH_ORIGINAL_TO_MIDDLE_GROW_NOCONTEXT, &diff_opts,
		"file.txt", 0100644));
}

172 173
void test_apply_fromfile__prepend(void)
{
174 175 176
	cl_git_pass(validate_and_apply_patchfile(
		FILE_ORIGINAL, strlen(FILE_ORIGINAL),
		FILE_PREPEND, strlen(FILE_PREPEND),
177
		PATCH_ORIGINAL_TO_PREPEND, NULL, "file.txt", 0100644));
178 179 180 181 182 183 184
}

void test_apply_fromfile__prepend_nocontext(void)
{
	git_diff_options diff_opts = GIT_DIFF_OPTIONS_INIT;
	diff_opts.context_lines = 0;

185 186 187
	cl_git_pass(validate_and_apply_patchfile(
		FILE_ORIGINAL, strlen(FILE_ORIGINAL),
		FILE_PREPEND, strlen(FILE_PREPEND),
188
		PATCH_ORIGINAL_TO_PREPEND_NOCONTEXT, &diff_opts,
189
		"file.txt", 0100644));
190 191 192 193
}

void test_apply_fromfile__append(void)
{
194 195 196
	cl_git_pass(validate_and_apply_patchfile(
		FILE_ORIGINAL, strlen(FILE_ORIGINAL),
		FILE_APPEND, strlen(FILE_APPEND),
197
		PATCH_ORIGINAL_TO_APPEND, NULL, "file.txt", 0100644));
198 199 200 201 202 203 204
}

void test_apply_fromfile__append_nocontext(void)
{
	git_diff_options diff_opts = GIT_DIFF_OPTIONS_INIT;
	diff_opts.context_lines = 0;

205 206 207
	cl_git_pass(validate_and_apply_patchfile(
		FILE_ORIGINAL, strlen(FILE_ORIGINAL),
		FILE_APPEND, strlen(FILE_APPEND),
208
		PATCH_ORIGINAL_TO_APPEND_NOCONTEXT, &diff_opts,
209
		"file.txt", 0100644));
210 211 212 213
}

void test_apply_fromfile__prepend_and_append(void)
{
214 215 216 217
	cl_git_pass(validate_and_apply_patchfile(
		FILE_ORIGINAL, strlen(FILE_ORIGINAL),
		FILE_PREPEND_AND_APPEND, strlen(FILE_PREPEND_AND_APPEND),
		PATCH_ORIGINAL_TO_PREPEND_AND_APPEND, NULL,
218
		"file.txt", 0100644));
219 220 221 222
}

void test_apply_fromfile__to_empty_file(void)
{
223 224 225
	cl_git_pass(validate_and_apply_patchfile(
		FILE_ORIGINAL, strlen(FILE_ORIGINAL),
		"", 0,
226
		PATCH_ORIGINAL_TO_EMPTY_FILE, NULL, "file.txt", 0100644));
227 228 229 230
}

void test_apply_fromfile__from_empty_file(void)
{
231 232 233
	cl_git_pass(validate_and_apply_patchfile(
		"", 0,
		FILE_ORIGINAL, strlen(FILE_ORIGINAL),
234
		PATCH_EMPTY_FILE_TO_ORIGINAL, NULL, "file.txt", 0100644));
235 236 237 238
}

void test_apply_fromfile__add(void)
{
239 240 241
	cl_git_pass(validate_and_apply_patchfile(
		NULL, 0,
		FILE_ORIGINAL, strlen(FILE_ORIGINAL),
242
		PATCH_ADD_ORIGINAL, NULL, "file.txt", 0100644));
243 244 245 246
}

void test_apply_fromfile__delete(void)
{
247 248 249
	cl_git_pass(validate_and_apply_patchfile(
		FILE_ORIGINAL, strlen(FILE_ORIGINAL),
		NULL, 0,
250 251 252 253 254 255
		PATCH_DELETE_ORIGINAL, NULL, NULL, 0));
}


void test_apply_fromfile__rename_exact(void)
{
256 257 258
	cl_git_pass(apply_patchfile(
		FILE_ORIGINAL, strlen(FILE_ORIGINAL),
		FILE_ORIGINAL, strlen(FILE_ORIGINAL),
259
		PATCH_RENAME_EXACT, "newfile.txt", 0100644));
260 261 262 263
}

void test_apply_fromfile__rename_similar(void)
{
264 265 266
	cl_git_pass(apply_patchfile(
		FILE_ORIGINAL, strlen(FILE_ORIGINAL),
		FILE_CHANGE_MIDDLE, strlen(FILE_CHANGE_MIDDLE),
267
		PATCH_RENAME_SIMILAR, "newfile.txt", 0100644));
268 269 270 271
}

void test_apply_fromfile__rename_similar_quotedname(void)
{
272 273 274
	cl_git_pass(apply_patchfile(
		FILE_ORIGINAL, strlen(FILE_ORIGINAL),
		FILE_CHANGE_MIDDLE, strlen(FILE_CHANGE_MIDDLE),
275
		PATCH_RENAME_SIMILAR_QUOTEDNAME, "foo\"bar.txt", 0100644));
276 277 278 279
}

void test_apply_fromfile__modechange(void)
{
280 281 282
	cl_git_pass(apply_patchfile(
		FILE_ORIGINAL, strlen(FILE_ORIGINAL),
		FILE_ORIGINAL, strlen(FILE_ORIGINAL),
283
		PATCH_MODECHANGE_UNCHANGED, "file.txt", 0100755));
284 285 286 287
}

void test_apply_fromfile__modechange_with_modification(void)
{
288 289 290
	cl_git_pass(apply_patchfile(
		FILE_ORIGINAL, strlen(FILE_ORIGINAL),
		FILE_CHANGE_MIDDLE, strlen(FILE_CHANGE_MIDDLE),
291
		PATCH_MODECHANGE_MODIFIED, "file.txt", 0100755));
292 293 294 295
}

void test_apply_fromfile__noisy(void)
{
296 297 298
	cl_git_pass(apply_patchfile(
		FILE_ORIGINAL, strlen(FILE_ORIGINAL),
		FILE_CHANGE_MIDDLE, strlen(FILE_CHANGE_MIDDLE),
299
		PATCH_NOISY, "file.txt", 0100644));
300 301 302 303
}

void test_apply_fromfile__noisy_nocontext(void)
{
304 305 306
	cl_git_pass(apply_patchfile(
		FILE_ORIGINAL, strlen(FILE_ORIGINAL),
		FILE_CHANGE_MIDDLE, strlen(FILE_CHANGE_MIDDLE),
307
		PATCH_NOISY_NOCONTEXT, "file.txt", 0100644));
308 309 310 311 312
}

void test_apply_fromfile__fail_truncated_1(void)
{
	git_patch *patch;
313
	cl_git_fail(git_patch_from_buffer(&patch, PATCH_TRUNCATED_1,
314
		strlen(PATCH_TRUNCATED_1), NULL));
315 316 317 318 319
}

void test_apply_fromfile__fail_truncated_2(void)
{
	git_patch *patch;
320
	cl_git_fail(git_patch_from_buffer(&patch, PATCH_TRUNCATED_2,
321
		strlen(PATCH_TRUNCATED_2), NULL));
322 323 324 325 326
}

void test_apply_fromfile__fail_truncated_3(void)
{
	git_patch *patch;
327
	cl_git_fail(git_patch_from_buffer(&patch, PATCH_TRUNCATED_3,
328
		strlen(PATCH_TRUNCATED_3), NULL));
329 330 331 332 333
}

void test_apply_fromfile__fail_corrupt_githeader(void)
{
	git_patch *patch;
334
	cl_git_fail(git_patch_from_buffer(&patch, PATCH_CORRUPT_GIT_HEADER,
335
		strlen(PATCH_CORRUPT_GIT_HEADER), NULL));
336 337 338 339
}

void test_apply_fromfile__empty_context(void)
{
340 341 342 343
	cl_git_pass(apply_patchfile(
		FILE_EMPTY_CONTEXT_ORIGINAL, strlen(FILE_EMPTY_CONTEXT_ORIGINAL),
		FILE_EMPTY_CONTEXT_MODIFIED, strlen(FILE_EMPTY_CONTEXT_MODIFIED),
		PATCH_EMPTY_CONTEXT,
344
		"file.txt", 0100644));
345 346 347 348 349
}

void test_apply_fromfile__append_no_nl(void)
{
	cl_git_pass(validate_and_apply_patchfile(
350 351
		FILE_ORIGINAL, strlen(FILE_ORIGINAL),
		FILE_APPEND_NO_NL, strlen(FILE_APPEND_NO_NL),
352
		PATCH_APPEND_NO_NL, NULL, "file.txt", 0100644));
353 354 355 356 357
}

void test_apply_fromfile__fail_missing_new_file(void)
{
	git_patch *patch;
358
	cl_git_fail(git_patch_from_buffer(&patch,
359
		PATCH_CORRUPT_MISSING_NEW_FILE,
360
		strlen(PATCH_CORRUPT_MISSING_NEW_FILE), NULL));
361 362 363 364 365
}

void test_apply_fromfile__fail_missing_old_file(void)
{
	git_patch *patch;
366
	cl_git_fail(git_patch_from_buffer(&patch,
367
		PATCH_CORRUPT_MISSING_OLD_FILE,
368
		strlen(PATCH_CORRUPT_MISSING_OLD_FILE), NULL));
369 370 371 372 373
}

void test_apply_fromfile__fail_no_changes(void)
{
	git_patch *patch;
374
	cl_git_fail(git_patch_from_buffer(&patch,
375
		PATCH_CORRUPT_NO_CHANGES,
376
		strlen(PATCH_CORRUPT_NO_CHANGES), NULL));
377 378 379 380 381
}

void test_apply_fromfile__fail_missing_hunk_header(void)
{
	git_patch *patch;
382
	cl_git_fail(git_patch_from_buffer(&patch,
383
		PATCH_CORRUPT_MISSING_HUNK_HEADER,
384
		strlen(PATCH_CORRUPT_MISSING_HUNK_HEADER), NULL));
385 386 387 388 389
}

void test_apply_fromfile__fail_not_a_patch(void)
{
	git_patch *patch;
390
	cl_git_fail(git_patch_from_buffer(&patch, PATCH_NOT_A_PATCH,
391
		strlen(PATCH_NOT_A_PATCH), NULL));
392
}
393

394
void test_apply_fromfile__binary_add(void)
395
{
396 397 398
	cl_git_pass(apply_patchfile(
		NULL, 0,
		FILE_BINARY_DELTA_MODIFIED, FILE_BINARY_DELTA_MODIFIED_LEN,
399
		PATCH_BINARY_ADD, "binary.bin", 0100644));
400
}
401

402 403 404 405 406
void test_apply_fromfile__binary_change_delta(void)
{
	cl_git_pass(apply_patchfile(
		FILE_BINARY_DELTA_ORIGINAL, FILE_BINARY_DELTA_ORIGINAL_LEN,
		FILE_BINARY_DELTA_MODIFIED, FILE_BINARY_DELTA_MODIFIED_LEN,
407
		PATCH_BINARY_DELTA, "binary.bin", 0100644));
408
}
409

410 411 412 413 414
void test_apply_fromfile__binary_change_literal(void)
{
	cl_git_pass(apply_patchfile(
		FILE_BINARY_LITERAL_ORIGINAL, FILE_BINARY_LITERAL_ORIGINAL_LEN,
		FILE_BINARY_LITERAL_MODIFIED, FILE_BINARY_LITERAL_MODIFIED_LEN,
415
		PATCH_BINARY_LITERAL, "binary.bin", 0100644));
416
}
417

418 419 420 421 422 423 424
void test_apply_fromfile__binary_delete(void)
{
	cl_git_pass(apply_patchfile(
		FILE_BINARY_DELTA_MODIFIED, FILE_BINARY_DELTA_MODIFIED_LEN,
		NULL, 0,
		PATCH_BINARY_DELETE, NULL, 0));
}
425

426 427 428 429 430 431
void test_apply_fromfile__binary_change_does_not_apply(void)
{
	/* try to apply patch backwards, ensure it does not apply */
	cl_git_fail(apply_patchfile(
		FILE_BINARY_DELTA_MODIFIED, FILE_BINARY_DELTA_MODIFIED_LEN,
		FILE_BINARY_DELTA_ORIGINAL, FILE_BINARY_DELTA_ORIGINAL_LEN,
432
		PATCH_BINARY_DELTA, "binary.bin", 0100644));
433
}
434

435 436 437 438 439 440
void test_apply_fromfile__binary_change_must_be_reversible(void)
{
	cl_git_fail(apply_patchfile(
		FILE_BINARY_DELTA_MODIFIED, FILE_BINARY_DELTA_MODIFIED_LEN,
		NULL, 0,
		PATCH_BINARY_NOT_REVERSIBLE, NULL, 0));
441
}
442 443 444 445 446

void test_apply_fromfile__empty_file_not_allowed(void)
{
	git_patch *patch;

447 448
	cl_git_fail(git_patch_from_buffer(&patch, "", 0, NULL));
	cl_git_fail(git_patch_from_buffer(&patch, NULL, 0, NULL));
449
}