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