aboutsummaryrefslogtreecommitdiffstats
path: root/org.eclipse.jgit/src
diff options
context:
space:
mode:
Diffstat (limited to 'org.eclipse.jgit/src')
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java1
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackReverseIndexWriter.java149
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackReverseIndexWriterV1.java75
3 files changed, 225 insertions, 0 deletions
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
index 28634cbc4d..518e0b7d9b 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
@@ -868,6 +868,7 @@ public class JGitText extends TranslationBundle {
/***/ public String unsupportedMark;
/***/ public String unsupportedOperationNotAddAtEnd;
/***/ public String unsupportedPackIndexVersion;
+ /***/ public String unsupportedPackReverseIndexVersion;
/***/ public String unsupportedPackVersion;
/***/ public String unsupportedReftableVersion;
/***/ public String unsupportedRepositoryDescription;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackReverseIndexWriter.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackReverseIndexWriter.java
new file mode 100644
index 0000000000..4c8417b115
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackReverseIndexWriter.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2023, Google LLC and others
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+package org.eclipse.jgit.internal.storage.file;
+
+import java.io.BufferedOutputStream;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.security.DigestOutputStream;
+import java.text.MessageFormat;
+import java.util.List;
+
+import org.eclipse.jgit.internal.JGitText;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.transport.PackedObjectInfo;
+
+/**
+ * Writes reverse index files conforming to the requested version.
+ * <p>
+ * The reverse index file format is specified at
+ * https://git-scm.com/docs/pack-format#_pack_rev_files_have_the_format.
+ */
+public abstract class PackReverseIndexWriter {
+ /**
+ * Magic bytes that uniquely identify git reverse index files.
+ */
+ protected static byte[] MAGIC = { 'R', 'I', 'D', 'X' };
+
+ /**
+ * The first reverse index file version.
+ */
+ protected static final int VERSION_1 = 1;
+
+ /**
+ * Stream to write contents to while maintaining a checksum.
+ */
+ protected final DigestOutputStream out;
+
+ /**
+ * Stream to write primitive type contents to while maintaining a checksum.
+ */
+ protected final DataOutput dataOutput;
+
+ private static final int DEFAULT_VERSION = VERSION_1;
+
+ /**
+ * Construct the components of a PackReverseIndexWriter that are shared
+ * between subclasses.
+ *
+ * @param dst
+ * the OutputStream that the instance will write contents to
+ */
+ protected PackReverseIndexWriter(OutputStream dst) {
+ out = new DigestOutputStream(
+ dst instanceof BufferedOutputStream ? dst
+ : new BufferedOutputStream(dst),
+ Constants.newMessageDigest());
+ dataOutput = new SimpleDataOutput(out);
+ }
+
+ /**
+ * Create a writer instance for the default file format version.
+ *
+ * @param dst
+ * the OutputStream that contents will be written to
+ * @return the new writer instance
+ */
+ public static PackReverseIndexWriter createWriter(OutputStream dst) {
+ return createWriter(dst, DEFAULT_VERSION);
+ }
+
+ /**
+ * Create a writer instance for the specified file format version.
+ *
+ * @param dst
+ * the OutputStream that contents will be written to
+ * @param version
+ * the reverse index format version to write contents as
+ * @return the new writer instance
+ */
+ public static PackReverseIndexWriter createWriter(OutputStream dst,
+ int version) {
+ if (version == VERSION_1) {
+ return new PackReverseIndexWriterV1(dst);
+ }
+ throw new IllegalArgumentException(MessageFormat.format(
+ JGitText.get().unsupportedPackReverseIndexVersion,
+ Integer.toString(version)));
+ }
+
+ /**
+ * Write the contents of a reverse index file for the given objects.
+ *
+ * @param objectsByIndexPos
+ * the objects whose forward index file positions should be
+ * written, sorted by forward index file position (currently SHA1
+ * ordering)
+ * @param packChecksum
+ * the checksum of the corresponding pack file
+ * @throws IOException
+ * if writing the output fails
+ */
+ public void write(
+ List<? extends PackedObjectInfo> objectsByIndexPos,
+ byte[] packChecksum) throws IOException {
+ writeHeader();
+ writeBody(objectsByIndexPos);
+ writeFooter(packChecksum);
+ out.flush();
+ }
+
+ /**
+ * Write the header of a reverse index file, usually the magic bytes and the
+ * file format version.
+ *
+ * @throws IOException
+ * if writing the output fails
+ */
+ protected abstract void writeHeader() throws IOException;
+
+ /**
+ * Write the body of a reverse index file, usually the forward index
+ * positions of the given objects, sorted by those objects' pack file
+ * offsets.
+ *
+ * @param objectsSortedByIndexPosition
+ * the objects whose forward index file positions should be
+ * written, sorted by forward index file position; not modified
+ * during method
+ * @throws IOException
+ * if writing the output fails
+ */
+ protected abstract void writeBody(
+ List<? extends PackedObjectInfo> objectsSortedByIndexPosition)
+ throws IOException;
+
+ private void writeFooter(byte[] packChecksum) throws IOException {
+ out.write(packChecksum);
+ byte[] selfChecksum = out.getMessageDigest().digest();
+ out.write(selfChecksum);
+ }
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackReverseIndexWriterV1.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackReverseIndexWriterV1.java
new file mode 100644
index 0000000000..7630724d09
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackReverseIndexWriterV1.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2023, Google LLC and others
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * https://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+package org.eclipse.jgit.internal.storage.file;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.List;
+
+import org.eclipse.jgit.transport.PackedObjectInfo;
+import org.eclipse.jgit.util.IntList;
+import org.eclipse.jgit.util.IntList.IntComparator;
+
+/**
+ * Writes reverse index files following the version 1 format.
+ * <p>
+ * The file format is specified at
+ * https://git-scm.com/docs/pack-format#_pack_rev_files_have_the_format.
+ */
+final class PackReverseIndexWriterV1 extends PackReverseIndexWriter {
+ private static final int OID_VERSION_SHA1 = 1;
+
+ private static final int DEFAULT_OID_VERSION = OID_VERSION_SHA1;
+
+ PackReverseIndexWriterV1(final OutputStream dst) {
+ super(dst);
+ }
+
+ @Override
+ protected void writeHeader() throws IOException {
+ out.write(MAGIC);
+ dataOutput.writeInt(VERSION_1);
+ dataOutput.writeInt(DEFAULT_OID_VERSION);
+ }
+
+ @Override
+ protected void writeBody(List<? extends PackedObjectInfo> objectsByIndexPos)
+ throws IOException {
+ IntList positionsByOffset = IntList.filledWithRange(0,
+ objectsByIndexPos.size());
+ positionsByOffset
+ .sort(new IndexPositionsByOffsetComparator(objectsByIndexPos));
+
+ for (int i = 0; i < positionsByOffset.size(); i++) {
+ int indexPosition = positionsByOffset.get(i);
+ dataOutput.writeInt(indexPosition);
+ }
+ }
+
+ private static class IndexPositionsByOffsetComparator
+ implements IntComparator {
+ private List<? extends PackedObjectInfo> objectsByIndexPos;
+
+ private IndexPositionsByOffsetComparator(
+ List<? extends PackedObjectInfo> objectsByIndexPos) {
+ this.objectsByIndexPos = objectsByIndexPos;
+ }
+
+ @Override
+ public int compare(int firstIndexPosition, int secondIndexPosition) {
+ return Long.compare(getOffset(firstIndexPosition),
+ getOffset(secondIndexPosition));
+ }
+
+ private long getOffset(int indexPosition) {
+ return objectsByIndexPos.get(indexPosition).getOffset();
+ }
+ }
+}