1
2
3
4
5
6
7
8
9
10 package org.eclipse.jgit.api;
11
12 import static org.junit.Assert.assertArrayEquals;
13 import static org.junit.Assert.assertEquals;
14 import static org.junit.Assert.assertFalse;
15 import static org.junit.Assert.assertTrue;
16 import static org.junit.Assert.fail;
17
18 import java.io.ByteArrayOutputStream;
19 import java.io.File;
20 import java.io.IOException;
21 import java.io.InputStream;
22 import java.io.OutputStream;
23 import java.nio.charset.StandardCharsets;
24 import java.nio.file.Files;
25
26 import org.eclipse.jgit.api.errors.PatchApplyException;
27 import org.eclipse.jgit.api.errors.PatchFormatException;
28 import org.eclipse.jgit.attributes.FilterCommand;
29 import org.eclipse.jgit.attributes.FilterCommandFactory;
30 import org.eclipse.jgit.attributes.FilterCommandRegistry;
31 import org.eclipse.jgit.diff.RawText;
32 import org.eclipse.jgit.junit.RepositoryTestCase;
33 import org.eclipse.jgit.lib.Config;
34 import org.eclipse.jgit.lib.ConfigConstants;
35 import org.eclipse.jgit.util.IO;
36 import org.junit.Test;
37
38 public class ApplyCommandTest extends RepositoryTestCase {
39
40 private RawText a;
41
42 private RawText b;
43
44 private ApplyResult init(String name) throws Exception {
45 return init(name, true, true);
46 }
47
48 private ApplyResult init(final String name, final boolean preExists,
49 final boolean postExists) throws Exception {
50 try (Git git = new Git(db)) {
51 if (preExists) {
52 a = new RawText(readFile(name + "_PreImage"));
53 write(new File(db.getDirectory().getParent(), name),
54 a.getString(0, a.size(), false));
55
56 git.add().addFilepattern(name).call();
57 git.commit().setMessage("PreImage").call();
58 }
59
60 if (postExists) {
61 b = new RawText(readFile(name + "_PostImage"));
62 }
63
64 return git
65 .apply()
66 .setPatch(getTestResource(name + ".patch")).call();
67 }
68 }
69
70 @Test
71 public void testCrLf() throws Exception {
72 try {
73 db.getConfig().setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null,
74 ConfigConstants.CONFIG_KEY_AUTOCRLF, true);
75 ApplyResult result = init("crlf", true, true);
76 assertEquals(1, result.getUpdatedFiles().size());
77 assertEquals(new File(db.getWorkTree(), "crlf"),
78 result.getUpdatedFiles().get(0));
79 checkFile(new File(db.getWorkTree(), "crlf"),
80 b.getString(0, b.size(), false));
81 } finally {
82 db.getConfig().unset(ConfigConstants.CONFIG_CORE_SECTION, null,
83 ConfigConstants.CONFIG_KEY_AUTOCRLF);
84 }
85 }
86
87 @Test
88 public void testCrLfOff() throws Exception {
89 try {
90 db.getConfig().setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null,
91 ConfigConstants.CONFIG_KEY_AUTOCRLF, false);
92 ApplyResult result = init("crlf", true, true);
93 assertEquals(1, result.getUpdatedFiles().size());
94 assertEquals(new File(db.getWorkTree(), "crlf"),
95 result.getUpdatedFiles().get(0));
96 checkFile(new File(db.getWorkTree(), "crlf"),
97 b.getString(0, b.size(), false));
98 } finally {
99 db.getConfig().unset(ConfigConstants.CONFIG_CORE_SECTION, null,
100 ConfigConstants.CONFIG_KEY_AUTOCRLF);
101 }
102 }
103
104 @Test
105 public void testCrLfEmptyCommitted() throws Exception {
106 try {
107 db.getConfig().setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null,
108 ConfigConstants.CONFIG_KEY_AUTOCRLF, true);
109 ApplyResult result = init("crlf3", true, true);
110 assertEquals(1, result.getUpdatedFiles().size());
111 assertEquals(new File(db.getWorkTree(), "crlf3"),
112 result.getUpdatedFiles().get(0));
113 checkFile(new File(db.getWorkTree(), "crlf3"),
114 b.getString(0, b.size(), false));
115 } finally {
116 db.getConfig().unset(ConfigConstants.CONFIG_CORE_SECTION, null,
117 ConfigConstants.CONFIG_KEY_AUTOCRLF);
118 }
119 }
120
121 @Test
122 public void testCrLfNewFile() throws Exception {
123 try {
124 db.getConfig().setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null,
125 ConfigConstants.CONFIG_KEY_AUTOCRLF, true);
126 ApplyResult result = init("crlf4", false, true);
127 assertEquals(1, result.getUpdatedFiles().size());
128 assertEquals(new File(db.getWorkTree(), "crlf4"),
129 result.getUpdatedFiles().get(0));
130 checkFile(new File(db.getWorkTree(), "crlf4"),
131 b.getString(0, b.size(), false));
132 } finally {
133 db.getConfig().unset(ConfigConstants.CONFIG_CORE_SECTION, null,
134 ConfigConstants.CONFIG_KEY_AUTOCRLF);
135 }
136 }
137
138 @Test
139 public void testPatchWithCrLf() throws Exception {
140 try {
141 db.getConfig().setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null,
142 ConfigConstants.CONFIG_KEY_AUTOCRLF, false);
143 ApplyResult result = init("crlf2", true, true);
144 assertEquals(1, result.getUpdatedFiles().size());
145 assertEquals(new File(db.getWorkTree(), "crlf2"),
146 result.getUpdatedFiles().get(0));
147 checkFile(new File(db.getWorkTree(), "crlf2"),
148 b.getString(0, b.size(), false));
149 } finally {
150 db.getConfig().unset(ConfigConstants.CONFIG_CORE_SECTION, null,
151 ConfigConstants.CONFIG_KEY_AUTOCRLF);
152 }
153 }
154
155 @Test
156 public void testPatchWithCrLf2() throws Exception {
157 String name = "crlf2";
158 try (Git git = new Git(db)) {
159 db.getConfig().setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null,
160 ConfigConstants.CONFIG_KEY_AUTOCRLF, false);
161 a = new RawText(readFile(name + "_PreImage"));
162 write(new File(db.getWorkTree(), name),
163 a.getString(0, a.size(), false));
164
165 git.add().addFilepattern(name).call();
166 git.commit().setMessage("PreImage").call();
167
168 b = new RawText(readFile(name + "_PostImage"));
169
170 db.getConfig().setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null,
171 ConfigConstants.CONFIG_KEY_AUTOCRLF, true);
172 ApplyResult result = git.apply()
173 .setPatch(getTestResource(name + ".patch")).call();
174 assertEquals(1, result.getUpdatedFiles().size());
175 assertEquals(new File(db.getWorkTree(), name),
176 result.getUpdatedFiles().get(0));
177 checkFile(new File(db.getWorkTree(), name),
178 b.getString(0, b.size(), false));
179 } finally {
180 db.getConfig().unset(ConfigConstants.CONFIG_CORE_SECTION, null,
181 ConfigConstants.CONFIG_KEY_AUTOCRLF);
182 }
183 }
184
185
186
187
188
189 private static class ReplaceFilter extends FilterCommand {
190
191 private final char toReplace;
192
193 private final char replacement;
194
195 ReplaceFilter(InputStream in, OutputStream out, char toReplace,
196 char replacement) {
197 super(in, out);
198 this.toReplace = toReplace;
199 this.replacement = replacement;
200 }
201
202 @Override
203 public int run() throws IOException {
204 int b = in.read();
205 if (b < 0) {
206 in.close();
207 out.close();
208 return -1;
209 }
210 if ((b & 0xFF) == toReplace) {
211 b = replacement;
212 }
213 out.write(b);
214 return 1;
215 }
216 }
217
218 @Test
219 public void testFiltering() throws Exception {
220
221 FilterCommandFactory clean = (repo, in, out) -> {
222 return new ReplaceFilter(in, out, 'A', 'E');
223 };
224 FilterCommandFactory smudge = (repo, in, out) -> {
225 return new ReplaceFilter(in, out, 'E', 'A');
226 };
227 FilterCommandRegistry.register("jgit://builtin/a2e/clean", clean);
228 FilterCommandRegistry.register("jgit://builtin/a2e/smudge", smudge);
229 try (Git git = new Git(db)) {
230 Config config = db.getConfig();
231 config.setString(ConfigConstants.CONFIG_FILTER_SECTION, "a2e",
232 "clean", "jgit://builtin/a2e/clean");
233 config.setString(ConfigConstants.CONFIG_FILTER_SECTION, "a2e",
234 "smudge", "jgit://builtin/a2e/smudge");
235 write(new File(db.getWorkTree(), ".gitattributes"),
236 "smudgetest filter=a2e");
237 git.add().addFilepattern(".gitattributes").call();
238 git.commit().setMessage("Attributes").call();
239 ApplyResult result = init("smudgetest", true, true);
240 assertEquals(1, result.getUpdatedFiles().size());
241 assertEquals(new File(db.getWorkTree(), "smudgetest"),
242 result.getUpdatedFiles().get(0));
243 checkFile(new File(db.getWorkTree(), "smudgetest"),
244 b.getString(0, b.size(), false));
245
246 } finally {
247
248 FilterCommandRegistry.unregister("jgit://builtin/a2e/clean");
249 FilterCommandRegistry.unregister("jgit://builtin/a2e/smudge");
250 }
251 }
252
253 private void checkBinary(String name, boolean hasPreImage)
254 throws Exception {
255 checkBinary(name, hasPreImage, 1);
256 }
257
258 private void checkBinary(String name, boolean hasPreImage,
259 int numberOfFiles) throws Exception {
260 try (Git git = new Git(db)) {
261 byte[] post = IO
262 .readWholeStream(getTestResource(name + "_PostImage"), 0)
263 .array();
264 File f = new File(db.getWorkTree(), name);
265 if (hasPreImage) {
266 byte[] pre = IO
267 .readWholeStream(getTestResource(name + "_PreImage"), 0)
268 .array();
269 Files.write(f.toPath(), pre);
270 git.add().addFilepattern(name).call();
271 git.commit().setMessage("PreImage").call();
272 }
273 ApplyResult result = git.apply()
274 .setPatch(getTestResource(name + ".patch")).call();
275 assertEquals(numberOfFiles, result.getUpdatedFiles().size());
276 assertEquals(f, result.getUpdatedFiles().get(0));
277 assertArrayEquals(post, Files.readAllBytes(f.toPath()));
278 }
279 }
280
281 @Test
282 public void testBinaryDelta() throws Exception {
283 checkBinary("delta", true);
284 }
285
286 @Test
287 public void testBinaryLiteral() throws Exception {
288 checkBinary("literal", true);
289 }
290
291 @Test
292 public void testBinaryLiteralAdd() throws Exception {
293 checkBinary("literal_add", false);
294 }
295
296 @Test
297 public void testEncodingChange() throws Exception {
298
299
300
301 checkBinary("umlaut", true);
302 }
303
304 @Test
305 public void testEmptyLine() throws Exception {
306
307
308
309 checkBinary("emptyLine", true);
310 }
311
312 @Test
313 public void testMultiFileNoNewline() throws Exception {
314
315 try (Git git = new Git(db)) {
316 Files.write(db.getWorkTree().toPath().resolve("yello"),
317 "yello".getBytes(StandardCharsets.US_ASCII));
318 git.add().addFilepattern("yello").call();
319 git.commit().setMessage("yello").call();
320 }
321 checkBinary("hello", true, 2);
322 }
323
324 @Test
325 public void testAddA1() throws Exception {
326 ApplyResult result = init("A1", false, true);
327 assertEquals(1, result.getUpdatedFiles().size());
328 assertEquals(new File(db.getWorkTree(), "A1"), result.getUpdatedFiles()
329 .get(0));
330 checkFile(new File(db.getWorkTree(), "A1"),
331 b.getString(0, b.size(), false));
332 }
333
334 @Test
335 public void testAddA2() throws Exception {
336 ApplyResult result = init("A2", false, true);
337 assertEquals(1, result.getUpdatedFiles().size());
338 assertEquals(new File(db.getWorkTree(), "A2"), result.getUpdatedFiles()
339 .get(0));
340 checkFile(new File(db.getWorkTree(), "A2"),
341 b.getString(0, b.size(), false));
342 }
343
344 @Test
345 public void testAddA3() throws Exception {
346 ApplyResult result = init("A3", false, true);
347 assertEquals(1, result.getUpdatedFiles().size());
348 assertEquals(new File(db.getWorkTree(), "A3"),
349 result.getUpdatedFiles().get(0));
350 checkFile(new File(db.getWorkTree(), "A3"),
351 b.getString(0, b.size(), false));
352 }
353
354 @Test
355 public void testAddA1Sub() throws Exception {
356 ApplyResult result = init("A1_sub", false, false);
357 assertEquals(1, result.getUpdatedFiles().size());
358 assertEquals(new File(db.getWorkTree(), "sub/A1"), result
359 .getUpdatedFiles().get(0));
360 }
361
362 @Test
363 public void testDeleteD() throws Exception {
364 ApplyResult result = init("D", true, false);
365 assertEquals(1, result.getUpdatedFiles().size());
366 assertEquals(new File(db.getWorkTree(), "D"), result.getUpdatedFiles()
367 .get(0));
368 assertFalse(new File(db.getWorkTree(), "D").exists());
369 }
370
371 @Test(expected = PatchFormatException.class)
372 public void testFailureF1() throws Exception {
373 init("F1", true, false);
374 }
375
376 @Test(expected = PatchApplyException.class)
377 public void testFailureF2() throws Exception {
378 init("F2", true, false);
379 }
380
381 @Test
382 public void testModifyE() throws Exception {
383 ApplyResult result = init("E");
384 assertEquals(1, result.getUpdatedFiles().size());
385 assertEquals(new File(db.getWorkTree(), "E"), result.getUpdatedFiles()
386 .get(0));
387 checkFile(new File(db.getWorkTree(), "E"),
388 b.getString(0, b.size(), false));
389 }
390
391 @Test
392 public void testModifyW() throws Exception {
393 ApplyResult result = init("W");
394 assertEquals(1, result.getUpdatedFiles().size());
395 assertEquals(new File(db.getWorkTree(), "W"),
396 result.getUpdatedFiles().get(0));
397 checkFile(new File(db.getWorkTree(), "W"),
398 b.getString(0, b.size(), false));
399 }
400
401 @Test
402 public void testAddM1() throws Exception {
403 ApplyResult result = init("M1", false, true);
404 assertEquals(1, result.getUpdatedFiles().size());
405 assertTrue(result.getUpdatedFiles().get(0).canExecute());
406 checkFile(new File(db.getWorkTree(), "M1"),
407 b.getString(0, b.size(), false));
408 }
409
410 @Test
411 public void testModifyM2() throws Exception {
412 ApplyResult result = init("M2", true, true);
413 assertEquals(1, result.getUpdatedFiles().size());
414 assertTrue(result.getUpdatedFiles().get(0).canExecute());
415 checkFile(new File(db.getWorkTree(), "M2"),
416 b.getString(0, b.size(), false));
417 }
418
419 @Test
420 public void testModifyM3() throws Exception {
421 ApplyResult result = init("M3", true, true);
422 assertEquals(1, result.getUpdatedFiles().size());
423 assertFalse(result.getUpdatedFiles().get(0).canExecute());
424 checkFile(new File(db.getWorkTree(), "M3"),
425 b.getString(0, b.size(), false));
426 }
427
428 @Test
429 public void testModifyX() throws Exception {
430 ApplyResult result = init("X");
431 assertEquals(1, result.getUpdatedFiles().size());
432 assertEquals(new File(db.getWorkTree(), "X"), result.getUpdatedFiles()
433 .get(0));
434 checkFile(new File(db.getWorkTree(), "X"),
435 b.getString(0, b.size(), false));
436 }
437
438 @Test
439 public void testModifyY() throws Exception {
440 ApplyResult result = init("Y");
441 assertEquals(1, result.getUpdatedFiles().size());
442 assertEquals(new File(db.getWorkTree(), "Y"), result.getUpdatedFiles()
443 .get(0));
444 checkFile(new File(db.getWorkTree(), "Y"),
445 b.getString(0, b.size(), false));
446 }
447
448 @Test
449 public void testModifyZ() throws Exception {
450 ApplyResult result = init("Z");
451 assertEquals(1, result.getUpdatedFiles().size());
452 assertEquals(new File(db.getWorkTree(), "Z"), result.getUpdatedFiles()
453 .get(0));
454 checkFile(new File(db.getWorkTree(), "Z"),
455 b.getString(0, b.size(), false));
456 }
457
458 @Test
459 public void testModifyNL1() throws Exception {
460 ApplyResult result = init("NL1");
461 assertEquals(1, result.getUpdatedFiles().size());
462 assertEquals(new File(db.getWorkTree(), "NL1"), result
463 .getUpdatedFiles().get(0));
464 checkFile(new File(db.getWorkTree(), "NL1"),
465 b.getString(0, b.size(), false));
466 }
467
468 @Test
469 public void testNonASCII() throws Exception {
470 ApplyResult result = init("NonASCII");
471 assertEquals(1, result.getUpdatedFiles().size());
472 assertEquals(new File(db.getWorkTree(), "NonASCII"),
473 result.getUpdatedFiles().get(0));
474 checkFile(new File(db.getWorkTree(), "NonASCII"),
475 b.getString(0, b.size(), false));
476 }
477
478 @Test
479 public void testNonASCII2() throws Exception {
480 ApplyResult result = init("NonASCII2");
481 assertEquals(1, result.getUpdatedFiles().size());
482 assertEquals(new File(db.getWorkTree(), "NonASCII2"),
483 result.getUpdatedFiles().get(0));
484 checkFile(new File(db.getWorkTree(), "NonASCII2"),
485 b.getString(0, b.size(), false));
486 }
487
488 @Test
489 public void testNonASCIIAdd() throws Exception {
490 ApplyResult result = init("NonASCIIAdd");
491 assertEquals(1, result.getUpdatedFiles().size());
492 assertEquals(new File(db.getWorkTree(), "NonASCIIAdd"),
493 result.getUpdatedFiles().get(0));
494 checkFile(new File(db.getWorkTree(), "NonASCIIAdd"),
495 b.getString(0, b.size(), false));
496 }
497
498 @Test
499 public void testNonASCIIAdd2() throws Exception {
500 ApplyResult result = init("NonASCIIAdd2", false, true);
501 assertEquals(1, result.getUpdatedFiles().size());
502 assertEquals(new File(db.getWorkTree(), "NonASCIIAdd2"),
503 result.getUpdatedFiles().get(0));
504 checkFile(new File(db.getWorkTree(), "NonASCIIAdd2"),
505 b.getString(0, b.size(), false));
506 }
507
508 @Test
509 public void testNonASCIIDel() throws Exception {
510 ApplyResult result = init("NonASCIIDel", true, false);
511 assertEquals(1, result.getUpdatedFiles().size());
512 assertEquals(new File(db.getWorkTree(), "NonASCIIDel"),
513 result.getUpdatedFiles().get(0));
514 assertFalse(new File(db.getWorkTree(), "NonASCIIDel").exists());
515 }
516
517 @Test
518 public void testRenameNoHunks() throws Exception {
519 ApplyResult result = init("RenameNoHunks", true, true);
520 assertEquals(1, result.getUpdatedFiles().size());
521 assertEquals(new File(db.getWorkTree(), "RenameNoHunks"), result.getUpdatedFiles()
522 .get(0));
523 checkFile(new File(db.getWorkTree(), "nested/subdir/Renamed"),
524 b.getString(0, b.size(), false));
525 }
526
527 @Test
528 public void testRenameWithHunks() throws Exception {
529 ApplyResult result = init("RenameWithHunks", true, true);
530 assertEquals(1, result.getUpdatedFiles().size());
531 assertEquals(new File(db.getWorkTree(), "RenameWithHunks"), result.getUpdatedFiles()
532 .get(0));
533 checkFile(new File(db.getWorkTree(), "nested/subdir/Renamed"),
534 b.getString(0, b.size(), false));
535 }
536
537 @Test
538 public void testCopyWithHunks() throws Exception {
539 ApplyResult result = init("CopyWithHunks", true, true);
540 assertEquals(1, result.getUpdatedFiles().size());
541 assertEquals(new File(db.getWorkTree(), "CopyWithHunks"), result.getUpdatedFiles()
542 .get(0));
543 checkFile(new File(db.getWorkTree(), "CopyResult"),
544 b.getString(0, b.size(), false));
545 }
546
547 @Test
548 public void testShiftUp() throws Exception {
549 ApplyResult result = init("ShiftUp");
550 assertEquals(1, result.getUpdatedFiles().size());
551 assertEquals(new File(db.getWorkTree(), "ShiftUp"),
552 result.getUpdatedFiles().get(0));
553 checkFile(new File(db.getWorkTree(), "ShiftUp"),
554 b.getString(0, b.size(), false));
555 }
556
557 @Test
558 public void testShiftUp2() throws Exception {
559 ApplyResult result = init("ShiftUp2");
560 assertEquals(1, result.getUpdatedFiles().size());
561 assertEquals(new File(db.getWorkTree(), "ShiftUp2"),
562 result.getUpdatedFiles().get(0));
563 checkFile(new File(db.getWorkTree(), "ShiftUp2"),
564 b.getString(0, b.size(), false));
565 }
566
567 @Test
568 public void testShiftDown() throws Exception {
569 ApplyResult result = init("ShiftDown");
570 assertEquals(1, result.getUpdatedFiles().size());
571 assertEquals(new File(db.getWorkTree(), "ShiftDown"),
572 result.getUpdatedFiles().get(0));
573 checkFile(new File(db.getWorkTree(), "ShiftDown"),
574 b.getString(0, b.size(), false));
575 }
576
577 @Test
578 public void testShiftDown2() throws Exception {
579 ApplyResult result = init("ShiftDown2");
580 assertEquals(1, result.getUpdatedFiles().size());
581 assertEquals(new File(db.getWorkTree(), "ShiftDown2"),
582 result.getUpdatedFiles().get(0));
583 checkFile(new File(db.getWorkTree(), "ShiftDown2"),
584 b.getString(0, b.size(), false));
585 }
586
587 private static byte[] readFile(String patchFile) throws IOException {
588 final InputStream in = getTestResource(patchFile);
589 if (in == null) {
590 fail("No " + patchFile + " test vector");
591 return null;
592 }
593 try {
594 final byte[] buf = new byte[1024];
595 final ByteArrayOutputStream temp = new ByteArrayOutputStream();
596 int n;
597 while ((n = in.read(buf)) > 0)
598 temp.write(buf, 0, n);
599 return temp.toByteArray();
600 } finally {
601 in.close();
602 }
603 }
604
605 private static InputStream getTestResource(String patchFile) {
606 return ApplyCommandTest.class.getClassLoader()
607 .getResourceAsStream("org/eclipse/jgit/diff/" + patchFile);
608 }
609 }