fromfile.c 11.7 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, NULL);
43 44

	if (error == 0) {
45
		cl_assert_equal_i(new_len, result.size);
46 47
		if (new_len)
			cl_assert(memcmp(new, result.ptr, new_len) == 0);
48 49 50 51 52 53

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

	git__free(filename);
54 55
	git_buf_dispose(&result);
	git_buf_dispose(&patchbuf);
56 57 58 59 60 61 62
	git_patch_free(patch);

	return error;
}

static int validate_and_apply_patchfile(
	const char *old,
63
	size_t old_len,
64
	const char *new,
65
	size_t new_len,
66 67 68 69 70 71 72 73 74 75
	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,
76 77
		old, old_len, "file.txt",
		new, new_len, "file.txt",
78 79 80 81 82
		diff_opts));
	cl_git_pass(git_patch_to_buf(&validated, patch_fromdiff));

	cl_assert_equal_s(patchfile, validated.ptr);

83
	error = apply_patchfile(old, old_len, new, new_len, patchfile, filename_expected, mode_expected);
84

85
	git_buf_dispose(&validated);
86 87 88 89 90 91 92
	git_patch_free(patch_fromdiff);

	return error;
}

void test_apply_fromfile__change_middle(void)
{
93 94 95 96
	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,
97
		"file.txt", 0100644));
98 99 100 101 102 103 104
}

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

105 106 107 108
	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,
109
		&diff_opts, "file.txt", 0100644));
110 111
}

112

113 114
void test_apply_fromfile__change_firstline(void)
{
115 116 117 118
	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,
119
		"file.txt", 0100644));
120 121 122 123
}

void test_apply_fromfile__lastline(void)
{
124 125 126 127
	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,
128
		"file.txt", 0100644));
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 172
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));
}

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

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

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

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

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

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

void test_apply_fromfile__prepend_and_append(void)
{
215 216 217 218
	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,
219
		"file.txt", 0100644));
220 221 222 223
}

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

void test_apply_fromfile__empty_context(void)
{
341 342 343 344
	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,
345
		"file.txt", 0100644));
346 347 348 349 350
}

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

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

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

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

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

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

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

403 404 405 406 407
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,
408
		PATCH_BINARY_DELTA, "binary.bin", 0100644));
409
}
410

411 412 413 414 415
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,
416
		PATCH_BINARY_LITERAL, "binary.bin", 0100644));
417
}
418

419 420 421 422 423 424 425
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));
}
426

427 428 429 430 431 432
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,
433
		PATCH_BINARY_DELTA, "binary.bin", 0100644));
434
}
435

436 437 438 439 440 441
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));
442
}
443 444 445 446 447

void test_apply_fromfile__empty_file_not_allowed(void)
{
	git_patch *patch;

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