diff --git a/org.eclipse.jgit/resources/org/eclipse/jgit/JGitText.properties b/org.eclipse.jgit/resources/org/eclipse/jgit/JGitText.properties index 3049ae7d0..c03c64929 100644 --- a/org.eclipse.jgit/resources/org/eclipse/jgit/JGitText.properties +++ b/org.eclipse.jgit/resources/org/eclipse/jgit/JGitText.properties @@ -419,6 +419,7 @@ unableToCheckConnectivity=Unable to check connectivity. unableToStore=Unable to store {0}. unableToWrite=Unable to write {0} unencodeableFile=Unencodeable file: {0} +unexpectedCompareResult=Unexpected metadata comparison result: {0} unexpectedEndOfConfigFile=Unexpected end of config file unexpectedHunkTrailer=Unexpected hunk trailer unexpectedOddResult=odd: {0} + {1} - {2} diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/JGitText.java b/org.eclipse.jgit/src/org/eclipse/jgit/JGitText.java index 9718e6294..4e3cb2035 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/JGitText.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/JGitText.java @@ -479,6 +479,7 @@ public class JGitText extends TranslationBundle { /***/ public String unableToStore; /***/ public String unableToWrite; /***/ public String unencodeableFile; + /***/ public String unexpectedCompareResult; /***/ public String unexpectedEndOfConfigFile; /***/ public String unexpectedHunkTrailer; /***/ public String unexpectedOddResult; 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 69d9b22d1..48e64831c 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java @@ -528,29 +528,51 @@ public abstract class WorkingTreeIterator extends AbstractTreeIterator { } /** - * Checks whether this entry differs from a given entry from the - * {@link DirCache}. - * - * File status information is used and if status is same we consider the - * file identical to the state in the working directory. Native git uses - * more stat fields than we have accessible in Java. + * The result of a metadata-comparison between the current entry and a + * {@link DirCacheEntry} + */ + public enum MetadataDiff { + /** + * The entries are equal by metaData (mode, length, + * modification-timestamp) or the assumeValid attribute of + * the index entry is set + */ + EQUAL, + + /** + * The entries are not equal by metaData (mode, length) or the + * isUpdateNeeded attribute of the index entry is set + */ + DIFFER_BY_METADATA, + + /** index entry is smudged - can't use that entry for comparison */ + SMUDGED, + + /** + * The entries are equal by metaData (mode, length) but differ by + * modification-timestamp. + */ + DIFFER_BY_TIMESTAMP + } + + /** + * Compare the metadata (mode, length, modification-timestamp) of the + * current entry and a {@link DirCacheEntry} * * @param entry - * the entry from the dircache we want to compare against - * @param forceContentCheck - * True if the actual file content should be checked if - * modification time differs. - * @return true if content is most likely different. + * the {@link DirCacheEntry} to compare with + * @return a {@link MetadataDiff} which tells whether and how the entries + * metadata differ */ - public boolean isModified(DirCacheEntry entry, boolean forceContentCheck) { + public MetadataDiff compareMetadata(DirCacheEntry entry) { if (entry.isAssumeValid()) - return false; + return MetadataDiff.EQUAL; if (entry.isUpdateNeeded()) - return true; + return MetadataDiff.DIFFER_BY_METADATA; if (!entry.isSmudged() && (getEntryLength() != entry.getLength())) - return true; + return MetadataDiff.DIFFER_BY_METADATA; // Determine difference in mode-bits of file and index-entry. In the // bitwise presentation of modeDiff we'll have a '1' when the two modes @@ -567,7 +589,7 @@ public abstract class WorkingTreeIterator extends AbstractTreeIterator { if (modeDiff != 0) // Report a modification if the modes still (after potentially // ignoring EXECUTABLE_FILE bits) differ - return true; + return MetadataDiff.DIFFER_BY_METADATA; } // Git under windows only stores seconds so we round the timestamp @@ -578,27 +600,52 @@ public abstract class WorkingTreeIterator extends AbstractTreeIterator { if (cacheLastModified % 1000 == 0) fileLastModified = fileLastModified - fileLastModified % 1000; - if (fileLastModified != cacheLastModified) { - // The file is dirty by timestamps - if (forceContentCheck) { + if (fileLastModified != cacheLastModified) + return MetadataDiff.DIFFER_BY_TIMESTAMP; + else if (!entry.isSmudged()) + // The file is clean when you look at timestamps. + return MetadataDiff.EQUAL; + else + return MetadataDiff.SMUDGED; + } + + /** + * Checks whether this entry differs from a given entry from the + * {@link DirCache}. + * + * File status information is used and if status is same we consider the + * file identical to the state in the working directory. Native git uses + * more stat fields than we have accessible in Java. + * + * @param entry + * the entry from the dircache we want to compare against + * @param forceContentCheck + * True if the actual file content should be checked if + * modification time differs. + * @return true if content is most likely different. + */ + public boolean isModified(DirCacheEntry entry, boolean forceContentCheck) { + MetadataDiff diff = compareMetadata(entry); + switch (diff) { + case DIFFER_BY_TIMESTAMP: + if (forceContentCheck) // But we are told to look at content even though timestamps // tell us about modification return contentCheck(entry); - } else { + else // We are told to assume a modification if timestamps differs return true; - } - } else { - // The file is clean when you look at timestamps. - if (entry.isSmudged()) { - // The file is clean by timestamps but the entry was smudged. - // Lets do a content check - return contentCheck(entry); - } else { - // The file is clean by timestamps and the entry is not - // smudged: Can't get any cleaner! - return false; - } + case SMUDGED: + // The file is clean by timestamps but the entry was smudged. + // Lets do a content check + return contentCheck(entry); + case EQUAL: + return false; + case DIFFER_BY_METADATA: + return true; + default: + throw new IllegalStateException(MessageFormat.format( + JGitText.get().unexpectedCompareResult, diff.name())); } }