View Javadoc
1   /*
2    * Copyright (C) 2011, 2021 IBM Corporation and others
3    *
4    * This program and the accompanying materials are made available under the
5    * terms of the Eclipse Distribution License v. 1.0 which is available at
6    * https://www.eclipse.org/org/documents/edl-v10.php.
7    *
8    * SPDX-License-Identifier: BSD-3-Clause
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 	// Clean/smudge filter for testFiltering. The smudgetest test resources were
187 	// created with C git using a clean filter sed -e "s/A/E/g" and the smudge
188 	// filter sed -e "s/E/A/g". To keep the test independent of the presence of
189 	// sed, implement this with a built-in filter.
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 		// Set up filter
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 			// Tear down filter
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 		// This is a text patch that changes a file containing ÄÖÜ in UTF-8 to
300 		// the same characters in ISO-8859-1. The patch file itself uses mixed
301 		// encoding. Since checkFile() works with strings use the binary check.
302 		checkBinary("umlaut", true);
303 	}
304 
305 	@Test
306 	public void testEmptyLine() throws Exception {
307 		// C git accepts completely empty lines as empty context lines.
308 		// According to comments in the C git sources (apply.c), newer GNU diff
309 		// may produce such diffs.
310 		checkBinary("emptyLine", true);
311 	}
312 
313 	@Test
314 	public void testMultiFileNoNewline() throws Exception {
315 		// This test needs two files. One is in the test resources.
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(1, result.getUpdatedFiles().size());
529 		assertEquals(new File(db.getWorkTree(), "RenameNoHunks"), result.getUpdatedFiles()
530 				.get(0));
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(1, result.getUpdatedFiles().size());
539 		assertEquals(new File(db.getWorkTree(), "RenameWithHunks"), result.getUpdatedFiles()
540 				.get(0));
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(), "CopyWithHunks"), 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; // Never happens
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 }