From 8b3ab4343c4d34993176b5fa799a039e8114054b Mon Sep 17 00:00:00 2001 From: Dave Borowitz Date: Mon, 20 Nov 2017 13:55:25 -0500 Subject: [PATCH] Config: Handle leading/trailing single whitespaces Change-Id: I468106acd2006d0a174c76dfd4bce231f1c7a6f8 --- .../tst/org/eclipse/jgit/lib/ConfigTest.java | 52 +++++++++++++++++++ .../src/org/eclipse/jgit/lib/Config.java | 22 ++++++-- 2 files changed, 71 insertions(+), 3 deletions(-) diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ConfigTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ConfigTest.java index e9505f67d..748848e97 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ConfigTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ConfigTest.java @@ -965,4 +965,56 @@ public void testTimeUnitNegative() throws ConfigInvalidException { expectedEx.expect(IllegalArgumentException.class); parseTime("-1", MILLISECONDS); } + + @Test + public void testEscapeSpacesOnly() throws ConfigInvalidException { + assertEquals("", Config.escapeValue("")); + assertEquals("\" \"", Config.escapeValue(" ")); + assertEquals("\" \"", Config.escapeValue(" ")); + + assertParseRoundTrip(" "); + assertParseRoundTrip(" "); + } + + @Test + public void testEscapeLeadingSpace() throws ConfigInvalidException { + assertEquals("x", Config.escapeValue("x")); + assertEquals("\" x\"", Config.escapeValue(" x")); + assertEquals("\" x\"", Config.escapeValue(" x")); + + assertParseRoundTrip("x"); + assertParseRoundTrip(" x"); + assertParseRoundTrip(" x"); + } + + @Test + public void testEscapeTrailingSpace() throws ConfigInvalidException { + assertEquals("x", Config.escapeValue("x")); + assertEquals("\"x \"", Config.escapeValue("x ")); + assertEquals("x\" \"", Config.escapeValue("x ")); + + assertParseRoundTrip("x"); + assertParseRoundTrip("x "); + assertParseRoundTrip("x "); + } + + @Test + public void testEscapeLeadingAndTrailingSpace() + throws ConfigInvalidException { + assertEquals("\" x \"", Config.escapeValue(" x ")); + assertEquals("\" x \"", Config.escapeValue(" x ")); + assertEquals("\" x \"", Config.escapeValue(" x ")); + assertEquals("\" x \"", Config.escapeValue(" x ")); + + assertParseRoundTrip(" x "); + assertParseRoundTrip(" x "); + assertParseRoundTrip(" x "); + assertParseRoundTrip(" x "); + } + + private static void assertParseRoundTrip(String value) + throws ConfigInvalidException { + Config c = parse("[foo]\nbar = " + Config.escapeValue(value)); + assertEquals(value, c.getString("foo", null, "bar")); + } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Config.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Config.java index 6281bcfb3..77dfce108 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Config.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Config.java @@ -147,7 +147,10 @@ public static void setTypedConfigGetter(TypedConfigGetter getter) { * the value to escape * @return the escaped value */ - private static String escapeValue(final String x) { + static String escapeValue(final String x) { + if (x.isEmpty()) { + return ""; //$NON-NLS-1$ + } boolean inquote = false; int lineStart = 0; final StringBuilder r = new StringBuilder(x.length()); @@ -189,8 +192,7 @@ private static String escapeValue(final String x) { break; case ' ': - if (!inquote && r.length() > 0 - && r.charAt(r.length() - 1) == ' ') { + if (!inquote && (r.length() == 0 || r.charAt(r.length() - 1) == ' ')) { r.insert(lineStart, '"'); inquote = true; } @@ -202,6 +204,20 @@ private static String escapeValue(final String x) { break; } } + + if (!inquote) { + // Ensure any trailing whitespace is quoted. + int s = x.length(); + while (s > 0 && x.charAt(s - 1) == ' ') { + s--; + } + if (s != x.length()) { + // Can't insert at lineStart since there may be intervening quotes. + r.insert(s, '"'); + inquote = true; + } + } + if (inquote) { r.append('"'); }