]> source.dussan.org Git - jgit.git/commitdiff
Add special case to WorkingTreeIterator for matching unnormalized symlinks 93/15393/17
authorRobin Rosenberg <robin.rosenberg@dewire.com>
Wed, 10 Jul 2013 22:17:23 +0000 (00:17 +0200)
committerMatthias Sohn <matthias.sohn@sap.com>
Wed, 12 Feb 2014 10:01:32 +0000 (11:01 +0100)
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>
org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java

index ac5198cd694b9c1778c9acf4adba08236ef70ba2..b57176b481cabd5929265d7f2ffb06cba2f2474e 100644 (file)
@@ -62,11 +62,13 @@ import java.util.Arrays;
 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.lib.Repository;
 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 @@ public abstract class WorkingTreeIterator extends AbstractTreeIterator {
         * @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 abstract class WorkingTreeIterator extends AbstractTreeIterator {
         * @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 abstract class WorkingTreeIterator extends AbstractTreeIterator {
                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 abstract class WorkingTreeIterator extends AbstractTreeIterator {
         *            acccess to repository data if necessary
         * @return <code>true</code> if the content doesn't match,
         *         <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())) {
                        // Content has not changed
 
@@ -908,6 +920,9 @@ public abstract class WorkingTreeIterator extends AbstractTreeIterator {
 
                        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 @@ 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 {
                // Since we only care about the length, use skip. The stream
                // may be able to more efficiently wade through its data.