]>
Commit | Line | Data |
---|---|---|
7cb904ba ET |
1 | #include "clar_libgit2.h" |
2 | #include "git2/sys/repository.h" | |
3 | ||
4 | #include "apply.h" | |
5 | #include "repository.h" | |
7cb904ba | 6 | |
8bca8b9e | 7 | #include "../patch/patch_common.h" |
7cb904ba ET |
8 | |
9 | static git_repository *repo = NULL; | |
3149ff6f | 10 | static git_diff_options binary_opts = GIT_DIFF_OPTIONS_INIT; |
7cb904ba ET |
11 | |
12 | void test_apply_fromdiff__initialize(void) | |
13 | { | |
14 | repo = cl_git_sandbox_init("renames"); | |
3149ff6f ET |
15 | |
16 | binary_opts.flags |= GIT_DIFF_SHOW_BINARY; | |
7cb904ba ET |
17 | } |
18 | ||
19 | void test_apply_fromdiff__cleanup(void) | |
20 | { | |
21 | cl_git_sandbox_cleanup(); | |
22 | } | |
23 | ||
3149ff6f | 24 | static int apply_gitbuf( |
e579e0f7 | 25 | const git_str *old, |
7cb904ba | 26 | const char *oldname, |
e579e0f7 | 27 | const git_str *new, |
7cb904ba ET |
28 | const char *newname, |
29 | const char *patch_expected, | |
30 | const git_diff_options *diff_opts) | |
31 | { | |
32 | git_patch *patch; | |
e579e0f7 | 33 | git_str result = GIT_STR_INIT; |
7cb904ba ET |
34 | git_buf patchbuf = GIT_BUF_INIT; |
35 | char *filename; | |
36 | unsigned int mode; | |
37 | int error; | |
38 | ||
39 | cl_git_pass(git_patch_from_buffers(&patch, | |
3149ff6f ET |
40 | old ? old->ptr : NULL, old ? old->size : 0, |
41 | oldname, | |
42 | new ? new->ptr : NULL, new ? new->size : 0, | |
43 | newname, | |
7cb904ba | 44 | diff_opts)); |
7cb904ba | 45 | |
3149ff6f ET |
46 | if (patch_expected) { |
47 | cl_git_pass(git_patch_to_buf(&patchbuf, patch)); | |
48 | cl_assert_equal_s(patch_expected, patchbuf.ptr); | |
49 | } | |
7cb904ba | 50 | |
ac3d33df | 51 | error = git_apply__patch(&result, &filename, &mode, old ? old->ptr : NULL, old ? old->size : 0, patch, NULL); |
7cb904ba ET |
52 | |
53 | if (error == 0 && new == NULL) { | |
54 | cl_assert_equal_i(0, result.size); | |
55 | cl_assert_equal_p(NULL, filename); | |
56 | cl_assert_equal_i(0, mode); | |
3149ff6f ET |
57 | } |
58 | else if (error == 0) { | |
59 | cl_assert_equal_s(new->ptr, result.ptr); | |
60 | cl_assert_equal_s(newname ? newname : oldname, filename); | |
7cb904ba ET |
61 | cl_assert_equal_i(0100644, mode); |
62 | } | |
63 | ||
64 | git__free(filename); | |
e579e0f7 | 65 | git_str_dispose(&result); |
ac3d33df | 66 | git_buf_dispose(&patchbuf); |
7cb904ba ET |
67 | git_patch_free(patch); |
68 | ||
69 | return error; | |
70 | } | |
71 | ||
3149ff6f ET |
72 | static int apply_buf( |
73 | const char *old, | |
74 | const char *oldname, | |
75 | const char *new, | |
76 | const char *newname, | |
77 | const char *patch_expected, | |
78 | const git_diff_options *diff_opts) | |
79 | { | |
e579e0f7 | 80 | git_str o = GIT_STR_INIT, n = GIT_STR_INIT, |
3149ff6f ET |
81 | *optr = NULL, *nptr = NULL; |
82 | ||
83 | if (old) { | |
84 | o.ptr = (char *)old; | |
85 | o.size = strlen(old); | |
86 | optr = &o; | |
87 | } | |
88 | ||
89 | if (new) { | |
90 | n.ptr = (char *)new; | |
91 | n.size = strlen(new); | |
92 | nptr = &n; | |
93 | } | |
94 | ||
95 | return apply_gitbuf(optr, oldname, nptr, newname, patch_expected, diff_opts); | |
96 | } | |
97 | ||
7cb904ba ET |
98 | void test_apply_fromdiff__change_middle(void) |
99 | { | |
100 | cl_git_pass(apply_buf( | |
101 | FILE_ORIGINAL, "file.txt", | |
102 | FILE_CHANGE_MIDDLE, "file.txt", | |
103 | PATCH_ORIGINAL_TO_CHANGE_MIDDLE, NULL)); | |
104 | } | |
105 | ||
106 | void test_apply_fromdiff__change_middle_nocontext(void) | |
107 | { | |
108 | git_diff_options diff_opts = GIT_DIFF_OPTIONS_INIT; | |
109 | diff_opts.context_lines = 0; | |
110 | ||
111 | cl_git_pass(apply_buf( | |
112 | FILE_ORIGINAL, "file.txt", | |
113 | FILE_CHANGE_MIDDLE, "file.txt", | |
114 | PATCH_ORIGINAL_TO_CHANGE_MIDDLE_NOCONTEXT, &diff_opts)); | |
115 | } | |
116 | ||
117 | void test_apply_fromdiff__change_firstline(void) | |
118 | { | |
119 | cl_git_pass(apply_buf( | |
120 | FILE_ORIGINAL, "file.txt", | |
121 | FILE_CHANGE_FIRSTLINE, "file.txt", | |
122 | PATCH_ORIGINAL_TO_CHANGE_FIRSTLINE, NULL)); | |
123 | } | |
124 | ||
125 | void test_apply_fromdiff__lastline(void) | |
126 | { | |
127 | cl_git_pass(apply_buf( | |
128 | FILE_ORIGINAL, "file.txt", | |
129 | FILE_CHANGE_LASTLINE, "file.txt", | |
130 | PATCH_ORIGINAL_TO_CHANGE_LASTLINE, NULL)); | |
131 | } | |
132 | ||
22a2d3d5 UG |
133 | void test_apply_fromdiff__change_middle_and_lastline_nocontext(void) |
134 | { | |
135 | git_diff_options diff_opts = GIT_DIFF_OPTIONS_INIT; | |
136 | diff_opts.context_lines = 0; | |
137 | ||
138 | cl_git_pass(apply_buf( | |
139 | FILE_ORIGINAL, "file.txt", | |
140 | FILE_CHANGE_MIDDLE_AND_LASTLINE, "file.txt", | |
141 | PATCH_ORIGINAL_TO_CHANGE_MIDDLE_AND_LASTLINE_NOCONTEXT, &diff_opts)); | |
142 | } | |
143 | ||
7cb904ba ET |
144 | void test_apply_fromdiff__prepend(void) |
145 | { | |
146 | cl_git_pass(apply_buf( | |
147 | FILE_ORIGINAL, "file.txt", | |
148 | FILE_PREPEND, "file.txt", | |
149 | PATCH_ORIGINAL_TO_PREPEND, NULL)); | |
150 | } | |
151 | ||
152 | void test_apply_fromdiff__prepend_nocontext(void) | |
153 | { | |
154 | git_diff_options diff_opts = GIT_DIFF_OPTIONS_INIT; | |
155 | diff_opts.context_lines = 0; | |
156 | ||
157 | cl_git_pass(apply_buf( | |
158 | FILE_ORIGINAL, "file.txt", | |
159 | FILE_PREPEND, "file.txt", | |
160 | PATCH_ORIGINAL_TO_PREPEND_NOCONTEXT, &diff_opts)); | |
161 | } | |
162 | ||
ac3d33df JK |
163 | void test_apply_fromdiff__prepend_and_change(void) |
164 | { | |
165 | cl_git_pass(apply_buf( | |
166 | FILE_ORIGINAL, "file.txt", | |
167 | FILE_PREPEND_AND_CHANGE, "file.txt", | |
168 | PATCH_ORIGINAL_TO_PREPEND_AND_CHANGE, NULL)); | |
169 | } | |
170 | ||
171 | void test_apply_fromdiff__prepend_and_change_nocontext(void) | |
172 | { | |
173 | git_diff_options diff_opts = GIT_DIFF_OPTIONS_INIT; | |
174 | diff_opts.context_lines = 0; | |
175 | ||
176 | cl_git_pass(apply_buf( | |
177 | FILE_ORIGINAL, "file.txt", | |
178 | FILE_PREPEND_AND_CHANGE, "file.txt", | |
179 | PATCH_ORIGINAL_TO_PREPEND_AND_CHANGE_NOCONTEXT, &diff_opts)); | |
180 | } | |
181 | ||
182 | void test_apply_fromdiff__delete_and_change(void) | |
183 | { | |
184 | cl_git_pass(apply_buf( | |
185 | FILE_ORIGINAL, "file.txt", | |
186 | FILE_DELETE_AND_CHANGE, "file.txt", | |
187 | PATCH_ORIGINAL_TO_DELETE_AND_CHANGE, NULL)); | |
188 | } | |
189 | ||
190 | void test_apply_fromdiff__delete_and_change_nocontext(void) | |
191 | { | |
192 | git_diff_options diff_opts = GIT_DIFF_OPTIONS_INIT; | |
193 | diff_opts.context_lines = 0; | |
194 | ||
195 | cl_git_pass(apply_buf( | |
196 | FILE_ORIGINAL, "file.txt", | |
197 | FILE_DELETE_AND_CHANGE, "file.txt", | |
198 | PATCH_ORIGINAL_TO_DELETE_AND_CHANGE_NOCONTEXT, &diff_opts)); | |
199 | } | |
200 | ||
201 | void test_apply_fromdiff__delete_firstline(void) | |
202 | { | |
203 | cl_git_pass(apply_buf( | |
204 | FILE_ORIGINAL, "file.txt", | |
205 | FILE_DELETE_FIRSTLINE, "file.txt", | |
206 | PATCH_ORIGINAL_TO_DELETE_FIRSTLINE, NULL)); | |
207 | } | |
208 | ||
7cb904ba ET |
209 | void test_apply_fromdiff__append(void) |
210 | { | |
211 | cl_git_pass(apply_buf( | |
212 | FILE_ORIGINAL, "file.txt", | |
213 | FILE_APPEND, "file.txt", | |
214 | PATCH_ORIGINAL_TO_APPEND, NULL)); | |
215 | } | |
216 | ||
217 | void test_apply_fromdiff__append_nocontext(void) | |
218 | { | |
219 | git_diff_options diff_opts = GIT_DIFF_OPTIONS_INIT; | |
220 | diff_opts.context_lines = 0; | |
221 | ||
222 | cl_git_pass(apply_buf( | |
223 | FILE_ORIGINAL, "file.txt", | |
224 | FILE_APPEND, "file.txt", | |
225 | PATCH_ORIGINAL_TO_APPEND_NOCONTEXT, &diff_opts)); | |
226 | } | |
227 | ||
228 | void test_apply_fromdiff__prepend_and_append(void) | |
229 | { | |
230 | cl_git_pass(apply_buf( | |
231 | FILE_ORIGINAL, "file.txt", | |
232 | FILE_PREPEND_AND_APPEND, "file.txt", | |
233 | PATCH_ORIGINAL_TO_PREPEND_AND_APPEND, NULL)); | |
234 | } | |
235 | ||
236 | void test_apply_fromdiff__to_empty_file(void) | |
237 | { | |
238 | cl_git_pass(apply_buf( | |
239 | FILE_ORIGINAL, "file.txt", | |
240 | "", NULL, | |
241 | PATCH_ORIGINAL_TO_EMPTY_FILE, NULL)); | |
242 | } | |
243 | ||
244 | void test_apply_fromdiff__from_empty_file(void) | |
245 | { | |
246 | cl_git_pass(apply_buf( | |
247 | "", NULL, | |
248 | FILE_ORIGINAL, "file.txt", | |
249 | PATCH_EMPTY_FILE_TO_ORIGINAL, NULL)); | |
250 | } | |
251 | ||
252 | void test_apply_fromdiff__add(void) | |
253 | { | |
254 | cl_git_pass(apply_buf( | |
255 | NULL, NULL, | |
256 | FILE_ORIGINAL, "file.txt", | |
257 | PATCH_ADD_ORIGINAL, NULL)); | |
258 | } | |
259 | ||
260 | void test_apply_fromdiff__delete(void) | |
261 | { | |
262 | cl_git_pass(apply_buf( | |
263 | FILE_ORIGINAL, "file.txt", | |
264 | NULL, NULL, | |
265 | PATCH_DELETE_ORIGINAL, NULL)); | |
266 | } | |
0004386f ET |
267 | |
268 | void test_apply_fromdiff__no_change(void) | |
269 | { | |
270 | cl_git_pass(apply_buf( | |
271 | FILE_ORIGINAL, "file.txt", | |
272 | FILE_ORIGINAL, "file.txt", | |
273 | "", NULL)); | |
274 | } | |
3149ff6f ET |
275 | |
276 | void test_apply_fromdiff__binary_add(void) | |
277 | { | |
e579e0f7 | 278 | git_str newfile = GIT_STR_INIT; |
3149ff6f ET |
279 | |
280 | newfile.ptr = FILE_BINARY_DELTA_MODIFIED; | |
281 | newfile.size = FILE_BINARY_DELTA_MODIFIED_LEN; | |
282 | ||
283 | cl_git_pass(apply_gitbuf( | |
284 | NULL, NULL, | |
285 | &newfile, "binary.bin", | |
286 | NULL, &binary_opts)); | |
287 | } | |
288 | ||
289 | void test_apply_fromdiff__binary_no_change(void) | |
290 | { | |
e579e0f7 | 291 | git_str original = GIT_STR_INIT; |
3149ff6f ET |
292 | |
293 | original.ptr = FILE_BINARY_DELTA_ORIGINAL; | |
294 | original.size = FILE_BINARY_DELTA_ORIGINAL_LEN; | |
295 | ||
296 | cl_git_pass(apply_gitbuf( | |
297 | &original, "binary.bin", | |
298 | &original, "binary.bin", | |
299 | "", &binary_opts)); | |
300 | } | |
301 | ||
302 | void test_apply_fromdiff__binary_change_delta(void) | |
303 | { | |
e579e0f7 | 304 | git_str original = GIT_STR_INIT, modified = GIT_STR_INIT; |
3149ff6f ET |
305 | |
306 | original.ptr = FILE_BINARY_DELTA_ORIGINAL; | |
307 | original.size = FILE_BINARY_DELTA_ORIGINAL_LEN; | |
308 | ||
309 | modified.ptr = FILE_BINARY_DELTA_MODIFIED; | |
310 | modified.size = FILE_BINARY_DELTA_MODIFIED_LEN; | |
311 | ||
312 | cl_git_pass(apply_gitbuf( | |
313 | &original, "binary.bin", | |
314 | &modified, "binary.bin", | |
315 | NULL, &binary_opts)); | |
316 | } | |
317 | ||
318 | void test_apply_fromdiff__binary_change_literal(void) | |
319 | { | |
e579e0f7 | 320 | git_str original = GIT_STR_INIT, modified = GIT_STR_INIT; |
3149ff6f ET |
321 | |
322 | original.ptr = FILE_BINARY_LITERAL_ORIGINAL; | |
323 | original.size = FILE_BINARY_LITERAL_ORIGINAL_LEN; | |
324 | ||
325 | modified.ptr = FILE_BINARY_LITERAL_MODIFIED; | |
326 | modified.size = FILE_BINARY_LITERAL_MODIFIED_LEN; | |
327 | ||
328 | cl_git_pass(apply_gitbuf( | |
329 | &original, "binary.bin", | |
330 | &modified, "binary.bin", | |
331 | NULL, &binary_opts)); | |
332 | } | |
333 | ||
334 | void test_apply_fromdiff__binary_delete(void) | |
335 | { | |
e579e0f7 | 336 | git_str original = GIT_STR_INIT; |
3149ff6f ET |
337 | |
338 | original.ptr = FILE_BINARY_DELTA_MODIFIED; | |
339 | original.size = FILE_BINARY_DELTA_MODIFIED_LEN; | |
340 | ||
341 | cl_git_pass(apply_gitbuf( | |
342 | &original, "binary.bin", | |
343 | NULL, NULL, | |
344 | NULL, &binary_opts)); | |
345 | } | |
22a2d3d5 UG |
346 | |
347 | void test_apply_fromdiff__patching_correctly_truncates_source(void) | |
348 | { | |
e579e0f7 | 349 | git_str original = GIT_STR_INIT, patched = GIT_STR_INIT; |
22a2d3d5 UG |
350 | git_patch *patch; |
351 | unsigned int mode; | |
352 | char *path; | |
353 | ||
354 | cl_git_pass(git_patch_from_buffers(&patch, | |
355 | "foo\nbar", 7, "file.txt", | |
356 | "foo\nfoo", 7, "file.txt", NULL)); | |
357 | ||
358 | /* | |
359 | * Previously, we would fail to correctly truncate the source buffer if | |
360 | * the source has more than one line and ends with a non-newline | |
361 | * character. In the following call, we thus truncate the source string | |
362 | * in the middle of the second line. Without the bug fixed, we would | |
363 | * successfully apply the patch to the source and return success. With | |
364 | * the overflow being fixed, we should return an error. | |
365 | */ | |
366 | cl_git_fail_with(GIT_EAPPLYFAIL, | |
367 | git_apply__patch(&patched, &path, &mode, | |
368 | "foo\nbar\n", 5, patch, NULL)); | |
369 | ||
370 | /* Verify that the patch succeeds if we do not truncate */ | |
371 | cl_git_pass(git_apply__patch(&patched, &path, &mode, | |
372 | "foo\nbar\n", 7, patch, NULL)); | |
373 | ||
e579e0f7 MB |
374 | git_str_dispose(&original); |
375 | git_str_dispose(&patched); | |
22a2d3d5 UG |
376 | git_patch_free(patch); |
377 | git__free(path); | |
378 | } |