diff options
4 files changed, 144 insertions, 19 deletions
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/QuotedStringGitPathStyleTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/QuotedStringGitPathStyleTest.java index 9a0c96e171..c09b136ca6 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/QuotedStringGitPathStyleTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/QuotedStringGitPathStyleTest.java @@ -45,6 +45,7 @@ package org.eclipse.jgit.util; import static java.nio.charset.StandardCharsets.ISO_8859_1; import static org.eclipse.jgit.util.QuotedString.GIT_PATH; +import static org.eclipse.jgit.util.QuotedString.GIT_PATH_MINIMAL; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotSame; @@ -67,6 +68,12 @@ public class QuotedStringGitPathStyleTest { assertEquals(exp, r); } + private static void assertDequoteMinimal(String exp, String in) { + final byte[] b = ('"' + in + '"').getBytes(ISO_8859_1); + final String r = GIT_PATH_MINIMAL.dequote(b, 0, b.length); + assertEquals(exp, r); + } + @Test public void testQuote_Empty() { assertEquals("\"\"", GIT_PATH.quote("")); @@ -206,4 +213,75 @@ public class QuotedStringGitPathStyleTest { assertSame("abc@2x.png", GIT_PATH.quote("abc@2x.png")); assertDequote("abc@2x.png", "abc\\1002x.png"); } + + @Test + public void testNoQuote() { + assertSame("\u00c5ngstr\u00f6m", + GIT_PATH_MINIMAL.quote("\u00c5ngstr\u00f6m")); + } + + @Test + public void testQuoteMinimal() { + assertEquals("\"\u00c5n\\\\str\u00f6m\"", + GIT_PATH_MINIMAL.quote("\u00c5n\\str\u00f6m")); + } + + @Test + public void testDequoteMinimal() { + assertEquals("\u00c5n\\str\u00f6m", GIT_PATH_MINIMAL + .dequote(GIT_PATH_MINIMAL.quote("\u00c5n\\str\u00f6m"))); + + } + + @Test + public void testRoundtripMinimal() { + assertEquals("\u00c5ngstr\u00f6m", GIT_PATH_MINIMAL + .dequote(GIT_PATH_MINIMAL.quote("\u00c5ngstr\u00f6m"))); + + } + + @Test + public void testQuoteMinimalDequoteNormal() { + assertEquals("\u00c5n\\str\u00f6m", GIT_PATH + .dequote(GIT_PATH_MINIMAL.quote("\u00c5n\\str\u00f6m"))); + + } + + @Test + public void testQuoteNormalDequoteMinimal() { + assertEquals("\u00c5n\\str\u00f6m", GIT_PATH_MINIMAL + .dequote(GIT_PATH.quote("\u00c5n\\str\u00f6m"))); + + } + + @Test + public void testRoundtripMinimalDequoteNormal() { + assertEquals("\u00c5ngstr\u00f6m", + GIT_PATH.dequote(GIT_PATH_MINIMAL.quote("\u00c5ngstr\u00f6m"))); + + } + + @Test + public void testRoundtripNormalDequoteMinimal() { + assertEquals("\u00c5ngstr\u00f6m", + GIT_PATH_MINIMAL.dequote(GIT_PATH.quote("\u00c5ngstr\u00f6m"))); + + } + + @Test + public void testDequote_UTF8_Minimal() { + assertDequoteMinimal("\u00c5ngstr\u00f6m", + "\\303\\205ngstr\\303\\266m"); + } + + @Test + public void testDequote_RawUTF8_Minimal() { + assertDequoteMinimal("\u00c5ngstr\u00f6m", "\303\205ngstr\303\266m"); + } + + @Test + public void testDequote_RawLatin1_Minimal() { + assertDequoteMinimal("\u00c5ngstr\u00f6m", "\305ngstr\366m"); + } + } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffFormatter.java b/org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffFormatter.java index fa552aabe1..d764499159 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffFormatter.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/diff/DiffFormatter.java @@ -145,6 +145,8 @@ public class DiffFormatter implements AutoCloseable { private Repository repository; + private Boolean quotePaths; + /** * Create a new formatter with a default level of context. * @@ -199,6 +201,11 @@ public class DiffFormatter implements AutoCloseable { this.closeReader = closeReader; this.reader = reader; this.diffCfg = cfg.get(DiffConfig.KEY); + if (quotePaths == null) { + quotePaths = Boolean + .valueOf(cfg.getBoolean(ConfigConstants.CONFIG_CORE_SECTION, + ConfigConstants.CONFIG_KEY_QUOTE_PATH, true)); + } ContentSource cs = ContentSource.create(reader); source = new ContentSource.Pair(cs, cs); @@ -379,6 +386,21 @@ public class DiffFormatter implements AutoCloseable { } /** + * Sets whether or not path names should be quoted. + * <p> + * By default the setting of git config {@code core.quotePath} is active, + * but this can be overridden through this method. + * </p> + * + * @param quote + * whether to quote path names + * @since 5.6 + */ + public void setQuotePaths(boolean quote) { + quotePaths = Boolean.valueOf(quote); + } + + /** * Set the filter to produce only specific paths. * * If the filter is an instance of @@ -726,8 +748,11 @@ public class DiffFormatter implements AutoCloseable { return id.name(); } - private static String quotePath(String name) { - return QuotedString.GIT_PATH.quote(name); + private String quotePath(String path) { + if (quotePaths == null || quotePaths.booleanValue()) { + return QuotedString.GIT_PATH.quote(path); + } + return QuotedString.GIT_PATH_MINIMAL.quote(path); } /** diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java index f2f1d5a48f..e0bd592194 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ConfigConstants.java @@ -155,6 +155,12 @@ public final class ConfigConstants { */ public static final String CONFIG_KEY_HOOKS_PATH = "hooksPath"; + /** + * The "quotePath" key. + * @since 5.6 + */ + public static final String CONFIG_KEY_QUOTE_PATH = "quotePath"; + /** The "algorithm" key */ public static final String CONFIG_KEY_ALGORITHM = "algorithm"; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/QuotedString.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/QuotedString.java index a55cad3705..2b2358abe9 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/util/QuotedString.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/QuotedString.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008, Google Inc. + * Copyright (C) 2008, 2019 Google Inc. * and other copyright owners as documented in the project's IP log. * * This program and the accompanying materials are made available @@ -54,7 +54,15 @@ import org.eclipse.jgit.lib.Constants; */ public abstract class QuotedString { /** Quoting style that obeys the rules Git applies to file names */ - public static final GitPathStyle GIT_PATH = new GitPathStyle(); + public static final GitPathStyle GIT_PATH = new GitPathStyle(true); + + /** + * Quoting style that obeys the rules Git applies to file names when + * {@code core.quotePath = false}. + * + * @since 5.6 + */ + public static final QuotedString GIT_PATH_MINIMAL = new GitPathStyle(false); /** * Quoting style used by the Bourne shell. @@ -256,40 +264,48 @@ public abstract class QuotedString { quote['"'] = '"'; } + private final boolean quoteHigh; + @Override public String quote(String instr) { - if (instr.length() == 0) + if (instr.isEmpty()) { return "\"\""; //$NON-NLS-1$ + } boolean reuse = true; final byte[] in = Constants.encode(instr); - final StringBuilder r = new StringBuilder(2 + in.length); - r.append('"'); + final byte[] out = new byte[4 * in.length + 2]; + int o = 0; + out[o++] = '"'; for (int i = 0; i < in.length; i++) { final int c = in[i] & 0xff; if (c < quote.length) { final byte style = quote[c]; if (style == 0) { - r.append((char) c); + out[o++] = (byte) c; continue; } if (style > 0) { reuse = false; - r.append('\\'); - r.append((char) style); + out[o++] = '\\'; + out[o++] = style; continue; } + } else if (!quoteHigh) { + out[o++] = (byte) c; + continue; } reuse = false; - r.append('\\'); - r.append((char) (((c >> 6) & 03) + '0')); - r.append((char) (((c >> 3) & 07) + '0')); - r.append((char) (((c >> 0) & 07) + '0')); + out[o++] = '\\'; + out[o++] = (byte) (((c >> 6) & 03) + '0'); + out[o++] = (byte) (((c >> 3) & 07) + '0'); + out[o++] = (byte) (((c >> 0) & 07) + '0'); } - if (reuse) + if (reuse) { return instr; - r.append('"'); - return r.toString(); + } + out[o++] = '"'; + return new String(out, 0, o, UTF_8); } @Override @@ -375,8 +391,8 @@ public abstract class QuotedString { return RawParseUtils.decode(UTF_8, r, 0, rPtr); } - private GitPathStyle() { - // Singleton + private GitPathStyle(boolean doQuote) { + quoteHigh = doQuote; } } } |