diff options
author | Patrick Hiesel <hiesel@google.com> | 2023-03-10 16:50:37 +0100 |
---|---|---|
committer | Patrick Hiesel <hiesel@google.com> | 2024-05-14 18:52:47 +0200 |
commit | 6e9a170364efc727f4368cf5304115c7b278a649 (patch) | |
tree | 15d27c0e3b1fbd2a882a10b3a5fcbd803e0a503d /org.eclipse.jgit.test | |
parent | 5c0c18f5665fe8d3c3fae0176e231deb6c2480a7 (diff) | |
download | jgit-6e9a170364efc727f4368cf5304115c7b278a649.tar.gz jgit-6e9a170364efc727f4368cf5304115c7b278a649.zip |
Allow applying a patch with conflicts
In some settings, we want to let users apply a patch that does
not cleanly apply and add conflict markers. In Gerrit, this is
useful when cherry picking (via Git patches) from one host to
another.
This commit takes a simple approach: If a hunk doesn't apply,
go to the pre-image line, treat all lines in pre-image length
as left side of the conflict and all context and newly added
lines as right side of the conflict.
Change-Id: I01411d7a32b3f3207097b26231909aae6b835650
Diffstat (limited to 'org.eclipse.jgit.test')
7 files changed, 119 insertions, 2 deletions
diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/ConflictOutOfBounds.patch b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/ConflictOutOfBounds.patch new file mode 100644 index 0000000000..6e7448b95c --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/ConflictOutOfBounds.patch @@ -0,0 +1,10 @@ +diff --git a/ConflictOutOfBounds b/ConflictOutOfBounds +index 0000000..de98044 +--- a/ConflictOutOfBounds ++++ b/ConflictOutOfBounds +@@ -25,4 +25,4 @@ + line3 +-lineA ++lineB + line5 + line6 diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/ConflictOutOfBounds_PostImage b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/ConflictOutOfBounds_PostImage new file mode 100644 index 0000000000..4e5d5b2d88 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/ConflictOutOfBounds_PostImage @@ -0,0 +1,15 @@ +line1 +line2 +line3 +line4 +line5 +line6 +line7 +line8 +<<<<<<< HEAD +======= +line3 +lineB +line5 +line6 +>>>>>>> PATCH diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/ConflictOutOfBounds_PreImage b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/ConflictOutOfBounds_PreImage new file mode 100644 index 0000000000..f62562a216 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/ConflictOutOfBounds_PreImage @@ -0,0 +1,8 @@ +line1 +line2 +line3 +line4 +line5 +line6 +line7 +line8 diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/allowconflict.patch b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/allowconflict.patch new file mode 100644 index 0000000000..a99e636382 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/allowconflict.patch @@ -0,0 +1,10 @@ +diff --git a/allowconflict b/allowconflict +index 0000000..de98044 +--- a/allowconflict ++++ b/allowconflict +@@ -3,4 +3,4 @@ + line3 +-lineA ++lineB + line5 + line6 diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/allowconflict_PostImage b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/allowconflict_PostImage new file mode 100644 index 0000000000..a963b40dfe --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/allowconflict_PostImage @@ -0,0 +1,15 @@ +line1 +line2 +<<<<<<< HEAD +line3 +line4 +line5 +line6 +======= +line3 +lineB +line5 +line6 +>>>>>>> PATCH +line7 +line8 diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/allowconflict_PreImage b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/allowconflict_PreImage new file mode 100644 index 0000000000..f62562a216 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/allowconflict_PreImage @@ -0,0 +1,8 @@ +line1 +line2 +line3 +line4 +line5 +line6 +line7 +line8 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 2aac15bbb6..e4b0ffbc21 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 @@ -27,6 +27,7 @@ import java.nio.file.Files; import org.eclipse.jgit.annotations.Nullable; import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.api.errors.PatchFormatException; import org.eclipse.jgit.attributes.FilterCommand; import org.eclipse.jgit.attributes.FilterCommandFactory; import org.eclipse.jgit.attributes.FilterCommandRegistry; @@ -48,8 +49,7 @@ import org.junit.runner.RunWith; import org.junit.runners.Suite; @RunWith(Suite.class) -@Suite.SuiteClasses({ - PatchApplierTest.WithWorktree. class, // +@Suite.SuiteClasses({ PatchApplierTest.WithWorktree.class, // PatchApplierTest.InCore.class, // }) public class PatchApplierTest { @@ -128,6 +128,20 @@ public class PatchApplierTest { } } + protected Result applyPatchAllowConflicts() throws IOException { + InputStream patchStream = getTestResource(name + ".patch"); + Patch patch = new Patch(); + patch.parse(patchStream); + if (inCore) { + try (ObjectInserter oi = db.newObjectInserter()) { + return new PatchApplier(db, baseTip, oi).allowConflicts() + .applyPatch(patch); + } + } + return new PatchApplier(db).allowConflicts() + .applyPatch(patch); + } + protected static InputStream getTestResource(String patchFile) { return PatchApplierTest.class.getClassLoader() .getResourceAsStream("org/eclipse/jgit/diff/" + patchFile); @@ -169,6 +183,13 @@ public class PatchApplierTest { verifyContent(result, aName, exists); } + void verifyChange(Result result, String aName, boolean exists, + int numConflicts) throws Exception { + assertEquals(numConflicts, result.getErrors().size()); + assertEquals(1, result.getPaths().size()); + verifyContent(result, aName, exists); + } + protected byte[] readBlob(ObjectId treeish, String path) throws Exception { try (TestRepository<?> tr = new TestRepository<>(db); @@ -346,6 +367,36 @@ public class PatchApplierTest { } @Test + public void testConflictMarkers() throws Exception { + init("allowconflict", true, true); + + Result result = applyPatchAllowConflicts(); + + assertEquals(result.getErrors().size(), 1); + PatchApplier.Result.Error error = result.getErrors().get(0); + error.hh = null; // We don't assert the hunk header as it is a + // complex object with lots of internal state. + assertEquals(error, new PatchApplier.Result.Error( + "cannot apply hunk", "allowconflict", null)); + verifyChange(result, "allowconflict", true, 1); + } + + @Test + public void testConflictMarkersOutOfBounds() throws Exception { + init("ConflictOutOfBounds", true, true); + + Result result = applyPatchAllowConflicts(); + + assertEquals(result.getErrors().size(), 1); + PatchApplier.Result.Error error = result.getErrors().get(0); + error.hh = null; // We don't assert the hunk header as it is a + // complex object with lots of internal state. + assertEquals(error, new PatchApplier.Result.Error( + "cannot apply hunk", "ConflictOutOfBounds", null)); + verifyChange(result, "ConflictOutOfBounds", true, 1); + } + + @Test public void testShiftUp() throws Exception { init("ShiftUp"); |