Browse Source

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
tags/v3.7.0.201502031740-rc1
Dave Borowitz 9 years ago
parent
commit
d612468c5c

+ 13
- 0
org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/InMemoryRepository.java View File

@@ -14,8 +14,10 @@ import java.util.concurrent.ConcurrentMap;
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 @@ public class InMemoryRepository extends DfsRepository {
@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;

Loading…
Cancel
Save