DfsPackFileMidx: offer local objects as ObjectToPack

The bitmap builder uses ObjectToPack as the initial list of
objects. From this list it calculates their idx/ridx positions and the
type bitmaps. We need the same information from the midx. Note that
this only needs to provide the *local* objects (as "in this midx", not
in its chain).

At the moment, copy the (sha1, midx-offset, type) into ObjectToPack
instances to see bitmaps over midx soonish. This could be a
considerable amount of memory duplicating what we already have in the
midx. We should consider a different way to feed the information to
the bitmap builder for midx.

Change-Id: I3c8b1f2695eec59fd5191a785c1476076a6a6964
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 ba4d5f6..0582737 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
@@ -20,6 +20,7 @@
 import org.eclipse.jgit.errors.StoredObjectRepresentationNotAvailableException;
 import org.eclipse.jgit.internal.storage.file.PackIndex;
 import org.eclipse.jgit.internal.storage.file.PackReverseIndex;
+import org.eclipse.jgit.internal.storage.pack.ObjectToPack;
 import org.eclipse.jgit.internal.storage.pack.PackOutputStream;
 import org.eclipse.jgit.lib.AbbreviatedObjectId;
 import org.eclipse.jgit.lib.AnyObjectId;
@@ -156,6 +157,23 @@ public final PackIndex getPackIndex(DfsReader ctx) {
 		return new MidxPackIndex(this, ctx);
 	}
 
+	/**
+	 * Return all objects in this midx (not recursively) as ObjectToPack
+	 * instances (oid, offset, type). Ordered by sha1.
+	 * <p>
+	 * ObjectToPack is the preferred format for the bitmap builder. This can
+	 * probably be optimized.
+	 *
+	 * @param ctx
+	 *            a reader
+	 * @return list of objects in this midx (NOT in its chain) with offset and
+	 *         type
+	 * @throws IOException
+	 *             an error reading the midx
+	 */
+	abstract List<ObjectToPack> getLocalObjects(DfsReader ctx)
+			throws IOException;
+
 	@Override
 	public abstract PackReverseIndex getReverseIdx(DfsReader ctx)
 			throws IOException;
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 9bc3cb1..bed7a53 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
@@ -196,6 +196,24 @@ public CommitGraph getCommitGraph(DfsReader ctx) throws IOException {
 	}
 
 	@Override
+	public List<ObjectToPack> getLocalObjects(DfsReader ctx)
+			throws IOException {
+		MultiPackIndex midx = midx(ctx);
+		int localObjCount = midx(ctx).getObjectCount();
+		List<ObjectToPack> otps = new ArrayList<>(localObjCount);
+		for (int idxPosition = 0; idxPosition < localObjCount; idxPosition++) {
+			ObjectId oid = midx.getObjectAt(idxPosition);
+			PackOffset packOffset = midx.find(oid);
+			long offset = offsetCalculator.encode(packOffset);
+			int objectType = getObjectType(ctx, offset);
+			ObjectToPack otp = new ObjectToPack(oid, objectType);
+			otp.setOffset(offset);
+			otps.add(otp);
+		}
+		return otps;
+	}
+
+	@Override
 	public PackReverseIndex getReverseIdx(DfsReader ctx) throws IOException {
 		return new MidxReverseIndex(ctx, this,
 				base == null ? 0 : base.getObjectCount(ctx),
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 72d6998..188cb81 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
@@ -23,6 +23,7 @@
 import org.eclipse.jgit.errors.PackMismatchException;
 import org.eclipse.jgit.internal.storage.commitgraph.CommitGraph;
 import org.eclipse.jgit.internal.storage.file.PackBitmapIndex;
+import org.eclipse.jgit.internal.storage.file.PackIndex;
 import org.eclipse.jgit.internal.storage.file.PackReverseIndex;
 import org.eclipse.jgit.internal.storage.midx.MultiPackIndex.PackOffset;
 import org.eclipse.jgit.internal.storage.pack.ObjectToPack;
@@ -296,6 +297,23 @@ long getIndexedObjectSize(DfsReader ctx, int idxPosition) {
 	}
 
 	@Override
+	public List<ObjectToPack> getLocalObjects(DfsReader ctx)
+			throws IOException {
+		PackIndex idx = getPackIndex(ctx);
+		int localObjCount = (int) idx.getObjectCount();
+		List<ObjectToPack> otps = new ArrayList<>(localObjCount);
+		for (int idxPosition = 0; idxPosition < localObjCount; idxPosition++) {
+			ObjectId oid = idx.getObjectId(idxPosition);
+			long offset = idx.getOffset(idxPosition);
+			int objectType = getObjectType(ctx, offset);
+			ObjectToPack otp = new ObjectToPack(oid, objectType);
+			otp.setOffset(offset);
+			otps.add(otp);
+		}
+		return otps;
+	}
+
+	@Override
 	List<DfsObjectToPack> findAllFromPack(DfsReader ctx,
 			Iterable<ObjectToPack> objects, boolean skipFound)
 			throws IOException {