Expose the ObjectInserter that created an ObjectReader
We've found in Gerrit Code Review that it is common to pass around both an ObjectReader (or more commonly a RevWalk wrapping one) and an ObjectInserter. These code paths often assume that the ObjectReader can read back any objects created by the ObjectInserter without flushing. However, we previously had no way to enforce that constraint programmatically, leading to hard-to-spot problems. Provide a solution by exposing the ObjectInserter that created an ObjectReader, when known. Callers can either continue passing both objects and check: reader.getCreatedFromInserter() == inserter or they can just pass around ObjectReader and extract the inserter when it's needed (checking that it's not null at usage time). Change-Id: Ibbf5d1968b506f6b47030ab1b046ffccb47352ea
This commit is contained in:
parent
8a26d0577f
commit
adff322a69
|
@ -45,6 +45,7 @@
|
|||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -97,6 +98,7 @@ public void testReadFromInserterSmallObjects() throws IOException {
|
|||
assertEquals(0, db.getObjectDatabase().listPacks().size());
|
||||
|
||||
ObjectReader reader = ins.newReader();
|
||||
assertSame(ins, reader.getCreatedFromInserter());
|
||||
assertEquals("foo", readString(reader.open(id1)));
|
||||
assertEquals("bar", readString(reader.open(id2)));
|
||||
assertEquals(0, db.getObjectDatabase().listPacks().size());
|
||||
|
@ -118,6 +120,7 @@ public void testReadFromInserterLargerObjects() throws IOException {
|
|||
assertEquals(0, db.getObjectDatabase().listPacks().size());
|
||||
|
||||
ObjectReader reader = ins.newReader();
|
||||
assertSame(ins, reader.getCreatedFromInserter());
|
||||
assertTrue(Arrays.equals(data, readStream(reader.open(id1))));
|
||||
assertEquals(0, db.getObjectDatabase().listPacks().size());
|
||||
ins.flush();
|
||||
|
@ -136,6 +139,7 @@ public void testReadFromFallback() throws IOException {
|
|||
assertEquals(1, db.getObjectDatabase().listPacks().size());
|
||||
|
||||
ObjectReader reader = ins.newReader();
|
||||
assertSame(ins, reader.getCreatedFromInserter());
|
||||
assertEquals("foo", readString(reader.open(id1)));
|
||||
assertEquals("bar", readString(reader.open(id2)));
|
||||
assertEquals(1, db.getObjectDatabase().listPacks().size());
|
||||
|
@ -154,6 +158,7 @@ public void testReaderResolve() throws IOException {
|
|||
assertFalse(abbr1.equals(abbr2));
|
||||
|
||||
ObjectReader reader = ins.newReader();
|
||||
assertSame(ins, reader.getCreatedFromInserter());
|
||||
Collection<ObjectId> objs;
|
||||
objs = reader.resolve(AbbreviatedObjectId.fromString(abbr1));
|
||||
assertEquals(1, objs.size());
|
||||
|
|
|
@ -600,6 +600,11 @@ public Set<ObjectId> getShallowCommits() throws IOException {
|
|||
return ctx.getShallowCommits();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectInserter getCreatedFromInserter() {
|
||||
return DfsInserter.this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
ctx.close();
|
||||
|
|
|
@ -136,7 +136,7 @@ public PackParser newPackParser(InputStream in) throws IOException {
|
|||
|
||||
@Override
|
||||
public ObjectReader newReader() {
|
||||
return new WindowCursor(db);
|
||||
return new WindowCursor(db, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
import java.util.zip.DataFormatException;
|
||||
import java.util.zip.Inflater;
|
||||
|
||||
import org.eclipse.jgit.annotations.Nullable;
|
||||
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
|
||||
import org.eclipse.jgit.errors.MissingObjectException;
|
||||
import org.eclipse.jgit.errors.StoredObjectRepresentationNotAvailableException;
|
||||
|
@ -69,6 +70,7 @@
|
|||
import org.eclipse.jgit.lib.Constants;
|
||||
import org.eclipse.jgit.lib.InflaterCache;
|
||||
import org.eclipse.jgit.lib.ObjectId;
|
||||
import org.eclipse.jgit.lib.ObjectInserter;
|
||||
import org.eclipse.jgit.lib.ObjectLoader;
|
||||
import org.eclipse.jgit.lib.ObjectReader;
|
||||
import org.eclipse.jgit.lib.ProgressMonitor;
|
||||
|
@ -84,10 +86,20 @@ final class WindowCursor extends ObjectReader implements ObjectReuseAsIs {
|
|||
|
||||
private DeltaBaseCache baseCache;
|
||||
|
||||
@Nullable
|
||||
private final ObjectInserter createdFromInserter;
|
||||
|
||||
final FileObjectDatabase db;
|
||||
|
||||
WindowCursor(FileObjectDatabase db) {
|
||||
this.db = db;
|
||||
this.createdFromInserter = null;
|
||||
}
|
||||
|
||||
WindowCursor(FileObjectDatabase db,
|
||||
@Nullable ObjectDirectoryInserter createdFromInserter) {
|
||||
this.db = db;
|
||||
this.createdFromInserter = createdFromInserter;
|
||||
}
|
||||
|
||||
DeltaBaseCache getDeltaBaseCache() {
|
||||
|
@ -329,6 +341,12 @@ int getStreamFileThreshold() {
|
|||
return WindowCache.getStreamFileThreshold();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public ObjectInserter getCreatedFromInserter() {
|
||||
return createdFromInserter;
|
||||
}
|
||||
|
||||
/** Release the current window cursor. */
|
||||
@Override
|
||||
public void close() {
|
||||
|
|
|
@ -143,7 +143,18 @@ public PackParser newPackParser(InputStream in) throws IOException {
|
|||
}
|
||||
|
||||
public ObjectReader newReader() {
|
||||
return delegate().newReader();
|
||||
final ObjectReader dr = delegate().newReader();
|
||||
return new ObjectReader.Filter() {
|
||||
@Override
|
||||
protected ObjectReader delegate() {
|
||||
return dr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectInserter getCreatedFromInserter() {
|
||||
return ObjectInserter.Filter.this;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public void flush() throws IOException {
|
||||
|
@ -398,6 +409,9 @@ public abstract ObjectId insert(int objectType, long length, InputStream in)
|
|||
* visible to the repository. The returned reader should only be used from
|
||||
* the same thread as the inserter. Objects written by this inserter may not
|
||||
* be visible to {@code this.newReader().newReader()}.
|
||||
* <p>
|
||||
* The returned reader should return this inserter instance from {@link
|
||||
* ObjectReader#getCreatedFromInserter()}.
|
||||
*
|
||||
* @since 3.5
|
||||
* @return reader for any object, including an object recently inserted by
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.jgit.annotations.Nullable;
|
||||
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
|
||||
import org.eclipse.jgit.errors.MissingObjectException;
|
||||
import org.eclipse.jgit.internal.storage.pack.ObjectReuseAsIs;
|
||||
|
@ -421,6 +422,17 @@ public BitmapIndex getBitmapIndex() throws IOException {
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the {@link ObjectInserter} from which this reader was created
|
||||
* using {@code inserter.newReader()}, or null if this reader was not
|
||||
* created from an inserter.
|
||||
* @since 4.4
|
||||
*/
|
||||
@Nullable
|
||||
public ObjectInserter getCreatedFromInserter() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Release any resources used by this reader.
|
||||
* <p>
|
||||
|
@ -524,6 +536,12 @@ public BitmapIndex getBitmapIndex() throws IOException {
|
|||
return delegate().getBitmapIndex();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public ObjectInserter getCreatedFromInserter() {
|
||||
return delegate().getCreatedFromInserter();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
delegate().close();
|
||||
|
|
Loading…
Reference in New Issue