diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/very_long_file.patch b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/very_long_file.patch new file mode 100644 index 000000000..64f2b0068 Binary files /dev/null and b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/very_long_file.patch differ diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/very_long_file_PostImage b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/very_long_file_PostImage new file mode 100644 index 000000000..72ef58f79 Binary files /dev/null and b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/very_long_file_PostImage differ diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/very_long_file_PreImage b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/very_long_file_PreImage new file mode 100644 index 000000000..379a33cf2 Binary files /dev/null and b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/very_long_file_PreImage differ diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/patch/PatchApplierTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/patch/PatchApplierTest.java index 92d47c296..2aac15bbb 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/patch/PatchApplierTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/patch/PatchApplierTest.java @@ -496,6 +496,14 @@ public void testRemoveNewlineAtEnd() throws Exception { Result result = applyPatch(); verifyChange(result, "x_last_rm_nl"); } + + @Test + public void testVeryLongFile() throws Exception { + init("very_long_file"); + + Result result = applyPatch(); + verifyChange(result, "very_long_file"); + } } public static class WithWorktree extends Base { diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/patch/PatchApplier.java b/org.eclipse.jgit/src/org/eclipse/jgit/patch/PatchApplier.java index 1edd85421..a327095c8 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/patch/PatchApplier.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/patch/PatchApplier.java @@ -88,6 +88,7 @@ import org.eclipse.jgit.util.TemporaryBuffer.LocalFile; import org.eclipse.jgit.util.io.BinaryDeltaInputStream; import org.eclipse.jgit.util.io.BinaryHunkInputStream; +import org.eclipse.jgit.util.io.CountingOutputStream; import org.eclipse.jgit.util.io.EolStreamTypeUtil; import org.eclipse.jgit.util.sha1.SHA1; @@ -1013,7 +1014,10 @@ && canApplyAt(hunkLines, newLines, 0)) { // We could check if old == new, but the short-circuiting complicates // logic for inCore patching, so just write the new thing regardless. TemporaryBuffer buffer = new TemporaryBuffer.LocalFile(null); - try (OutputStream out = buffer) { + // TemporaryBuffer::length reports incorrect length until the buffer + // is closed. To use it as input for ContentStreamLoader below, we + // need a wrapper with a reliable in-progress length. + try (CountingOutputStream out = new CountingOutputStream(buffer)) { for (Iterator l = newLines.iterator(); l.hasNext();) { ByteBuffer line = l.next(); if (line == null) { @@ -1026,7 +1030,7 @@ && canApplyAt(hunkLines, newLines, 0)) { } } return new ContentStreamLoader(buffer::openInputStream, - buffer.length()); + out.getCount()); } }