Browse Source

Merge changes I0f1df93b,Ifd40129b,I1b059e1a

* changes:
  ConfigTest: Add some additional comment parsing tests
  Config: Drop backslash in invalid escape sequences in subsections
  Config: Match C git behavior more closely in escaping values
stable-4.10
Dave Borowitz 7 years ago committed by Gerrit Code Review @ Eclipse.org
parent
commit
83a7a3482e
  1. 2
      org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/T0003_BasicTest.java
  2. 45
      org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ConfigTest.java
  3. 33
      org.eclipse.jgit/src/org/eclipse/jgit/lib/Config.java

2
org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/T0003_BasicTest.java

@ -368,7 +368,7 @@ public class T0003_BasicTest extends SampleDataRepositoryTestCase {
+ "[user]\n" + "[user]\n"
+ " email = A U Thor <thor@example.com> # Just an example...\n" + " email = A U Thor <thor@example.com> # Just an example...\n"
+ " name = \"A Thor \\\\ \\\"\\t \"\n" + " name = \"A Thor \\\\ \\\"\\t \"\n"
+ " defaultCheckInComment = \"a many line\\ncomment\\n to test\"\n"; + " defaultCheckInComment = a many line\\ncomment\\n to test\n";
assertEquals(expectedStr, new String(IO.readFully(cfg), Constants.CHARSET)); assertEquals(expectedStr, new String(IO.readFully(cfg), Constants.CHARSET));
} }

45
org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ConfigTest.java

@ -977,14 +977,25 @@ public class ConfigTest {
} }
@Test @Test
public void testEscapeSpecialCharacters() throws ConfigInvalidException { public void testNoEscapeSpecialCharacters() throws ConfigInvalidException {
assertValueRoundTrip("x\\y", "x\\\\y");
assertValueRoundTrip("x\"y", "x\\\"y");
assertValueRoundTrip("x\ny", "x\\ny");
assertValueRoundTrip("x\ty", "x\\ty");
assertValueRoundTrip("x\by", "x\\by");
}
@Test
public void testParseLiteralBackspace() throws ConfigInvalidException {
// This is round-tripped with an escape sequence by JGit, but C git writes
// it out as a literal backslash.
assertEquals("x\by", parseEscapedValue("x\by"));
}
@Test
public void testEscapeCommentCharacters() throws ConfigInvalidException {
assertValueRoundTrip("x#y", "\"x#y\""); assertValueRoundTrip("x#y", "\"x#y\"");
assertValueRoundTrip("x;y", "\"x;y\""); assertValueRoundTrip("x;y", "\"x;y\"");
assertValueRoundTrip("x\\y", "\"x\\\\y\"");
assertValueRoundTrip("x\"y", "\"x\\\"y\"");
assertValueRoundTrip("x\ny", "\"x\\ny\"");
assertValueRoundTrip("x\ty", "\"x\\ty\"");
assertValueRoundTrip("x\by", "\"x\\by\"");
} }
@Test @Test
@ -1014,6 +1025,11 @@ public class ConfigTest {
assertEquals("baz", parseEscapedValue("baz # comment")); assertEquals("baz", parseEscapedValue("baz # comment"));
assertEquals("baz", parseEscapedValue("baz " + WS + " ; comment")); assertEquals("baz", parseEscapedValue("baz " + WS + " ; comment"));
assertEquals("baz", parseEscapedValue("baz " + WS + " # comment")); assertEquals("baz", parseEscapedValue("baz " + WS + " # comment"));
assertEquals("baz ", parseEscapedValue("\"baz \"; comment"));
assertEquals("baz ", parseEscapedValue("\"baz \"# comment"));
assertEquals("baz ", parseEscapedValue("\"baz \" ; comment"));
assertEquals("baz ", parseEscapedValue("\"baz \" # comment"));
} }
@Test @Test
@ -1045,16 +1061,17 @@ public class ConfigTest {
public void testParseInvalidSubsections() { public void testParseInvalidSubsections() {
assertInvalidSubsection( assertInvalidSubsection(
JGitText.get().newlineInQuotesNotAllowed, "\"x\ny\""); JGitText.get().newlineInQuotesNotAllowed, "\"x\ny\"");
assertInvalidSubsection( }
MessageFormat.format(JGitText.get().badEscape, 'q'), "\"x\\q\"");
@Test
public void testDropBackslashFromInvalidEscapeSequenceInSubsectionName()
throws ConfigInvalidException {
assertEquals("x0", parseEscapedSubsection("\"x\\0\""));
assertEquals("xq", parseEscapedSubsection("\"x\\q\""));
// Unlike for values, \b, \n, and \t are not valid escape sequences. // Unlike for values, \b, \n, and \t are not valid escape sequences.
assertInvalidSubsection( assertEquals("xb", parseEscapedSubsection("\"x\\b\""));
MessageFormat.format(JGitText.get().badEscape, 'b'), "\"x\\b\""); assertEquals("xn", parseEscapedSubsection("\"x\\n\""));
assertInvalidSubsection( assertEquals("xt", parseEscapedSubsection("\"x\\t\""));
MessageFormat.format(JGitText.get().badEscape, 'n'), "\"x\\n\"");
assertInvalidSubsection(
MessageFormat.format(JGitText.get().badEscape, 't'), "\"x\\t\"");
} }
private static void assertValueRoundTrip(String value) private static void assertValueRoundTrip(String value)

33
org.eclipse.jgit/src/org/eclipse/jgit/lib/Config.java

@ -155,9 +155,18 @@ public class Config {
StringBuilder r = new StringBuilder(x.length()); StringBuilder r = new StringBuilder(x.length());
for (int k = 0; k < x.length(); k++) { for (int k = 0; k < x.length(); k++) {
char c = x.charAt(k); char c = x.charAt(k);
boolean thisCharNeedsQuote = true; // git-config(1) lists the limited set of supported escape sequences, but
// the documentation is otherwise not especially normative. In particular,
// git-config(1) lists the limited set of supported escape sequences. // which ones of these produce and/or require escaping and/or quoting
// around them is not documented and was discovered by trial and error.
// In summary:
//
// * Quotes are only required if there is leading/trailing whitespace or a
// comment character.
// * Bytes that have a supported escape sequence are escaped, except for
// \b for some reason which isn't.
// * Needing an escape sequence is not sufficient reason to quote the
// value.
switch (c) { switch (c) {
case '\0': case '\0':
// Unix command line calling convention cannot pass a '\0' as an // Unix command line calling convention cannot pass a '\0' as an
@ -175,25 +184,30 @@ public class Config {
break; break;
case '\b': case '\b':
// Doesn't match `git config foo.bar $'x\by'`, which doesn't escape the
// \x08, but since both escaped and unescaped forms are readable, we'll
// prefer internal consistency here.
r.append('\\').append('b'); r.append('\\').append('b');
break; break;
case '\\': case '\\':
r.append('\\').append('\\');
break;
case '"': case '"':
r.append('\\').append(c); r.append('\\').append('"');
break; break;
case '#': case '#':
case ';': case ';':
needQuote = true;
r.append(c); r.append(c);
break; break;
default: default:
thisCharNeedsQuote = false;
r.append(c); r.append(c);
break; break;
} }
needQuote |= thisCharNeedsQuote;
} }
return needQuote ? '"' + r.toString() + '"' : r.toString(); return needQuote ? '"' + r.toString() + '"' : r.toString();
@ -1301,9 +1315,10 @@ public class Config {
continue; continue;
default: default:
throw new ConfigInvalidException(MessageFormat.format( // C git simply drops backslashes if the escape sequence is not
JGitText.get().badEscape, // recognized.
Character.valueOf(((char) c)))); r.append((char) c);
continue;
} }
} }
if ('"' == c) { if ('"' == c) {

Loading…
Cancel
Save