@ -398,20 +398,20 @@ public abstract class WorkingTreeIterator extends AbstractTreeIterator {
if ( entry . isUpdateNeeded ( ) )
if ( entry . isUpdateNeeded ( ) )
return true ;
return true ;
if ( getEntryLength ( ) ! = entry . getLength ( ) )
if ( ! entry . isSmudged ( ) & & ( getEntryLength ( ) ! = entry . getLength ( ) ) )
return true ;
return true ;
// d etermine difference in mode-bits of file and index-entry. In the
// D etermine difference in mode-bits of file and index-entry. In the
// bitwise presentation of modeDiff we'll have a '1' when the two modes
// bitwise presentation of modeDiff we'll have a '1' when the two modes
// differ at this position.
// differ at this position.
int modeDiff = getEntryRawMode ( ) ^ entry . getRawMode ( ) ;
int modeDiff = getEntryRawMode ( ) ^ entry . getRawMode ( ) ;
// i gnore the executable file bits if checkFilemode tells me to do so.
// I gnore the executable file bits if checkFilemode tells me to do so.
// Ignoring is done by setting the bits representing a EXECUTABLE_FILE
// Ignoring is done by setting the bits representing a EXECUTABLE_FILE
// to '0' in modeDiff
// to '0' in modeDiff
if ( ! checkFilemode )
if ( ! checkFilemode )
modeDiff & = ~ FileMode . EXECUTABLE_FILE . getBits ( ) ;
modeDiff & = ~ FileMode . EXECUTABLE_FILE . getBits ( ) ;
if ( modeDiff ! = 0 )
if ( modeDiff ! = 0 )
// r eport a modification if the modes still (after potentially
// R eport a modification if the modes still (after potentially
// ignoring EXECUTABLE_FILE bits) differ
// ignoring EXECUTABLE_FILE bits) differ
return true ;
return true ;
@ -422,14 +422,58 @@ public abstract class WorkingTreeIterator extends AbstractTreeIterator {
long fileLastModified = getEntryLastModified ( ) ;
long fileLastModified = getEntryLastModified ( ) ;
if ( cacheLastModified % 1000 = = 0 )
if ( cacheLastModified % 1000 = = 0 )
fileLastModified = fileLastModified - fileLastModified % 1000 ;
fileLastModified = fileLastModified - fileLastModified % 1000 ;
if ( fileLastModified ! = cacheLastModified ) {
// The file is dirty by timestamps
if ( forceContentCheck ) {
if ( forceContentCheck ) {
if ( fileLastModified = = cacheLastModified )
// But we are told to look at content even though timestamps
return false ; // Same time, don't check content.
// tell us about modification
else
return contentCheck ( entry ) ;
return ! getEntryObjectId ( ) . equals ( entry . getObjectId ( ) ) ;
} else {
// We are told to assume a modification if timestamps differs
return true ;
}
} else {
} else {
// No content check forced, assume dirty if stat differs.
// The file is clean when you look at timestamps.
return fileLastModified ! = cacheLastModified ;
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 ;
}
}
}
/ * *
* Compares the entries content with the content in the filesystem .
* Unsmudges the entry when it is detected that it is clean .
*
* @param entry
* the entry to be checked
* @return < code > true < / code > if the content matches , < code > false < / code >
* otherwise
* /
private boolean contentCheck ( DirCacheEntry entry ) {
if ( getEntryObjectId ( ) . equals ( entry . getObjectId ( ) ) ) {
// Content has not changed
// We know the entry can't be racily clean because it's still clean.
// Therefore we unsmudge the entry!
// If by any chance we now unsmudge although we are still in the
// same time-slot as the last modification to the index file the
// next index write operation will smudge again.
// Caution: we are unsmudging just by setting the length of the
// in-memory entry object. It's the callers task to detect that we
// have modified the entry and to persist the modified index.
entry . setLength ( ( int ) getEntryLength ( ) ) ;
return false ;
} else {
// Content differs: that's a real change!
return true ;
}
}
}
}