diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackWriterTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackWriterTest.java index 3fe8f52fb..2a403c769 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackWriterTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackWriterTest.java @@ -504,6 +504,43 @@ public void testWriteIndex() throws Exception { } } + @Test + public void testWriteObjectSizeIndex_noDeltas() throws Exception { + config.setMinBytesForObjSizeIndex(0); + HashSet interesting = new HashSet<>(); + interesting.add(ObjectId + .fromString("82c6b885ff600be425b4ea96dee75dca255b69e7")); + + NullProgressMonitor m1 = NullProgressMonitor.INSTANCE; + writer = new PackWriter(config, db.newObjectReader()); + writer.setUseBitmaps(false); + writer.setThin(false); + writer.setIgnoreMissingUninteresting(false); + writer.preparePack(m1, interesting, NONE); + writer.writePack(m1, m1, os); + + PackIndex idx; + try (ByteArrayOutputStream is = new ByteArrayOutputStream()) { + writer.writeIndex(is); + idx = PackIndex.read(new ByteArrayInputStream(is.toByteArray())); + } + + PackObjectSizeIndex objSizeIdx; + try (ByteArrayOutputStream objSizeStream = new ByteArrayOutputStream()) { + writer.writeObjectSizeIndex(objSizeStream); + objSizeIdx = PackObjectSizeIndexLoader.load( + new ByteArrayInputStream(objSizeStream.toByteArray())); + } + writer.close(); + + ObjectId knownBlob1 = ObjectId + .fromString("5b6e7c66c276e7610d4a73c70ec1a1f7c1003259"); + ObjectId knownBlob2 = ObjectId + .fromString("6ff87c4664981e4397625791c8ea3bbb5f2279a3"); + assertEquals(18009, objSizeIdx.getSize(idx.findPosition(knownBlob1))); + assertEquals(18787, objSizeIdx.getSize(idx.findPosition(knownBlob2))); + } + @Test public void testExclude() throws Exception { // TestRepository closes repo diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriter.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriter.java index d42d348a1..bad572459 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriter.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriter.java @@ -61,6 +61,7 @@ import org.eclipse.jgit.internal.storage.file.PackBitmapIndexBuilder; import org.eclipse.jgit.internal.storage.file.PackBitmapIndexWriterV1; import org.eclipse.jgit.internal.storage.file.PackIndexWriter; +import org.eclipse.jgit.internal.storage.file.PackObjectSizeIndexWriter; import org.eclipse.jgit.lib.AnyObjectId; import org.eclipse.jgit.lib.AsyncObjectSizeQueue; import org.eclipse.jgit.lib.BatchingProgressMonitor; @@ -1091,6 +1092,50 @@ public void writeIndex(OutputStream indexStream) throws IOException { stats.timeWriting += System.currentTimeMillis() - writeStart; } + /** + * Create an object size index file for the contents of the pack file just + * written. + *

+ * Called after + * {@link #writePack(ProgressMonitor, ProgressMonitor, OutputStream)} that + * populates the list of objects to pack and before + * {@link #writeBitmapIndex(OutputStream)} that destroys it. + *

+ * Writing this index is only required for local pack storage. Packs sent on + * the network do not need to create an object size index. + * + * @param objIdxStream + * output for the object size index data. Caller is responsible + * for closing this stream. + * @throws IOException + * errors while writing + */ + public void writeObjectSizeIndex(OutputStream objIdxStream) + throws IOException { + if (config.getMinBytesForObjSizeIndex() < 0) { + return; + } + + long writeStart = System.currentTimeMillis(); + // We only need to populate the size of blobs + AsyncObjectSizeQueue sizeQueue = reader + .getObjectSize(objectsLists[OBJ_BLOB], /* reportMissing= */false); + try { + while (sizeQueue.next()) { + ObjectToPack otp = sizeQueue.getCurrent(); + long sz = sizeQueue.getSize(); + otp.setFullSize(sz); + } + } finally { + sizeQueue.release(); + } + PackObjectSizeIndexWriter iw = PackObjectSizeIndexWriter.createWriter( + objIdxStream, config.getMinBytesForObjSizeIndex()); + // All indexed objects because their positions must match primary index order + iw.write(sortByName()); + stats.timeWriting += System.currentTimeMillis() - writeStart; + } + /** * Create a bitmap index file to match the pack file just written. *