Merge "DfsPackFileMidx: Add method to translate midx position to objectId"
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsPackFileMidxNPacksTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsPackFileMidxNPacksTest.java
index 758ac1f..ea333e6 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsPackFileMidxNPacksTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsPackFileMidxNPacksTest.java
@@ -11,6 +11,7 @@
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.eclipse.jgit.internal.storage.dfs.DfsObjDatabase.PackSource.GC;
+import static org.eclipse.jgit.internal.storage.pack.PackExt.MULTI_PACK_INDEX;
import static org.eclipse.jgit.internal.storage.pack.PackExt.PACK;
import static org.eclipse.jgit.lib.Constants.OBJ_BLOB;
import static org.eclipse.jgit.lib.Constants.OBJ_COMMIT;
@@ -120,6 +121,49 @@ public void midx_findIdxPosition_withBase() throws IOException {
}
@Test
+ public void midx_getObjectAt() throws IOException {
+ ObjectId o1 = writePackWithBlob("something".getBytes(UTF_8));
+ ObjectId o2 = writePackWithBlob("something else".getBytes(UTF_8));
+ ObjectId o3 = writePackWithBlob("and more".getBytes(UTF_8));
+ DfsPackFileMidx midx = writeMultipackIndex();
+
+ try (DfsReader ctx = db.getObjectDatabase().newReader()) {
+ assertEquals(o1, midx.getObjectAt(ctx, 2));
+ assertEquals(o2, midx.getObjectAt(ctx, 0));
+ assertEquals(o3, midx.getObjectAt(ctx, 1));
+ }
+ }
+
+ @Test
+ public void midx_getObjectAt_withBase() throws IOException {
+ ObjectId o1 = writePackWithBlob("o1".getBytes(UTF_8));
+ ObjectId o2 = writePackWithBlob("o2".getBytes(UTF_8));
+ ObjectId o3 = writePackWithBlob("o3".getBytes(UTF_8));
+ ObjectId o4 = writePackWithBlob("o4".getBytes(UTF_8));
+ ObjectId o5 = writePackWithBlob("o5".getBytes(UTF_8));
+ ObjectId o6 = writePackWithBlob("o6".getBytes(UTF_8));
+ DfsPackFile[] packs = db.getObjectDatabase().getPacks();
+
+ // Packs are in reverse insertion order
+ DfsPackFileMidx midxBase = writeMultipackIndex(
+ Arrays.copyOfRange(packs, 4, 6), null);
+ DfsPackFileMidx midxMid = writeMultipackIndex(
+ Arrays.copyOfRange(packs, 2, 4), midxBase);
+ DfsPackFileMidx midxTip = writeMultipackIndex(
+ Arrays.copyOfRange(packs, 0, 2), midxMid);
+
+ try (DfsReader ctx = db.getObjectDatabase().newReader()) {
+ assertEquals(o1, midxTip.getObjectAt(ctx, 0));
+ assertEquals(o2, midxTip.getObjectAt(ctx, 1));
+ assertEquals(o3, midxTip.getObjectAt(ctx, 2));
+ assertEquals(o4, midxTip.getObjectAt(ctx, 3));
+ // In sha1 order
+ assertEquals(o5, midxTip.getObjectAt(ctx, 5));
+ assertEquals(o6, midxTip.getObjectAt(ctx, 4));
+ }
+ }
+
+ @Test
public void midx_hasObject() throws IOException {
ObjectId o1 = writePackWithRandomBlob(100);
ObjectId o2 = writePackWithRandomBlob(200);
@@ -1184,7 +1228,9 @@ private DfsPackFileMidx writeMultipackIndex(DfsPackFile[] packs,
.write(NullProgressMonitor.INSTANCE, out, forMidx);
desc.setCoveredPacks(midxStats.packNames().stream()
.map(descByName::get).toList());
+ desc.setObjectCount(midxStats.objectCount());
desc.addFileExt(PackExt.MULTI_PACK_INDEX);
+ desc.setFileSize(MULTI_PACK_INDEX, midxStats.bytesWritten());
}
db.getObjectDatabase().commitPack(List.of(desc), null);
return DfsPackFileMidx.create(DfsBlockCache.getInstance(), desc,
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsPackFileMidxSingleTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsPackFileMidxSingleTest.java
index 9f698db..01271e5 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsPackFileMidxSingleTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/dfs/DfsPackFileMidxSingleTest.java
@@ -117,6 +117,48 @@ public void findIdxPosition_withBase() throws IOException {
}
@Test
+ public void getObjectAt() throws IOException {
+ ObjectId[] oids = writePackWithBlobs("something", "something else",
+ "and more");
+ // oids = [a4..., 33..., 64...]
+ DfsPackFileMidx midx = writeSinglePackMidx();
+
+ try (DfsReader ctx = db.getObjectDatabase().newReader()) {
+ assertEquals(oids[0], midx.getObjectAt(ctx, 2));
+ assertEquals(oids[1], midx.getObjectAt(ctx, 0));
+ assertEquals(oids[2], midx.getObjectAt(ctx, 1));
+ }
+ }
+
+ @Test
+ public void getObjectAt_withBase() throws IOException {
+ ObjectId o1 = writePackWithBlob("o1".getBytes(UTF_8));
+ ObjectId o2 = writePackWithBlob("o2".getBytes(UTF_8));
+ ObjectId o3 = writePackWithBlob("o3".getBytes(UTF_8));
+ ObjectId o4 = writePackWithBlob("o4".getBytes(UTF_8));
+ ObjectId o5 = writePackWithBlob("o5".getBytes(UTF_8));
+ ObjectId o6 = writePackWithBlob("o6".getBytes(UTF_8));
+ DfsPackFile[] packs = db.getObjectDatabase().getPacks();
+
+ // Packs are in reverse insertion order
+ DfsPackFileMidx midxBase = writeMultipackIndex(
+ Arrays.copyOfRange(packs, 3, 6), null);
+ DfsPackFileMidx midxMid = writeSinglePackMidx(packs[2], midxBase);
+ DfsPackFileMidx midxTip = writeMultipackIndex(
+ Arrays.copyOfRange(packs, 0, 2), midxMid);
+
+ try (DfsReader ctx = db.getObjectDatabase().newReader()) {
+ assertEquals(o1, midxTip.getObjectAt(ctx, 0));
+ assertEquals(o3, midxTip.getObjectAt(ctx, 1));
+ assertEquals(o2, midxTip.getObjectAt(ctx, 2));
+ assertEquals(o4, midxTip.getObjectAt(ctx, 3));
+ // In sha1 order
+ assertEquals(o6, midxTip.getObjectAt(ctx, 4));
+ assertEquals(o5, midxTip.getObjectAt(ctx, 5));
+ }
+ }
+
+ @Test
public void hasObject() throws IOException {
ObjectId[] oids = writePackWithBlobs("aaaa", "bbbb", "cccc");
DfsPackFile midx = writeSinglePackMidx();
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackFileMidx.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackFileMidx.java
index 0f96593..5f08444 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackFileMidx.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackFileMidx.java
@@ -19,6 +19,7 @@
import org.eclipse.jgit.internal.storage.file.PackIndex;
import org.eclipse.jgit.internal.storage.file.PackReverseIndex;
import org.eclipse.jgit.internal.storage.pack.PackOutputStream;
+import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectLoader;
/**
@@ -104,6 +105,24 @@ public List<DfsPackFile> getAllCoveredPacks() {
}
/**
+ * Get the objectId at the corresponding position in the midx chain up to
+ * this point
+ * <p>
+ * In a chain with midx-tip (100 objects) and midx-base (50 objects),
+ * positions 0-49 belong to the base midx and 50-149 to the tip midx.
+ *
+ * @param ctx
+ * a reader for the midx data
+ * @param nthPosition
+ * position in midx chain
+ * @return the objectId
+ * @throws IOException
+ * a problem reading midx bytes
+ */
+ abstract ObjectId getObjectAt(DfsReader ctx, long nthPosition)
+ throws IOException;
+
+ /**
* Count of objects in this <b>pack</b> (i.e. including, recursively, its
* base)
*
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackFileMidxNPacks.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackFileMidxNPacks.java
index 6ff078a..6d9ec1a 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackFileMidxNPacks.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackFileMidxNPacks.java
@@ -140,7 +140,6 @@ public ObjectIdSet asObjectIdSet(DfsReader ctx) throws IOException {
return multiPackIndex::hasObject;
}
-
@Override
public PackBitmapIndex getBitmapIndex(DfsReader ctx) throws IOException {
// TODO(ifrade): at some point we will have bitmaps over the multipack
@@ -227,6 +226,17 @@ public DfsPackFileMidx getMultipackIndexBase() {
}
@Override
+ ObjectId getObjectAt(DfsReader ctx, long nthPosition) throws IOException {
+ int baseObjectCount = base == null ? 0 : base.getObjectCount(ctx);
+ if (nthPosition >= baseObjectCount) {
+ long localPosition = nthPosition - baseObjectCount;
+ return midx(ctx).getObjectAt((int) localPosition);
+ }
+
+ return base.getObjectAt(ctx, nthPosition);
+ }
+
+ @Override
public int findIdxPosition(DfsReader ctx, AnyObjectId id)
throws IOException {
int p = midx(ctx).findPosition(id);
@@ -363,7 +373,6 @@ List<DfsObjectToPack> findAllFromPack(DfsReader ctx,
return tmp;
}
-
// Visible for testing
static class VOffsetCalculatorNPacks implements VOffsetCalculator {
private final DfsPackFile[] packs;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackFileMidxSingle.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackFileMidxSingle.java
index 60fd7d5..54dce89 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackFileMidxSingle.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/dfs/DfsPackFileMidxSingle.java
@@ -151,6 +151,17 @@ public int findIdxPosition(DfsReader ctx, AnyObjectId id)
}
@Override
+ ObjectId getObjectAt(DfsReader ctx, long nthPosition) throws IOException {
+ int baseObjects = base == null ? 0 : base.getObjectCount(ctx);
+ if (nthPosition >= baseObjects) {
+ long localPosition = nthPosition - baseObjects;
+ return pack.getPackIndex(ctx).getObjectId(localPosition);
+ }
+
+ return base.getObjectAt(ctx, nthPosition);
+ }
+
+ @Override
public boolean hasObject(DfsReader ctx, AnyObjectId id) throws IOException {
if (pack.hasObject(ctx, id)) {
return true;