Browse Source

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 <matthias.sohn@sap.com>
stable-3.3
Robin Rosenberg 12 years ago committed by Matthias Sohn
parent
commit
0b3a5ab817
  1. 36
      org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java

36
org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java

@ -62,11 +62,13 @@ import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import org.eclipse.jgit.api.errors.JGitInternalException;
import org.eclipse.jgit.diff.RawText; import org.eclipse.jgit.diff.RawText;
import org.eclipse.jgit.dircache.DirCache; import org.eclipse.jgit.dircache.DirCache;
import org.eclipse.jgit.dircache.DirCacheEntry; import org.eclipse.jgit.dircache.DirCacheEntry;
import org.eclipse.jgit.dircache.DirCacheIterator; import org.eclipse.jgit.dircache.DirCacheIterator;
import org.eclipse.jgit.errors.CorruptObjectException; import org.eclipse.jgit.errors.CorruptObjectException;
import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.errors.NoWorkTreeException; import org.eclipse.jgit.errors.NoWorkTreeException;
import org.eclipse.jgit.ignore.IgnoreNode; import org.eclipse.jgit.ignore.IgnoreNode;
import org.eclipse.jgit.ignore.IgnoreRule; import org.eclipse.jgit.ignore.IgnoreRule;
@ -83,6 +85,7 @@ import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.submodule.SubmoduleWalk; import org.eclipse.jgit.submodule.SubmoduleWalk;
import org.eclipse.jgit.util.FS; import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.IO; import org.eclipse.jgit.util.IO;
import org.eclipse.jgit.util.RawParseUtils;
import org.eclipse.jgit.util.io.EolCanonicalizingInputStream; import org.eclipse.jgit.util.io.EolCanonicalizingInputStream;
/** /**
@ -808,7 +811,11 @@ public abstract class WorkingTreeIterator extends AbstractTreeIterator {
* @deprecated Use {@link #isModified(DirCacheEntry, boolean, ObjectReader)} * @deprecated Use {@link #isModified(DirCacheEntry, boolean, ObjectReader)}
*/ */
public boolean isModified(DirCacheEntry entry, boolean forceContentCheck) { 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 abstract class WorkingTreeIterator extends AbstractTreeIterator {
* @param reader * @param reader
* access to repository objects if necessary. Should not be null. * access to repository objects if necessary. Should not be null.
* @return true if content is most likely different. * @return true if content is most likely different.
* @throws IOException
* @since 3.3 * @since 3.3
*/ */
public boolean isModified(DirCacheEntry entry, boolean forceContentCheck, public boolean isModified(DirCacheEntry entry, boolean forceContentCheck,
ObjectReader reader) { ObjectReader reader) throws IOException {
MetadataDiff diff = compareMetadata(entry); MetadataDiff diff = compareMetadata(entry);
switch (diff) { switch (diff) {
case DIFFER_BY_TIMESTAMP: case DIFFER_BY_TIMESTAMP:
@ -848,6 +856,8 @@ public abstract class WorkingTreeIterator extends AbstractTreeIterator {
case EQUAL: case EQUAL:
return false; return false;
case DIFFER_BY_METADATA: case DIFFER_BY_METADATA:
if (mode == FileMode.SYMLINK.getBits())
return contentCheck(entry, reader);
return true; return true;
default: default:
throw new IllegalStateException(MessageFormat.format( throw new IllegalStateException(MessageFormat.format(
@ -891,8 +901,10 @@ public abstract class WorkingTreeIterator extends AbstractTreeIterator {
* acccess to repository data if necessary * acccess to repository data if necessary
* @return <code>true</code> if the content doesn't match, * @return <code>true</code> if the content doesn't match,
* <code>false</code> if it matches * <code>false</code> 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())) { if (getEntryObjectId().equals(entry.getObjectId())) {
// Content has not changed // Content has not changed
@ -908,6 +920,9 @@ public abstract class WorkingTreeIterator extends AbstractTreeIterator {
return false; return false;
} else { } else {
if (mode == FileMode.SYMLINK.getBits())
return !new File(readContentAsString(current()))
.equals(new File(readContentAsString(entry)));
// Content differs: that's a real change, perhaps // Content differs: that's a real change, perhaps
if (reader == null) // deprecated use, do no further checks if (reader == null) // deprecated use, do no further checks
return true; return true;
@ -956,6 +971,21 @@ public abstract class WorkingTreeIterator extends AbstractTreeIterator {
} }
} }
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 { private long computeLength(InputStream in) throws IOException {
// Since we only care about the length, use skip. The stream // Since we only care about the length, use skip. The stream
// may be able to more efficiently wade through its data. // may be able to more efficiently wade through its data.

Loading…
Cancel
Save