summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnna Papitto <annapapitto@google.com>2023-07-14 12:19:27 -0700
committerAnna Papitto <annapapitto@google.com>2023-07-18 15:19:26 -0700
commit2eba4e5b41c299d82e5aa0b974a1f039997ecf6e (patch)
tree7bea9924a36b198a7fd836984ad568965a6d4793
parent8123dcd6993457622fc5df08c58c776286cc427a (diff)
downloadjgit-2eba4e5b41c299d82e5aa0b974a1f039997ecf6e.tar.gz
jgit-2eba4e5b41c299d82e5aa0b974a1f039997ecf6e.zip
PackReverseIndex: open file if present otherwise compute
The existing #read and #computeFromIndex static builder methods require the caller to choose whether to supply an input stream of a reverse index file or a forward index to compute the reverse index from, which is slower. Allow a caller to provide a file path where the pack's reverse index might be and the pack's forward index index and simply get some reverse index instance back. Prefer opening and parsing the file if it is present, to save computation time. Otherwise, fall back onto computing the reverse index from the pack's forward index. Change-Id: I09bdd4b813ad62c86add586417b2ab86e9331aec Signed-off-by: Anna Papitto <annapapitto@google.com>
-rw-r--r--org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/pack-cbdeda40019ae0e6e789088ea0f51f164f489d14.corrupt.revbin0 -> 76 bytes
-rw-r--r--org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/pack-cbdeda40019ae0e6e789088ea0f51f164f489d14.revbin0 -> 76 bytes
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackReverseIndexTest.java44
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackReverseIndexFactory.java33
4 files changed, 77 insertions, 0 deletions
diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/pack-cbdeda40019ae0e6e789088ea0f51f164f489d14.corrupt.rev b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/pack-cbdeda40019ae0e6e789088ea0f51f164f489d14.corrupt.rev
new file mode 100644
index 0000000000..74283a2f9a
--- /dev/null
+++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/pack-cbdeda40019ae0e6e789088ea0f51f164f489d14.corrupt.rev
Binary files differ
diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/pack-cbdeda40019ae0e6e789088ea0f51f164f489d14.rev b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/pack-cbdeda40019ae0e6e789088ea0f51f164f489d14.rev
new file mode 100644
index 0000000000..6ac7d65f67
--- /dev/null
+++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/pack-cbdeda40019ae0e6e789088ea0f51f164f489d14.rev
Binary files differ
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackReverseIndexTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackReverseIndexTest.java
index 84fc58e050..f8fb4c15e7 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackReverseIndexTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackReverseIndexTest.java
@@ -10,13 +10,52 @@
package org.eclipse.jgit.internal.storage.file;
import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertTrue;
import java.io.ByteArrayInputStream;
+import java.io.File;
import java.io.IOException;
+import org.eclipse.jgit.internal.storage.pack.PackExt;
+import org.eclipse.jgit.junit.JGitTestUtil;
import org.junit.Test;
public class PackReverseIndexTest {
+
+ @Test
+ public void open_fallbackToComputed() throws IOException {
+ String noRevFilePrefix = "pack-3280af9c07ee18a87705ef50b0cc4cd20266cf12.";
+ PackReverseIndex computed = PackReverseIndexFactory.openOrCompute(
+ getResourceFileFor(noRevFilePrefix, PackExt.REVERSE_INDEX), 7,
+ () -> PackIndex.open(
+ getResourceFileFor(noRevFilePrefix, PackExt.INDEX)));
+
+ assertTrue(computed instanceof PackReverseIndexComputed);
+ }
+
+ @Test
+ public void open_readGoodFile() throws IOException {
+ String hasRevFilePrefix = "pack-cbdeda40019ae0e6e789088ea0f51f164f489d14.";
+ PackReverseIndex version1 = PackReverseIndexFactory.openOrCompute(
+ getResourceFileFor(hasRevFilePrefix, PackExt.REVERSE_INDEX), 6,
+ () -> PackIndex.open(
+ getResourceFileFor(hasRevFilePrefix, PackExt.INDEX)));
+
+ assertTrue(version1 instanceof PackReverseIndexV1);
+ }
+
+ @Test
+ public void open_readCorruptFile() {
+ String hasRevFilePrefix = "pack-cbdeda40019ae0e6e789088ea0f51f164f489d14.";
+
+ assertThrows(IOException.class,
+ () -> PackReverseIndexFactory.openOrCompute(
+ getResourceFileFor(hasRevFilePrefix + "corrupt.",
+ PackExt.REVERSE_INDEX),
+ 6, () -> PackIndex.open(getResourceFileFor(
+ hasRevFilePrefix, PackExt.INDEX))));
+ }
+
@Test
public void read_badMagic() {
byte[] badMagic = new byte[] { 'R', 'B', 'A', 'D', // magic
@@ -53,4 +92,9 @@ public class PackReverseIndexTest {
assertThrows(IOException.class,
() -> PackReverseIndexFactory.readFromFile(in, 0, () -> null));
}
+
+ private File getResourceFileFor(String packFilePrefix, PackExt ext) {
+ return JGitTestUtil
+ .getTestResourceFile(packFilePrefix + ext.getExtension());
+ }
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackReverseIndexFactory.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackReverseIndexFactory.java
index b16da5ae83..32830c3cf0 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackReverseIndexFactory.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackReverseIndexFactory.java
@@ -14,6 +14,8 @@ import static org.eclipse.jgit.internal.storage.file.PackReverseIndex.MAGIC;
import static org.eclipse.jgit.internal.storage.file.PackReverseIndex.VERSION_1;
import java.io.DataInput;
+import java.io.File;
+import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.security.DigestInputStream;
@@ -23,12 +25,43 @@ import java.util.Arrays;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.util.IO;
+import org.eclipse.jgit.util.io.SilentFileInputStream;
/**
* Factory for creating instances of {@link PackReverseIndex}.
*/
public final class PackReverseIndexFactory {
/**
+ * Create an in-memory pack reverse index by reading it from the given file
+ * if the file exists, or computing it from the given pack index if the file
+ * doesn't exist.
+ *
+ * @param idxFile
+ * the file to read the pack file from, if it exists
+ * @param objectCount
+ * the number of objects in the corresponding pack
+ * @param packIndexSupplier
+ * a function to lazily get the corresponding forward index
+ * @return the reverse index instance
+ * @throws IOException
+ * if reading from the file fails
+ */
+ static PackReverseIndex openOrCompute(File idxFile, long objectCount,
+ PackBitmapIndex.SupplierWithIOException<PackIndex> packIndexSupplier)
+ throws IOException {
+ try (SilentFileInputStream fd = new SilentFileInputStream(idxFile)) {
+ return readFromFile(fd, objectCount, packIndexSupplier);
+ } catch (FileNotFoundException e) {
+ return computeFromIndex(packIndexSupplier.get());
+ } catch (IOException e) {
+ throw new IOException(
+ MessageFormat.format(JGitText.get().unreadablePackIndex,
+ idxFile.getAbsolutePath()),
+ e);
+ }
+ }
+
+ /**
* Compute an in-memory pack reverse index from the in-memory pack forward
* index. This computation uses insertion sort, which has a quadratic
* runtime on average.