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>
This commit is contained in:
parent
8dc2f54fa4
commit
0b3a5ab817
|
@ -62,11 +62,13 @@
|
||||||
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.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 @@ else if (!entry.isSmudged())
|
||||||
* @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) {
|
||||||
|
try {
|
||||||
return isModified(entry, forceContentCheck, null);
|
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
|
* @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 boolean isModified(DirCacheEntry entry, boolean forceContentCheck,
|
||||||
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 FileMode getIndexFileMode(final DirCacheIterator indexIter) {
|
||||||
* 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 @@ private boolean contentCheck(DirCacheEntry entry, ObjectReader reader) {
|
||||||
|
|
||||||
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 @@ 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 {
|
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…
Reference in New Issue