PackBitmapIndexWriterV1.java

  1. /*
  2.  * Copyright (C) 2012, Google Inc. and others
  3.  *
  4.  * This program and the accompanying materials are made available under the
  5.  * terms of the Eclipse Distribution License v. 1.0 which is available at
  6.  * https://www.eclipse.org/org/documents/edl-v10.php.
  7.  *
  8.  * SPDX-License-Identifier: BSD-3-Clause
  9.  */

  10. package org.eclipse.jgit.internal.storage.file;

  11. import java.io.BufferedOutputStream;
  12. import java.io.DataOutput;
  13. import java.io.IOException;
  14. import java.io.OutputStream;
  15. import java.security.DigestOutputStream;
  16. import java.text.MessageFormat;

  17. import org.eclipse.jgit.internal.JGitText;
  18. import org.eclipse.jgit.internal.storage.file.PackBitmapIndexBuilder.StoredEntry;
  19. import org.eclipse.jgit.lib.Constants;

  20. import com.googlecode.javaewah.EWAHCompressedBitmap;

  21. /**
  22.  * Creates the version 1 pack bitmap index files.
  23.  *
  24.  * @see PackBitmapIndexV1
  25.  */
  26. public class PackBitmapIndexWriterV1 {
  27.     private final DigestOutputStream out;
  28.     private final DataOutput dataOutput;

  29.     /**
  30.      * Creates the version 1 pack bitmap index files.
  31.      *
  32.      * @param dst
  33.      *            the output stream to which the index will be written.
  34.      */
  35.     public PackBitmapIndexWriterV1(final OutputStream dst) {
  36.         out = new DigestOutputStream(dst instanceof BufferedOutputStream ? dst
  37.                 : new BufferedOutputStream(dst),
  38.                 Constants.newMessageDigest());
  39.         dataOutput = new SimpleDataOutput(out);
  40.     }

  41.     /**
  42.      * Write all object entries to the index stream.
  43.      * <p>
  44.      * After writing the stream passed to the factory is flushed but remains
  45.      * open. Callers are always responsible for closing the output stream.
  46.      *
  47.      * @param bitmaps
  48.      *            the index data for the bitmaps
  49.      * @param packDataChecksum
  50.      *            checksum signature of the entire pack data content. This is
  51.      *            traditionally the last 20 bytes of the pack file's own stream.
  52.      * @throws java.io.IOException
  53.      *             an error occurred while writing to the output stream, or this
  54.      *             index format cannot store the object data supplied.
  55.      */
  56.     public void write(PackBitmapIndexBuilder bitmaps, byte[] packDataChecksum)
  57.             throws IOException {
  58.         if (bitmaps == null || packDataChecksum.length != 20)
  59.             throw new IllegalStateException();

  60.         writeHeader(bitmaps.getOptions(), bitmaps.getBitmapCount(),
  61.                 packDataChecksum);
  62.         writeBody(bitmaps);
  63.         writeFooter();

  64.         out.flush();
  65.     }

  66.     private void writeHeader(
  67.             int options, int bitmapCount, byte[] packDataChecksum)
  68.             throws IOException {
  69.         out.write(PackBitmapIndexV1.MAGIC);
  70.         dataOutput.writeShort(1);
  71.         dataOutput.writeShort(options);
  72.         dataOutput.writeInt(bitmapCount);
  73.         out.write(packDataChecksum);
  74.     }

  75.     private void writeBody(PackBitmapIndexBuilder bitmaps) throws IOException {
  76.         writeBitmap(bitmaps.getCommits());
  77.         writeBitmap(bitmaps.getTrees());
  78.         writeBitmap(bitmaps.getBlobs());
  79.         writeBitmap(bitmaps.getTags());
  80.         writeBitmaps(bitmaps);
  81.     }

  82.     private void writeBitmap(EWAHCompressedBitmap bitmap) throws IOException {
  83.         bitmap.serialize(dataOutput);
  84.     }

  85.     private void writeBitmaps(PackBitmapIndexBuilder bitmaps)
  86.             throws IOException {
  87.         int bitmapCount = 0;
  88.         for (StoredEntry entry : bitmaps.getCompressedBitmaps()) {
  89.             writeBitmapEntry(entry);
  90.             bitmapCount++;
  91.         }

  92.         int expectedBitmapCount = bitmaps.getBitmapCount();
  93.         if (expectedBitmapCount != bitmapCount)
  94.             throw new IOException(MessageFormat.format(
  95.                     JGitText.get().expectedGot,
  96.                     String.valueOf(expectedBitmapCount),
  97.                     String.valueOf(bitmapCount)));
  98.     }

  99.     private void writeBitmapEntry(StoredEntry entry) throws IOException {
  100.         // Write object, XOR offset, and bitmap
  101.         dataOutput.writeInt((int) entry.getObjectId());
  102.         out.write(entry.getXorOffset());
  103.         out.write(entry.getFlags());
  104.         writeBitmap(entry.getBitmap());
  105.     }

  106.     private void writeFooter() throws IOException {
  107.         out.on(false);
  108.         out.write(out.getMessageDigest().digest());
  109.     }
  110. }