aboutsummaryrefslogtreecommitdiffstats
path: root/org.eclipse.jgit/src
diff options
context:
space:
mode:
Diffstat (limited to 'org.eclipse.jgit/src')
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectChecker.java70
1 files changed, 69 insertions, 1 deletions
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectChecker.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectChecker.java
index 38fd0a1eb6..1b135a924c 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectChecker.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectChecker.java
@@ -48,7 +48,12 @@ import static org.eclipse.jgit.util.RawParseUtils.match;
import static org.eclipse.jgit.util.RawParseUtils.nextLF;
import static org.eclipse.jgit.util.RawParseUtils.parseBase10;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
import java.text.MessageFormat;
+import java.util.HashSet;
+import java.util.Locale;
+import java.util.Set;
import org.eclipse.jgit.errors.CorruptObjectException;
import org.eclipse.jgit.internal.JGitText;
@@ -348,6 +353,9 @@ public class ObjectChecker {
final int sz = raw.length;
int ptr = 0;
int lastNameB = 0, lastNameE = 0, lastMode = 0;
+ Set<String> normalized = windows || macosx
+ ? new HashSet<String>()
+ : null;
while (ptr < sz) {
int thisMode = 0;
@@ -373,7 +381,10 @@ public class ObjectChecker {
if (ptr == sz || raw[ptr] != 0)
throw new CorruptObjectException("truncated in name");
checkPathSegment2(raw, thisNameB, ptr);
- if (duplicateName(raw, thisNameB, ptr))
+ if (normalized != null) {
+ if (normalized.add(normalize(raw, thisNameB, ptr)))
+ throw new CorruptObjectException("duplicate entry names");
+ } else if (duplicateName(raw, thisNameB, ptr))
throw new CorruptObjectException("duplicate entry names");
if (lastNameB != 0) {
@@ -558,4 +569,61 @@ public class ObjectChecker {
public void checkBlob(final byte[] raw) throws CorruptObjectException {
// We can always assume the blob is valid.
}
+
+ private String normalize(byte[] raw, int ptr, int end) {
+ String n = RawParseUtils.decode(raw, ptr, end).toLowerCase(Locale.US);
+ return macosx ? Normalizer.normalize(n) : n;
+ }
+
+ private static class Normalizer {
+ // TODO Simplify invocation to Normalizer after dropping Java 5.
+ private static final Method normalize;
+ private static final Object nfc;
+ static {
+ Method method;
+ Object formNfc;
+ try {
+ Class<?> formClazz = Class.forName("java.text.Normalizer$Form"); //$NON-NLS-1$
+ formNfc = formClazz.getField("NFC").get(null); //$NON-NLS-1$
+ method = Class.forName("java.text.Normalizer") //$NON-NLS-1$
+ .getMethod("normalize", CharSequence.class, formClazz); //$NON-NLS-1$
+ } catch (ClassNotFoundException e) {
+ method = null;
+ formNfc = null;
+ } catch (NoSuchFieldException e) {
+ method = null;
+ formNfc = null;
+ } catch (NoSuchMethodException e) {
+ method = null;
+ formNfc = null;
+ } catch (SecurityException e) {
+ method = null;
+ formNfc = null;
+ } catch (IllegalArgumentException e) {
+ method = null;
+ formNfc = null;
+ } catch (IllegalAccessException e) {
+ method = null;
+ formNfc = null;
+ }
+ normalize = method;
+ nfc = formNfc;
+ }
+
+ static String normalize(String in) {
+ if (normalize == null)
+ return in;
+ try {
+ return (String) normalize.invoke(null, in, nfc);
+ } catch (IllegalAccessException e) {
+ return in;
+ } catch (InvocationTargetException e) {
+ if (e.getCause() instanceof RuntimeException)
+ throw (RuntimeException) e.getCause();
+ if (e.getCause() instanceof Error)
+ throw (Error) e.getCause();
+ return in;
+ }
+ }
+ }
}