From c98d97731b87417b196341fa63a50fffea4e123c Mon Sep 17 00:00:00 2001 From: Christian Halstrick Date: Thu, 15 Jul 2010 13:36:11 +0200 Subject: [PATCH] Smudge racily clean index entries by truncating length (like git.git) To mark an entry racily clean we set its length to 0 (like native git does). Entries which are not racily clean and have zero length can be distinguished from racily clean entries by checking P_OBJECTID against the SHA1 of empty content. When length is 0 and P_OBJECTID is different from SHA1 of empty content we know the entry is marked racily clean. See http://dev.eclipse.org/mhonarc/lists/jgit-dev/msg00488.html Change-Id: I689552931441ab51964b430b303160c9126b66af Signed-off-by: Christian Halstrick Signed-off-by: Matthias Sohn --- .../eclipse/jgit/dircache/DirCacheEntry.java | 44 +++++++++++-------- .../src/org/eclipse/jgit/lib/Constants.java | 4 ++ 2 files changed, 30 insertions(+), 18 deletions(-) diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheEntry.java b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheEntry.java index 7cb1472e46..909729d6c6 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheEntry.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheEntry.java @@ -2,6 +2,7 @@ * Copyright (C) 2008-2009, Google Inc. * Copyright (C) 2008, Shawn O. Pearce * Copyright (C) 2010, Matthias Sohn + * Copyright (C) 2010, Christian Halstrick * and other copyright owners as documented in the project's IP log. * * This program and the accompanying materials are made available @@ -282,7 +283,7 @@ public class DirCacheEntry { * nanoseconds component of the index's last modified time. * @return true if extra careful checks should be used. */ - final boolean mightBeRacilyClean(final int smudge_s, final int smudge_ns) { + public final boolean mightBeRacilyClean(final int smudge_s, final int smudge_ns) { // If the index has a modification time then it came from disk // and was not generated from scratch in memory. In such cases // the entry is 'racily clean' if the entry's cached modification @@ -292,8 +293,6 @@ public class DirCacheEntry { // final int base = infoOffset + P_MTIME; final int mtime = NB.decodeInt32(info, base); - if (smudge_s < mtime) - return true; if (smudge_s == mtime) return smudge_ns <= NB.decodeInt32(info, base + 4); return false; @@ -306,21 +305,30 @@ public class DirCacheEntry { * match the file in the working directory. Later git will be forced to * compare the file content to ensure the file matches the working tree. */ - final void smudgeRacilyClean() { - // We don't use the same approach as C Git to smudge the entry, - // as we cannot compare the working tree file to our SHA-1 and - // thus cannot use the "size to 0" trick without accidentally - // thinking a zero length file is clean. - // - // Instead we force the mtime to the largest possible value, so - // it is certainly after the index's own modification time and - // on a future read will cause mightBeRacilyClean to say "yes!". - // It is also unlikely to match with the working tree file. - // - // I'll see you again before Jan 19, 2038, 03:14:07 AM GMT. - // - final int base = infoOffset + P_MTIME; - Arrays.fill(info, base, base + 8, (byte) 127); + public final void smudgeRacilyClean() { + // To mark an entry racily clean we set its length to 0 (like native git + // does). Entries which are not racily clean and have zero length can be + // distinguished from racily clean entries by checking P_OBJECTID + // against the SHA1 of empty content. When length is 0 and P_OBJECTID is + // different from SHA1 of empty content we know the entry is marked + // racily clean + final int base = infoOffset + P_SIZE; + Arrays.fill(info, base, base + 4, (byte) 0); + } + + /** + * Check whether this entry has been smudged or not + *

+ * If a blob has length 0 we know his id see {@link Constants#EMPTY_BLOB_ID}. If an entry + * has length 0 and an ID different from the one for empty blob we know this + * entry was smudged. + * + * @return true if the entry is smudged, false + * otherwise + */ + public final boolean isSmudged() { + final int base = infoOffset + P_OBJECTID; + return (getLength() == 0) && (Constants.EMPTY_BLOB_ID.compareTo(info, base) != 0); } final byte[] idBuffer() { diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Constants.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Constants.java index a5b3d95d76..2269655cf5 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Constants.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Constants.java @@ -527,6 +527,10 @@ public final class Constants { /** name of the file containing the IDs of the parents of a merge commit */ public static final String MERGE_HEAD = "MERGE_HEAD"; + /** objectid for the empty blob */ + public static final ObjectId EMPTY_BLOB_ID = ObjectId + .fromString("e69de29bb2d1d6434b8b29ae775ad8c2e48c5391"); + private Constants() { // Hide the default constructor } -- 2.39.5