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}.
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}

View File

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

View File

@ -528,29 +528,51 @@ protected Entry current() {
}
/**
* 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 <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
* 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 boolean isModified(DirCacheEntry entry, boolean forceContentCheck) {
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 boolean isModified(DirCacheEntry entry, boolean forceContentCheck) {
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()));
}
}