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.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 	// Clean/smudge filter for testFiltering. The smudgetest test resources were
186 	// created with C git using a clean filter sed -e "s/A/E/g" and the smudge
187 	// filter sed -e "s/E/A/g". To keep the test independent of the presence of
188 	// sed, implement this with a built-in filter.
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 		// Set up filter
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 			// Tear down filter
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 		// This is a text patch that changes a file containing ÄÖÜ in UTF-8 to
299 		// the same characters in ISO-8859-1. The patch file itself uses mixed
300 		// encoding. Since checkFile() works with strings use the binary check.
301 		checkBinary("umlaut", true);
302 	}
303 
304 	@Test
305 	public void testEmptyLine() throws Exception {
306 		// C git accepts completely empty lines as empty context lines.
307 		// According to comments in the C git sources (apply.c), newer GNU diff
308 		// may produce such diffs.
309 		checkBinary("emptyLine", true);
310 	}
311 
312 	@Test
313 	public void testMultiFileNoNewline() throws Exception {
314 		// This test needs two files. One is in the test resources.
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; // Never happens
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 }