Canonical git treats CR-LF in config files as LF.[1][2] JGit does so, too, except when escaped as a line continuation. Correct this and treat the sequence \-CR-LF as a line continuation. [1] https://github.com/git/git/commit/db2c075d9 [2] https://github.com/git/git/blob/v2.21.0/config.c#L485 Bug: 545850 Change-Id: I51e7378a22c21b3baa3701163c423d04c900af5a Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch> Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>tags/v5.4.0.201906121030-r
@@ -1457,6 +1457,41 @@ public class ConfigTest { | |||
parse("[foo \"bar\" ]\nfoo=bar\n"); | |||
} | |||
@Test | |||
public void testCrLf() throws ConfigInvalidException { | |||
assertEquals("true", parseEscapedValue("true\r\n")); | |||
} | |||
@Test | |||
public void testLfContinuation() throws ConfigInvalidException { | |||
assertEquals("true", parseEscapedValue("tr\\\nue")); | |||
} | |||
@Test | |||
public void testCrCharContinuation() throws ConfigInvalidException { | |||
expectedEx.expect(ConfigInvalidException.class); | |||
expectedEx.expectMessage("Bad escape: \\u000d"); | |||
parseEscapedValue("tr\\\rue"); | |||
} | |||
@Test | |||
public void testCrEOFContinuation() throws ConfigInvalidException { | |||
expectedEx.expect(ConfigInvalidException.class); | |||
expectedEx.expectMessage("Bad escape: \\u000d"); | |||
parseEscapedValue("tr\\\r"); | |||
} | |||
@Test | |||
public void testCrLfContinuation() throws ConfigInvalidException { | |||
assertEquals("true", parseEscapedValue("tr\\\r\nue")); | |||
} | |||
@Test | |||
public void testWhitespaceContinuation() throws ConfigInvalidException { | |||
assertEquals("tr ue", parseEscapedValue("tr \\\n ue")); | |||
assertEquals("tr ue", parseEscapedValue("tr \\\r\n ue")); | |||
} | |||
private static void assertValueRoundTrip(String value) | |||
throws ConfigInvalidException { | |||
assertValueRoundTrip(value, value); |
@@ -1413,11 +1413,23 @@ public class Config { | |||
case '"': | |||
value.append('"'); | |||
continue; | |||
case '\r': { | |||
int next = in.read(); | |||
if (next == '\n') { | |||
continue; // CR-LF | |||
} else if (next >= 0) { | |||
in.reset(); | |||
} | |||
break; | |||
} | |||
default: | |||
throw new ConfigInvalidException(MessageFormat.format( | |||
JGitText.get().badEscape, | |||
Character.valueOf(((char) c)))); | |||
break; | |||
} | |||
throw new ConfigInvalidException( | |||
MessageFormat.format(JGitText.get().badEscape, | |||
Character.isAlphabetic(c) | |||
? Character.valueOf(((char) c)) | |||
: toUnicodeLiteral(c))); | |||
} | |||
if ('"' == c) { | |||
@@ -1430,6 +1442,11 @@ public class Config { | |||
return value.length() > 0 ? value.toString() : null; | |||
} | |||
private static String toUnicodeLiteral(int c) { | |||
return String.format("\\u%04x", //$NON-NLS-1$ | |||
Integer.valueOf(c)); | |||
} | |||
/** | |||
* Parses a section of the configuration into an application model object. | |||
* <p> |