diff --git a/.gitattributes b/.gitattributes index a2517b6f44..9ae14fa217 100644 --- a/.gitattributes +++ b/.gitattributes @@ -46,3 +46,8 @@ *.pdf binary *.exe binary *.zip binary + +# special line ending handling for test files +cobigen/cobigen-textmerger/src/test/resources/TestBaseLineDelimiter.txt eol=lf +cobigen/cobigen-textmerger/src/test/resources/PatchBaseLineDelimiter.txt eol=crlf +cobigen/cobigen-textmerger/src/test/resources/MergeBaseLineDelimiter.txt eol=lf diff --git a/cobigen/cobigen-textmerger/pom.xml b/cobigen/cobigen-textmerger/pom.xml index ba7c95ba8f..71f7bedac0 100644 --- a/cobigen/cobigen-textmerger/pom.xml +++ b/cobigen/cobigen-textmerger/pom.xml @@ -2,7 +2,7 @@ 4.0.0 textmerger jar - 7.0.0 + 7.1.0 CobiGen - Text Merger Plug-in CobiGen - Text Merger Plug-in diff --git a/cobigen/cobigen-textmerger/src/main/java/com/devonfw/cobigen/textmerger/TextAppender.java b/cobigen/cobigen-textmerger/src/main/java/com/devonfw/cobigen/textmerger/TextAppender.java index 3c36b4aa68..e2ba0bafca 100644 --- a/cobigen/cobigen-textmerger/src/main/java/com/devonfw/cobigen/textmerger/TextAppender.java +++ b/cobigen/cobigen-textmerger/src/main/java/com/devonfw/cobigen/textmerger/TextAppender.java @@ -2,6 +2,8 @@ import java.io.File; import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedHashMap; @@ -11,6 +13,8 @@ import com.devonfw.cobigen.api.exception.MergeException; import com.devonfw.cobigen.api.extension.Merger; +import com.devonfw.cobigen.api.util.StringUtil; +import com.devonfw.cobigen.api.util.SystemUtil; import com.devonfw.cobigen.textmerger.anchorextension.Anchor; import com.devonfw.cobigen.textmerger.anchorextension.MergeStrategy; import com.devonfw.cobigen.textmerger.anchorextension.MergeUtil; @@ -26,6 +30,9 @@ public class TextAppender implements Merger { */ private String type; + /** + * Default merge strategy + */ private MergeStrategy defaultStrat; /** @@ -68,13 +75,24 @@ public String getType() { @Override public String merge(File base, String patch, String targetCharset) throws MergeException { String mergedString; + String lineDelimiterBase; + + Path path = Paths.get(base.getAbsolutePath()); + try { mergedString = FileUtils.readFileToString(base, targetCharset); + lineDelimiterBase = SystemUtil.determineLineDelimiter(path, targetCharset); + } catch (IOException e) { throw new MergeException(base, "Could not read base file.", e); } try { - mergedString = merge(mergedString, patch); + if (lineDelimiterBase.isEmpty()) { + lineDelimiterBase = System.lineSeparator(); + } + + mergedString = + merge(mergedString, StringUtil.consolidateLineEndings(patch, lineDelimiterBase), lineDelimiterBase); } catch (Exception e) { throw new MergeException(base, e.getMessage(), e); } @@ -87,26 +105,28 @@ public String merge(File base, String patch, String targetCharset) throws MergeE * target {@link String} to be merged into * @param patch * {@link String} patch, which should be applied to the base file + * @param lineDelimiter + * String line delimiter to use * @return Merged text (not null) * @throws Exception * When there is some problem about anchors */ - public String merge(String base, String patch) throws Exception { + public String merge(String base, String patch, String lineDelimiter) throws Exception { String mergedString = ""; if (MergeUtil.hasAnchors(patch)) { - LinkedHashMap splitBase = MergeUtil.splitByAnchors(base, defaultStrat); - LinkedHashMap splitPatch = MergeUtil.splitByAnchors(patch, defaultStrat); + LinkedHashMap splitBase = MergeUtil.splitByAnchors(base, defaultStrat, lineDelimiter); + LinkedHashMap splitPatch = MergeUtil.splitByAnchors(patch, defaultStrat, lineDelimiter); String footer = "footer"; String header = "header"; String toAppend = ""; if (MergeUtil.hasKeyMatchingDocumentPart(header, splitBase)) { - toAppend = MergeUtil.appendText(toAppend, header, splitBase, true, true); + toAppend = MergeUtil.appendText(toAppend, header, splitBase, true, true, lineDelimiter); mergedString = MergeUtil.addTextAndDeleteCurrentAnchor(mergedString, toAppend, splitPatch, splitBase, MergeUtil.getKeyMatchingDocumentPart(header, splitBase)); } else if (MergeUtil.hasKeyMatchingDocumentPart(header, splitPatch)) { - toAppend = MergeUtil.appendText(toAppend, header, splitPatch, true, true); + toAppend = MergeUtil.appendText(toAppend, header, splitPatch, true, true, lineDelimiter); mergedString = MergeUtil.addTextAndDeleteCurrentAnchor(mergedString, toAppend, splitPatch, splitBase, MergeUtil.getKeyMatchingDocumentPart(header, splitPatch)); } @@ -127,16 +147,20 @@ public String merge(String base, String patch) throws Exception { if (tmpAnchor.getNewlineName().matches("(newline_).+")) { switch (tmpAnchor.getNewlineName().toLowerCase()) { case "newline_appendbefore": - toAppend += MergeUtil.appendText(toAppend, docPart, splitBase, false, false); - toAppend = MergeUtil.appendText(toAppend, docPart, splitPatch, true, true); + toAppend += MergeUtil.appendText(toAppend, docPart, splitBase, false, false, + lineDelimiter); + toAppend = MergeUtil.appendText(toAppend, docPart, splitPatch, true, true, + lineDelimiter); mergedString = MergeUtil.addTextAndDeleteCurrentAnchor(mergedString, toAppend, splitPatch, splitBase, tmpAnchor); break; case "newline_appendafter": case "newline_append": - toAppend = MergeUtil.appendText(toAppend, docPart, splitBase, false, false); - toAppend += System.lineSeparator(); - toAppend = MergeUtil.appendText(toAppend, docPart, splitPatch, false, true); + toAppend = MergeUtil.appendText(toAppend, docPart, splitBase, false, false, + lineDelimiter); + toAppend += lineDelimiter; + toAppend = MergeUtil.appendText(toAppend, docPart, splitPatch, false, true, + lineDelimiter); mergedString = MergeUtil.addTextAndDeleteCurrentAnchor(mergedString, toAppend, splitPatch, splitBase, tmpAnchor); break; @@ -147,18 +171,22 @@ public String merge(String base, String patch) throws Exception { } else if (tmpAnchor.getNewlineName().matches(".*(newline)")) { switch (tmpAnchor.getNewlineName().toLowerCase()) { case "appendbefore_newline": - toAppend += System.lineSeparator(); - toAppend = MergeUtil.appendText(toAppend, docPart, splitBase, false, false); - toAppend = MergeUtil.appendText(toAppend, docPart, splitPatch, true, true); + toAppend += lineDelimiter; + toAppend = MergeUtil.appendText(toAppend, docPart, splitBase, false, false, + lineDelimiter); + toAppend = MergeUtil.appendText(toAppend, docPart, splitPatch, true, true, + lineDelimiter); mergedString = MergeUtil.addTextAndDeleteCurrentAnchor(mergedString, toAppend, splitPatch, splitBase, tmpAnchor); break; case "newline": case "appendafter_newline": case "append_newline": - toAppend = MergeUtil.appendText(toAppend, docPart, splitBase, false, false); - toAppend = MergeUtil.appendText(toAppend, docPart, splitPatch, false, true); - toAppend += System.lineSeparator(); + toAppend = MergeUtil.appendText(toAppend, docPart, splitBase, false, false, + lineDelimiter); + toAppend = MergeUtil.appendText(toAppend, docPart, splitPatch, false, true, + lineDelimiter); + toAppend += lineDelimiter; mergedString = MergeUtil.addTextAndDeleteCurrentAnchor(mergedString, toAppend, splitPatch, splitBase, tmpAnchor); break; @@ -169,25 +197,31 @@ public String merge(String base, String patch) throws Exception { } else { switch (mergeStrat) { case APPENDBEFORE: - toAppend = MergeUtil.appendText(toAppend, docPart, splitBase, false, false); - toAppend = MergeUtil.appendText(toAppend, docPart, splitPatch, true, true); + toAppend = MergeUtil.appendText(toAppend, docPart, splitBase, false, false, + lineDelimiter); + toAppend = MergeUtil.appendText(toAppend, docPart, splitPatch, true, true, + lineDelimiter); mergedString = MergeUtil.addTextAndDeleteCurrentAnchor(mergedString, toAppend, splitPatch, splitBase, tmpAnchor); break; case APPENDAFTER: case APPEND: - toAppend = MergeUtil.appendText(toAppend, docPart, splitBase, false, false); - toAppend = MergeUtil.appendText(toAppend, docPart, splitPatch, false, true); + toAppend = MergeUtil.appendText(toAppend, docPart, splitBase, false, false, + lineDelimiter); + toAppend = MergeUtil.appendText(toAppend, docPart, splitPatch, false, true, + lineDelimiter); mergedString = MergeUtil.addTextAndDeleteCurrentAnchor(mergedString, toAppend, splitPatch, splitBase, tmpAnchor); break; case OVERRIDE: - toAppend = MergeUtil.appendText(toAppend, docPart, splitPatch, false, true); + toAppend = MergeUtil.appendText(toAppend, docPart, splitPatch, false, true, + lineDelimiter); mergedString = MergeUtil.addTextAndDeleteCurrentAnchor(mergedString, toAppend, splitPatch, splitBase, tmpAnchor); break; case NOMERGE: - toAppend = MergeUtil.appendText(toAppend, docPart, splitBase, false, true); + toAppend = MergeUtil.appendText(toAppend, docPart, splitBase, false, true, + lineDelimiter); mergedString = MergeUtil.addTextAndDeleteCurrentAnchor(mergedString, toAppend, splitPatch, splitBase, tmpAnchor); break; @@ -203,22 +237,23 @@ public String merge(String base, String patch) throws Exception { } } else { - toAppend = MergeUtil.appendText(toAppend, docPart, splitBase, false, true); + toAppend = + MergeUtil.appendText(toAppend, docPart, splitBase, false, true, lineDelimiter); mergedString = MergeUtil.addTextAndDeleteCurrentAnchor(mergedString, toAppend, splitPatch, splitBase, tmpAnchor); } } else if (MergeUtil.hasKeyMatchingDocumentPart(docPart, splitPatch)) { - toAppend = MergeUtil.appendText(toAppend, docPart, splitPatch, false, true); + toAppend = MergeUtil.appendText(toAppend, docPart, splitPatch, false, true, lineDelimiter); mergedString = MergeUtil.addTextAndDeleteCurrentAnchor(mergedString, toAppend, splitPatch, splitBase, tmpAnchor); } } } else { if (MergeUtil.hasKeyMatchingDocumentPart(footer, splitBase)) { - toAppend = MergeUtil.appendText(toAppend, footer, splitBase, false, true); + toAppend = MergeUtil.appendText(toAppend, footer, splitBase, false, true, lineDelimiter); mergedString += toAppend; } else if (MergeUtil.hasKeyMatchingDocumentPart(footer, splitPatch)) { - toAppend = MergeUtil.appendText(toAppend, footer, splitPatch, false, true); + toAppend = MergeUtil.appendText(toAppend, footer, splitPatch, false, true, lineDelimiter); mergedString += toAppend; } break; @@ -231,7 +266,7 @@ public String merge(String base, String patch) throws Exception { mergedString = patch; return mergedString; } else if (withNewLineBeforehand) { - mergedString += System.lineSeparator(); + mergedString += lineDelimiter; } mergedString += patch; } diff --git a/cobigen/cobigen-textmerger/src/main/java/com/devonfw/cobigen/textmerger/anchorextension/MergeUtil.java b/cobigen/cobigen-textmerger/src/main/java/com/devonfw/cobigen/textmerger/anchorextension/MergeUtil.java index 025386dd4c..72867f9f14 100644 --- a/cobigen/cobigen-textmerger/src/main/java/com/devonfw/cobigen/textmerger/anchorextension/MergeUtil.java +++ b/cobigen/cobigen-textmerger/src/main/java/com/devonfw/cobigen/textmerger/anchorextension/MergeUtil.java @@ -57,12 +57,14 @@ public class MergeUtil { * The string that is to be split by anchors * @param defaultMergeStrategy * the default merge strategy to fall back + * @param lineDelimiter + * String line delimiter to use * @return a LinkedHashMap which contains anchors as keys and the following text as values * @throws Exception * when an anchor contains a wrong definition */ - public static LinkedHashMap splitByAnchors(String toSplit, MergeStrategy defaultMergeStrategy) - throws Exception { + public static LinkedHashMap splitByAnchors(String toSplit, MergeStrategy defaultMergeStrategy, + String lineDelimiter) throws Exception { LinkedHashMap result = new LinkedHashMap<>(); toSplit.trim(); String firstLine = @@ -75,7 +77,7 @@ public static LinkedHashMap splitByAnchors(String toSplit, Merge + "https://github.com/devonfw/cobigen/wiki/cobigen-textmerger#error-list " + "for more details"); } - toSplit = toSplit + System.lineSeparator() + "anchor:::anchorend" + System.lineSeparator(); + toSplit = toSplit + lineDelimiter + "anchor:::anchorend" + lineDelimiter; Anchor anchor; int anchorCount = 0; Pattern regex = Pattern.compile(anchorRegex); @@ -168,26 +170,27 @@ public static Anchor getKeyMatchingDocumentPart(String docPart, Map m, boolean before, - boolean withKey) { + public static String appendText(String text, String docPart, Map m, boolean before, boolean withKey, + String lineDelimiter) { Anchor key = MergeUtil.getKeyMatchingDocumentPart(docPart, m); if (key.getNewlineName().equalsIgnoreCase("newline_appendbefore") && withKey) { - return System.lineSeparator() + key.getAnchor() + System.lineSeparator() + System.lineSeparator() - + m.get(key) + text; + return lineDelimiter + key.getAnchor() + lineDelimiter + lineDelimiter + m.get(key) + text; } else if (before) { if (withKey) { - return System.lineSeparator() + key.getAnchor() + System.lineSeparator() + m.get(key) + text; + return lineDelimiter + key.getAnchor() + lineDelimiter + m.get(key) + text; } else { - return System.lineSeparator() + m.get(key) + text; + return lineDelimiter + m.get(key) + text; } } else { if (withKey) { - return System.lineSeparator() + key.getAnchor() + text + System.lineSeparator() + m.get(key); + return lineDelimiter + key.getAnchor() + text + lineDelimiter + m.get(key); } else { - return text + System.lineSeparator() + m.get(key); + return text + lineDelimiter + m.get(key); } } } diff --git a/cobigen/cobigen-textmerger/src/test/java/com/devonfw/cobigen/textmerger/MergeUtilTest.java b/cobigen/cobigen-textmerger/src/test/java/com/devonfw/cobigen/textmerger/MergeUtilTest.java index d049b2a197..8e64cc933b 100644 --- a/cobigen/cobigen-textmerger/src/test/java/com/devonfw/cobigen/textmerger/MergeUtilTest.java +++ b/cobigen/cobigen-textmerger/src/test/java/com/devonfw/cobigen/textmerger/MergeUtilTest.java @@ -61,7 +61,7 @@ public void testProperMappingOfAnchorsAndText() { + "// anchor:test2213123:append:anchorend" + System.lineSeparator() + " Lorem ipsum dolor sit amet"; Map result = new LinkedHashMap<>(); try { - result = MergeUtil.splitByAnchors(testString, testStrat); + result = MergeUtil.splitByAnchors(testString, testStrat, System.lineSeparator()); } catch (Exception e) { fail("Expected no Exception, got the following Exception instead: " + e.getMessage()); } @@ -80,7 +80,7 @@ public void testProperMappingOfAnchorsAndTextWhenAnchorDoesntHaveEnoughPartsAndN + System.lineSeparator() + "// anchor:anotherone:hgfds:anchorend" + System.lineSeparator() + "test3" + System.lineSeparator() + "// anchor:footer:append:anchorend" + System.lineSeparator() + "test4"; try { - MergeUtil.splitByAnchors(testString, testStrat); + MergeUtil.splitByAnchors(testString, testStrat, System.lineSeparator()); failBecauseExceptionWasNotThrown(Exception.class); } catch (Exception e) { @@ -111,7 +111,7 @@ public void testProperMappingOfAnchorsAndTextAddsDefaultMergeStrategy() { Map test = new LinkedHashMap<>(); try { - test = MergeUtil.splitByAnchors(testString, testStrat); + test = MergeUtil.splitByAnchors(testString, testStrat, System.lineSeparator()); assertThat(test).isEqualTo(expected); } catch (Exception e) { fail("Expected no Exception, got the following Exception instead: " + e.getMessage()); @@ -130,20 +130,19 @@ public void throwsExceptionWhenNoAnchorAsFirstLine() { String test2 = "blabla" + System.lineSeparator() + "// anchor:test2:test2:anchorend" + System.lineSeparator() + "test2"; try { - MergeUtil.splitByAnchors(test, testStrat); + MergeUtil.splitByAnchors(test, testStrat, System.lineSeparator()); } catch (Exception e) { fail("Expected no Exception, got the following Exception instead: " + e.getClass()); } try { - MergeUtil.splitByAnchors(test2, testStrat); + MergeUtil.splitByAnchors(test2, testStrat, System.lineSeparator()); failBecauseExceptionWasNotThrown(Exception.class); } catch (Exception e) { assertThat(e).hasMessage( "Incorrect document structure. Anchors are defined but there is no anchor at the start of the document.\n" + "See https://github.com/devonfw/cobigen/wiki/cobigen-textmerger#general and " - + "https://github.com/devonfw/cobigen/wiki/cobigen-textmerger#error-list " - + "for more details"); + + "https://github.com/devonfw/cobigen/wiki/cobigen-textmerger#error-list " + "for more details"); } } @@ -179,17 +178,17 @@ public void testProperAppendingOfText() { String testString = "", testString2 = "", testString3 = "", testString4 = ""; - testString = MergeUtil.appendText(testString, "test", test, false, false); - testString = MergeUtil.appendText(testString, "test", test2, true, true); + testString = MergeUtil.appendText(testString, "test", test, false, false, System.lineSeparator()); + testString = MergeUtil.appendText(testString, "test", test2, true, true, System.lineSeparator()); - testString2 = MergeUtil.appendText(testString2, "test", test, false, false); - testString2 = MergeUtil.appendText(testString2, "test", test2, false, true); + testString2 = MergeUtil.appendText(testString2, "test", test, false, false, System.lineSeparator()); + testString2 = MergeUtil.appendText(testString2, "test", test2, false, true, System.lineSeparator()); - testString3 = MergeUtil.appendText(testString3, "test", test, false, false); - testString3 = MergeUtil.appendText(testString3, "test", test2, true, false); + testString3 = MergeUtil.appendText(testString3, "test", test, false, false, System.lineSeparator()); + testString3 = MergeUtil.appendText(testString3, "test", test2, true, false, System.lineSeparator()); - testString4 = MergeUtil.appendText(testString4, "test", test, false, false); - testString4 = MergeUtil.appendText(testString4, "test", test2, false, false); + testString4 = MergeUtil.appendText(testString4, "test", test, false, false, System.lineSeparator()); + testString4 = MergeUtil.appendText(testString4, "test", test2, false, false, System.lineSeparator()); assertThat(testString).isEqualTo(System.lineSeparator() + "// anchor:test:append:anchorend" + System.lineSeparator() + "test2" + System.lineSeparator() + "test1"); diff --git a/cobigen/cobigen-textmerger/src/test/java/com/devonfw/cobigen/textmerger/TextAppenderTest.java b/cobigen/cobigen-textmerger/src/test/java/com/devonfw/cobigen/textmerger/TextAppenderTest.java index 96e0904b07..c3562a4401 100644 --- a/cobigen/cobigen-textmerger/src/test/java/com/devonfw/cobigen/textmerger/TextAppenderTest.java +++ b/cobigen/cobigen-textmerger/src/test/java/com/devonfw/cobigen/textmerger/TextAppenderTest.java @@ -9,7 +9,6 @@ import org.junit.Test; import com.devonfw.cobigen.api.exception.MergeException; -import com.devonfw.cobigen.textmerger.TextAppender; /** * @@ -276,8 +275,7 @@ public void testAnchorMerge_testNoAnchorAtStartOfBase() throws Exception { assertThat(e).hasMessage(getMergeExceptionMessage(file, "Incorrect document structure. Anchors are defined but there is no anchor at the start of the document.\n" + "See https://github.com/devonfw/cobigen/wiki/cobigen-textmerger#general and " - + "https://github.com/devonfw/cobigen/wiki/cobigen-textmerger#error-list " - + "for more details")); + + "https://github.com/devonfw/cobigen/wiki/cobigen-textmerger#error-list " + "for more details")); } } @@ -299,11 +297,25 @@ public void testAnchorMerge_testNoAnchorAtStartOfPatch() throws Exception { assertThat(e).hasMessage(getMergeExceptionMessage(file, "Incorrect document structure. Anchors are defined but there is no anchor at the start of the document.\n" + "See https://github.com/devonfw/cobigen/wiki/cobigen-textmerger#general and " - + "https://github.com/devonfw/cobigen/wiki/cobigen-textmerger#error-list " - + "for more details")); + + "https://github.com/devonfw/cobigen/wiki/cobigen-textmerger#error-list " + "for more details")); } } + /** + * Tests if line endings of base and patch file get normalized to base file if line endings of base and + * patch file differ + * @throws Exception + * if errors occur while merging + */ + @Test + public void testMerge_normalizeToBaseLineDelimiter() throws Exception { + TextAppender appender = new TextAppender("textmerge_append", false); + String mergedString = appender.merge(new File(testFileRootPath + "TestBaseLineDelimiter.txt"), + FileUtils.readFileToString(new File(testFileRootPath + "PatchBaseLineDelimiter.txt")), "UTF-8"); + assertThat(mergedString) + .isEqualTo(FileUtils.readFileToString(new File(testFileRootPath + "MergedBaseLineDelimiter.txt"))); + } + /** * Helper method that creates a String matching the usual look of a merge exception * @param base diff --git a/cobigen/cobigen-textmerger/src/test/resources/MergedBaseLineDelimiter.txt b/cobigen/cobigen-textmerger/src/test/resources/MergedBaseLineDelimiter.txt new file mode 100644 index 0000000000..f916f2839d --- /dev/null +++ b/cobigen/cobigen-textmerger/src/test/resources/MergedBaseLineDelimiter.txt @@ -0,0 +1,3 @@ +a +bc +d \ No newline at end of file diff --git a/cobigen/cobigen-textmerger/src/test/resources/PatchBaseLineDelimiter.txt b/cobigen/cobigen-textmerger/src/test/resources/PatchBaseLineDelimiter.txt new file mode 100644 index 0000000000..7abb43b567 --- /dev/null +++ b/cobigen/cobigen-textmerger/src/test/resources/PatchBaseLineDelimiter.txt @@ -0,0 +1,2 @@ +c +d \ No newline at end of file diff --git a/cobigen/cobigen-textmerger/src/test/resources/TestBaseLineDelimiter.txt b/cobigen/cobigen-textmerger/src/test/resources/TestBaseLineDelimiter.txt new file mode 100644 index 0000000000..0a207c060e --- /dev/null +++ b/cobigen/cobigen-textmerger/src/test/resources/TestBaseLineDelimiter.txt @@ -0,0 +1,2 @@ +a +b \ No newline at end of file diff --git a/documentation/master-cobigen.asciidoc b/documentation/master-cobigen.asciidoc index 24d3828b2d..b956a5b625 100644 --- a/documentation/master-cobigen.asciidoc +++ b/documentation/master-cobigen.asciidoc @@ -22,7 +22,7 @@ DISCLAIMER: All Cobigen plugins are compatible with the latest release of Devonf * CobiGen - XML Plug-in v7.0.0 * CobiGen - TypeScript Plug-in v7.1.0 * CobiGen - Property Plug-in v7.0.0 -* CobiGen - Text Merger v7.0.0 +* CobiGen - Text Merger v7.1.0 * CobiGen - JSON Plug-in v7.0.0 * CobiGen - HTML Plug-in v7.0.0 * CobiGen - Open API Plug-in v7.0.0