Fix TreeWalk bug comparing DirCache and WorkingTree with ANY_DIFF

When comparing a DirCache and a WorkingTree using ANY_DIFF we
sometimes didn't recursive into a subtree of both sides gave us
zeroId() back for the identity of a subtree.  This happens when the
DirCache doesn't have a valid cache tree for the subtree, as then
it uses zeroId() for the ObjectId of the subtree, which then appears
to be equal to the zeroId() of the WorkingTreeIterator's subtree.

We work around this by adding a hasId() method that returns true
only if this iterator has a valid ObjectId.  The idEquals method
on TreeWalk than only performs a compare between two iterators if
both iterators have a valid id.

Change-Id: I695f7fafbeb452e8c0703a05c02921fae0822d3f
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
This commit is contained in:
Shawn O. Pearce 2010-09-01 12:31:37 -07:00
parent 244b1580b5
commit 6f00a3e651
6 changed files with 32 additions and 6 deletions

View File

@ -45,7 +45,6 @@
package org.eclipse.jgit.dircache;
import java.io.IOException;
import java.util.Arrays;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.lib.Constants;
@ -141,10 +140,17 @@ public EmptyTreeIterator createEmptyTreeIterator() {
return new EmptyTreeIterator(this, n, pathLen + 1);
}
@Override
public boolean hasId() {
if (currentSubtree != null)
return currentSubtree.isValid();
return currentEntry != null;
}
@Override
public byte[] idBuffer() {
if (currentSubtree != null)
return subtreeId;
return currentSubtree.isValid() ? subtreeId : zeroid;
if (currentEntry != null)
return currentEntry.idBuffer();
return zeroid;
@ -218,8 +224,6 @@ private void parseEntry() {
if (s.isValid())
s.getObjectId().copyRawTo(subtreeId, 0);
else
Arrays.fill(subtreeId, (byte) 0);
mode = FileMode.TREE.getBits();
path = cep;
pathLen = pathOffset + s.nameLength();

View File

@ -369,6 +369,9 @@ public boolean idEqual(final AbstractTreeIterator otherIterator) {
otherIterator.idBuffer(), otherIterator.idOffset());
}
/** @return true if the entry has a valid ObjectId. */
public abstract boolean hasId();
/**
* Get the object id of the current entry.
*

View File

@ -233,6 +233,11 @@ public CanonicalTreeParser createSubtreeIterator(final ObjectReader reader)
return createSubtreeIterator(reader, new MutableObjectId());
}
@Override
public boolean hasId() {
return true;
}
@Override
public byte[] idBuffer() {
return raw;

View File

@ -92,6 +92,11 @@ public AbstractTreeIterator createSubtreeIterator(final ObjectReader reader)
return new EmptyTreeIterator(this);
}
@Override
public boolean hasId() {
return false;
}
@Override
public ObjectId getEntryObjectId() {
return ObjectId.zeroId();

View File

@ -683,8 +683,6 @@ public boolean idEqual(final int nthA, final int nthB) {
final AbstractTreeIterator ch = currentHead;
final AbstractTreeIterator a = trees[nthA];
final AbstractTreeIterator b = trees[nthB];
if (a.matches == ch && b.matches == ch)
return a.idEqual(b);
if (a.matches != ch && b.matches != ch) {
// If neither tree matches the current path node then neither
// tree has this entry. In such case the ObjectId is zero(),
@ -692,6 +690,10 @@ public boolean idEqual(final int nthA, final int nthB) {
//
return true;
}
if (!a.hasId() || !b.hasId())
return false;
if (a.matches == ch && b.matches == ch)
return a.idEqual(b);
return false;
}

View File

@ -194,6 +194,13 @@ protected void initRootIterator(Repository repo) {
ignoreNode = new RootIgnoreNode(entry, repo);
}
@Override
public boolean hasId() {
if (contentIdFromPtr == ptr)
return true;
return (mode & FileMode.TYPE_MASK) == FileMode.TYPE_FILE;
}
@Override
public byte[] idBuffer() {
if (contentIdFromPtr == ptr)