From d612468c5c25057d1137832e6d3bad4432dae82c Mon Sep 17 00:00:00 2001 From: Dave Borowitz Date: Mon, 26 Jan 2015 09:21:05 -0800 Subject: [PATCH] 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 --- .../internal/storage/dfs/InMemoryRepository.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/InMemoryRepository.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/InMemoryRepository.java index 56efdd683..18fedf8b9 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/InMemoryRepository.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/InMemoryRepository.java @@ -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;