InMemoryRepository: Ensure new ref targets exist in the repo

ObjectInserter recently learned to read back inserted objects before
they have been flushed. It is in general unsafe to create refs to such
objects, but it is now much more possible to do so, by passing "new
RevWalk(inserter.newReader())" into RefUpdate#execute(RevWalk).

We can't change the RefUpdate interface to remove execute(RevWalk);
nor would we necessarily want to, for performance reasons. And in any
case, RefUpdate#safeParse explicitly ignores MissingObjectExceptions.
But we can enforce object existence in InMemoryRepository, which will
allow callers using this class in their tests to ensure they are using
the RefDatabase correctly.

Change-Id: I5c696ba23bcd2a536a0512fa7f5b6130961905c5
This commit is contained in:
Dave Borowitz 2015-01-26 09:21:05 -08:00
parent e314e42d41
commit d612468c5c
1 changed files with 13 additions and 0 deletions

View File

@ -14,8 +14,10 @@
import java.util.concurrent.atomic.AtomicInteger;
import org.eclipse.jgit.internal.storage.pack.PackExt;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Ref.Storage;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.util.RefList;
/**
@ -241,6 +243,17 @@ protected RefCache scanAllRefs() throws IOException {
@Override
protected boolean compareAndPut(Ref oldRef, Ref newRef)
throws IOException {
ObjectId id = newRef.getObjectId();
if (id != null) {
RevWalk rw = new RevWalk(getRepository());
try {
// Validate that the target exists in a new RevWalk, as the RevWalk
// from the RefUpdate might be reading back unflushed objects.
rw.parseAny(id);
} finally {
rw.release();
}
}
String name = newRef.getName();
if (oldRef == null || oldRef.getStorage() == Storage.NEW)
return refs.putIfAbsent(name, newRef) == null;