Commit 0da62c5cf094394e7d9a4f7ef0832f8459ab3d40

Edward Thomson 2013-04-17T10:52:49

checkout: use cache when possible to determine if workdir item is dirty If the on-disk file has been staged (it's stat data matches the stat data in the cache) then we need not hash the file to determine whether it differs from the checkout target; instead we can simply use the oid in the index. This prevents recomputing a file's hash unnecessarily, prevents loading the file (when filtering) and prevents edge cases where filters suggest that a file is dirty immediately after git writes the file.

diff --git a/src/checkout.c b/src/checkout.c
index 24fa210..81dc5e3 100644
--- a/src/checkout.c
+++ b/src/checkout.c
@@ -119,6 +119,7 @@ static bool checkout_is_workdir_modified(
 	const git_index_entry *wditem)
 {
 	git_oid oid;
+	const git_index_entry *ie;
 
 	/* handle "modified" submodule */
 	if (wditem->mode == GIT_FILEMODE_COMMIT) {
@@ -140,6 +141,17 @@ static bool checkout_is_workdir_modified(
 		return (git_oid_cmp(&baseitem->oid, sm_oid) != 0);
 	}
 
+	/* Look at the cache to decide if the workdir is modified.  If not,
+	 * we can simply compare the oid in the cache to the baseitem instead
+	 * of hashing the file.
+	 */
+	if ((ie = git_index_get_bypath(data->index, wditem->path, 0)) != NULL) {
+		if (wditem->mtime.seconds == ie->mtime.seconds &&
+			wditem->mtime.nanoseconds == ie->mtime.nanoseconds &&
+			wditem->file_size == ie->file_size)
+			return (git_oid_cmp(&baseitem->oid, &ie->oid) != 0);
+	}
+
 	/* depending on where base is coming from, we may or may not know
 	 * the actual size of the data, so we can't rely on this shortcut.
 	 */