Introduce metaData compare between working tree and index entries

Instead of offering only a high-level isModified() method a new
method compareMetadata() is introduced which compares a working tree entry
and a index entry by looking at metadata only. Some use-cases
(e.g. computing the content-id in idBuffer()) may use this new method
instead of isModified().

Change-Id: I4de7501d159889fbac5ae6951f4fef8340461b47
Signed-off-by: Chris Aniszczyk <caniszczyk@gmail.com>
This commit is contained in:
Christian Halstrick 2010-12-31 14:42:41 +01:00 committed by Chris Aniszczyk
parent 5e2e3819a6
commit c62882191f
3 changed files with 81 additions and 32 deletions

View File

@ -419,6 +419,7 @@ unableToCheckConnectivity=Unable to check connectivity.
unableToStore=Unable to store {0}. unableToStore=Unable to store {0}.
unableToWrite=Unable to write {0} unableToWrite=Unable to write {0}
unencodeableFile=Unencodeable file: {0} unencodeableFile=Unencodeable file: {0}
unexpectedCompareResult=Unexpected metadata comparison result: {0}
unexpectedEndOfConfigFile=Unexpected end of config file unexpectedEndOfConfigFile=Unexpected end of config file
unexpectedHunkTrailer=Unexpected hunk trailer unexpectedHunkTrailer=Unexpected hunk trailer
unexpectedOddResult=odd: {0} + {1} - {2} unexpectedOddResult=odd: {0} + {1} - {2}

View File

@ -479,6 +479,7 @@ public static JGitText get() {
/***/ public String unableToStore; /***/ public String unableToStore;
/***/ public String unableToWrite; /***/ public String unableToWrite;
/***/ public String unencodeableFile; /***/ public String unencodeableFile;
/***/ public String unexpectedCompareResult;
/***/ public String unexpectedEndOfConfigFile; /***/ public String unexpectedEndOfConfigFile;
/***/ public String unexpectedHunkTrailer; /***/ public String unexpectedHunkTrailer;
/***/ public String unexpectedOddResult; /***/ public String unexpectedOddResult;

View File

@ -528,29 +528,51 @@ protected Entry current() {
} }
/** /**
* Checks whether this entry differs from a given entry from the * The result of a metadata-comparison between the current entry and a
* {@link DirCache}. * {@link DirCacheEntry}
* */
* File status information is used and if status is same we consider the public enum MetadataDiff {
* file identical to the state in the working directory. Native git uses /**
* more stat fields than we have accessible in Java. * The entries are equal by metaData (mode, length,
* modification-timestamp) or the <code>assumeValid</code> attribute of
* the index entry is set
*/
EQUAL,
/**
* The entries are not equal by metaData (mode, length) or the
* <code>isUpdateNeeded</code> 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 * @param entry
* the entry from the dircache we want to compare against * the {@link DirCacheEntry} to compare with
* @param forceContentCheck * @return a {@link MetadataDiff} which tells whether and how the entries
* True if the actual file content should be checked if * metadata differ
* modification time differs.
* @return true if content is most likely different.
*/ */
public boolean isModified(DirCacheEntry entry, boolean forceContentCheck) { public MetadataDiff compareMetadata(DirCacheEntry entry) {
if (entry.isAssumeValid()) if (entry.isAssumeValid())
return false; return MetadataDiff.EQUAL;
if (entry.isUpdateNeeded()) if (entry.isUpdateNeeded())
return true; return MetadataDiff.DIFFER_BY_METADATA;
if (!entry.isSmudged() && (getEntryLength() != entry.getLength())) 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 // 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 // bitwise presentation of modeDiff we'll have a '1' when the two modes
@ -567,7 +589,7 @@ public boolean isModified(DirCacheEntry entry, boolean forceContentCheck) {
if (modeDiff != 0) if (modeDiff != 0)
// Report a modification if the modes still (after potentially // Report a modification if the modes still (after potentially
// ignoring EXECUTABLE_FILE bits) differ // ignoring EXECUTABLE_FILE bits) differ
return true; return MetadataDiff.DIFFER_BY_METADATA;
} }
// Git under windows only stores seconds so we round the timestamp // Git under windows only stores seconds so we round the timestamp
@ -578,27 +600,52 @@ public boolean isModified(DirCacheEntry entry, boolean forceContentCheck) {
if (cacheLastModified % 1000 == 0) if (cacheLastModified % 1000 == 0)
fileLastModified = fileLastModified - fileLastModified % 1000; fileLastModified = fileLastModified - fileLastModified % 1000;
if (fileLastModified != cacheLastModified) { if (fileLastModified != cacheLastModified)
// The file is dirty by timestamps return MetadataDiff.DIFFER_BY_TIMESTAMP;
if (forceContentCheck) { 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 // But we are told to look at content even though timestamps
// tell us about modification // tell us about modification
return contentCheck(entry); return contentCheck(entry);
} else { else
// We are told to assume a modification if timestamps differs // We are told to assume a modification if timestamps differs
return true; return true;
} case SMUDGED:
} else { // The file is clean by timestamps but the entry was smudged.
// The file is clean when you look at timestamps. // Lets do a content check
if (entry.isSmudged()) { return contentCheck(entry);
// The file is clean by timestamps but the entry was smudged. case EQUAL:
// Lets do a content check return false;
return contentCheck(entry); case DIFFER_BY_METADATA:
} else { return true;
// The file is clean by timestamps and the entry is not default:
// smudged: Can't get any cleaner! throw new IllegalStateException(MessageFormat.format(
return false; JGitText.get().unexpectedCompareResult, diff.name()));
}
} }
} }