From 0b3a5ab817a5d82f4a2f5866ae9de9f2d91e15fd Mon Sep 17 00:00:00 2001 From: Robin Rosenberg Date: Thu, 11 Jul 2013 00:17:23 +0200 Subject: [PATCH] Add special case to WorkingTreeIterator for matching unnormalized symlinks If there is an unnormalized symbolic link in the index, lie that it matches a normalized link in the working tree. This does not make the case completely invisible everywhere though, but it helps to some degree. Change-Id: I599fb71648c41fa2310049d0e0040b3c9f09386b Signed-off-by: Matthias Sohn --- .../jgit/treewalk/WorkingTreeIterator.java | 36 +++++++++++++++++-- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java index ac5198cd6..b57176b48 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java @@ -62,11 +62,13 @@ import java.util.Collections; import java.util.Comparator; +import org.eclipse.jgit.api.errors.JGitInternalException; import org.eclipse.jgit.diff.RawText; import org.eclipse.jgit.dircache.DirCache; import org.eclipse.jgit.dircache.DirCacheEntry; import org.eclipse.jgit.dircache.DirCacheIterator; import org.eclipse.jgit.errors.CorruptObjectException; +import org.eclipse.jgit.errors.MissingObjectException; import org.eclipse.jgit.errors.NoWorkTreeException; import org.eclipse.jgit.ignore.IgnoreNode; import org.eclipse.jgit.ignore.IgnoreRule; @@ -83,6 +85,7 @@ import org.eclipse.jgit.submodule.SubmoduleWalk; import org.eclipse.jgit.util.FS; import org.eclipse.jgit.util.IO; +import org.eclipse.jgit.util.RawParseUtils; import org.eclipse.jgit.util.io.EolCanonicalizingInputStream; /** @@ -808,7 +811,11 @@ else if (!entry.isSmudged()) * @deprecated Use {@link #isModified(DirCacheEntry, boolean, ObjectReader)} */ public boolean isModified(DirCacheEntry entry, boolean forceContentCheck) { - return isModified(entry, forceContentCheck, null); + try { + return isModified(entry, forceContentCheck, null); + } catch (IOException e) { + throw new JGitInternalException(e.getMessage(), e); + } } /** @@ -827,10 +834,11 @@ public boolean isModified(DirCacheEntry entry, boolean forceContentCheck) { * @param reader * access to repository objects if necessary. Should not be null. * @return true if content is most likely different. + * @throws IOException * @since 3.3 */ public boolean isModified(DirCacheEntry entry, boolean forceContentCheck, - ObjectReader reader) { + ObjectReader reader) throws IOException { MetadataDiff diff = compareMetadata(entry); switch (diff) { case DIFFER_BY_TIMESTAMP: @@ -848,6 +856,8 @@ public boolean isModified(DirCacheEntry entry, boolean forceContentCheck, case EQUAL: return false; case DIFFER_BY_METADATA: + if (mode == FileMode.SYMLINK.getBits()) + return contentCheck(entry, reader); return true; default: throw new IllegalStateException(MessageFormat.format( @@ -891,8 +901,10 @@ public FileMode getIndexFileMode(final DirCacheIterator indexIter) { * acccess to repository data if necessary * @return true if the content doesn't match, * false if it matches + * @throws IOException */ - private boolean contentCheck(DirCacheEntry entry, ObjectReader reader) { + private boolean contentCheck(DirCacheEntry entry, ObjectReader reader) + throws IOException { if (getEntryObjectId().equals(entry.getObjectId())) { // Content has not changed @@ -908,6 +920,9 @@ private boolean contentCheck(DirCacheEntry entry, ObjectReader reader) { return false; } else { + if (mode == FileMode.SYMLINK.getBits()) + return !new File(readContentAsString(current())) + .equals(new File(readContentAsString(entry))); // Content differs: that's a real change, perhaps if (reader == null) // deprecated use, do no further checks return true; @@ -956,6 +971,21 @@ private boolean contentCheck(DirCacheEntry entry, ObjectReader reader) { } } + private String readContentAsString(DirCacheEntry entry) + throws MissingObjectException, IOException { + ObjectLoader open = repository.open(entry.getObjectId()); + byte[] cachedBytes = open.getCachedBytes(); + return RawParseUtils.decode(cachedBytes); + } + + private static String readContentAsString(Entry entry) throws IOException { + long length = entry.getLength(); + byte[] content = new byte[(int) length]; + InputStream is = entry.openInputStream(); + IO.readFully(is, content, 0, (int) length); + return RawParseUtils.decode(content); + } + private long computeLength(InputStream in) throws IOException { // Since we only care about the length, use skip. The stream // may be able to more efficiently wade through its data.