]> source.dussan.org Git - jgit.git/commitdiff
Move PackWriter over to storage.pack.PackWriter 74/974/1
authorShawn O. Pearce <spearce@spearce.org>
Sun, 27 Jun 2010 01:48:39 +0000 (18:48 -0700)
committerShawn O. Pearce <spearce@spearce.org>
Sun, 27 Jun 2010 01:51:12 +0000 (18:51 -0700)
Similar to what we did with the file code, move the pack writer
into its own package so the related classes and their package
private methods are hidden from the rest of the library.

Change-Id: Ic1b5c7c8c8d266e90c910d8d68dfc8e93586854f
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
32 files changed:
org.eclipse.jgit.junit/META-INF/MANIFEST.MF
org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/TestRepository.java
org.eclipse.jgit.test/META-INF/MANIFEST.MF
org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/ConcurrentRepackTest.java
org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/PackWriterTest.java
org.eclipse.jgit/META-INF/MANIFEST.MF
org.eclipse.jgit/src/org/eclipse/jgit/errors/StoredObjectRepresentationNotAvailableException.java
org.eclipse.jgit/src/org/eclipse/jgit/lib/BinaryDelta.java [deleted file]
org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectReader.java
org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectReuseAsIs.java [deleted file]
org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectToPack.java [deleted file]
org.eclipse.jgit/src/org/eclipse/jgit/lib/PackOutputStream.java [deleted file]
org.eclipse.jgit/src/org/eclipse/jgit/lib/PackWriter.java [deleted file]
org.eclipse.jgit/src/org/eclipse/jgit/lib/StoredObjectRepresentation.java [deleted file]
org.eclipse.jgit/src/org/eclipse/jgit/storage/file/CachedObjectDirectory.java
org.eclipse.jgit/src/org/eclipse/jgit/storage/file/FileObjectDatabase.java
org.eclipse.jgit/src/org/eclipse/jgit/storage/file/LocalObjectRepresentation.java
org.eclipse.jgit/src/org/eclipse/jgit/storage/file/LocalObjectToPack.java
org.eclipse.jgit/src/org/eclipse/jgit/storage/file/ObjectDirectory.java
org.eclipse.jgit/src/org/eclipse/jgit/storage/file/PackFile.java
org.eclipse.jgit/src/org/eclipse/jgit/storage/file/WindowCursor.java
org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/BinaryDelta.java [new file with mode: 0644]
org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/ObjectReuseAsIs.java [new file with mode: 0644]
org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/ObjectToPack.java [new file with mode: 0644]
org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/PackOutputStream.java [new file with mode: 0644]
org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/PackWriter.java [new file with mode: 0644]
org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/StoredObjectRepresentation.java [new file with mode: 0644]
org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackPushConnection.java
org.eclipse.jgit/src/org/eclipse/jgit/transport/BundleWriter.java
org.eclipse.jgit/src/org/eclipse/jgit/transport/IndexPack.java
org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java
org.eclipse.jgit/src/org/eclipse/jgit/transport/WalkPushConnection.java

index ab24b5aaf92708cb4215149a933e617efc0b86f3..7f4dcfddd6d79dd6024bdd1f36f1f42c33bae84c 100644 (file)
@@ -19,6 +19,7 @@ Import-Package: junit.framework;version="[3.8.2,4.0.0)",
  org.eclipse.jgit.revwalk;version="[0.9.0,0.10.0)",
  org.eclipse.jgit.revwalk.filter;version="[0.9.0,0.10.0)",
  org.eclipse.jgit.storage.file;version="[0.9.0,0.10.0)",
+ org.eclipse.jgit.storage.pack;version="[0.9.0,0.10.0)",
  org.eclipse.jgit.transport;version="[0.9.0,0.10.0)",
  org.eclipse.jgit.treewalk;version="[0.9.0,0.10.0)",
  org.eclipse.jgit.treewalk.filter;version="[0.9.0,0.10.0)",
index ec34e3c3a86c745d992a747fb642b35f18366938..18275ec710469be1f24575d6e1df2f27ee74f580 100644 (file)
@@ -77,7 +77,6 @@ import org.eclipse.jgit.lib.NullProgressMonitor;
 import org.eclipse.jgit.lib.ObjectChecker;
 import org.eclipse.jgit.lib.ObjectId;
 import org.eclipse.jgit.lib.ObjectInserter;
-import org.eclipse.jgit.lib.PackWriter;
 import org.eclipse.jgit.lib.PersonIdent;
 import org.eclipse.jgit.lib.Ref;
 import org.eclipse.jgit.lib.RefUpdate;
@@ -96,6 +95,7 @@ import org.eclipse.jgit.storage.file.LockFile;
 import org.eclipse.jgit.storage.file.ObjectDirectory;
 import org.eclipse.jgit.storage.file.PackFile;
 import org.eclipse.jgit.storage.file.PackIndex.MutableEntry;
+import org.eclipse.jgit.storage.pack.PackWriter;
 import org.eclipse.jgit.treewalk.TreeWalk;
 import org.eclipse.jgit.treewalk.filter.PathFilterGroup;
 
index b88ccf346776145d6f5427e40ba867c7a879ceb5..c8ad25d8153222da37929a92348dfde8c2dbb80b 100644 (file)
@@ -29,6 +29,7 @@ Import-Package: junit.framework;version="[3.8.2,4.0.0)",
  org.eclipse.jgit.revwalk;version="[0.9.0,0.10.0)",
  org.eclipse.jgit.revwalk.filter;version="[0.9.0,0.10.0)",
  org.eclipse.jgit.storage.file;version="[0.9.0,0.10.0)",
+ org.eclipse.jgit.storage.pack;version="[0.9.0,0.10.0)",
  org.eclipse.jgit.transport;version="[0.9.0,0.10.0)",
  org.eclipse.jgit.treewalk;version="[0.9.0,0.10.0)",
  org.eclipse.jgit.treewalk.filter;version="[0.9.0,0.10.0)",
index db770f777d00d5ede23dfb62de21987ba3fe05d3..96b117881718f7a2fd86cebf6ce252ddc75d5602 100644 (file)
@@ -59,11 +59,11 @@ import org.eclipse.jgit.lib.NullProgressMonitor;
 import org.eclipse.jgit.lib.ObjectId;
 import org.eclipse.jgit.lib.ObjectLoader;
 import org.eclipse.jgit.lib.ObjectWriter;
-import org.eclipse.jgit.lib.PackWriter;
 import org.eclipse.jgit.lib.Repository;
 import org.eclipse.jgit.lib.RepositoryTestCase;
 import org.eclipse.jgit.revwalk.RevObject;
 import org.eclipse.jgit.revwalk.RevWalk;
+import org.eclipse.jgit.storage.pack.PackWriter;
 
 public class ConcurrentRepackTest extends RepositoryTestCase {
        public void setUp() throws Exception {
index cf0d7eb6a320532c75b895c6c3efc7120c33907b..b12359cf60a11f32c5e8a596e8c5a5be0a8033b8 100644 (file)
@@ -60,12 +60,12 @@ import java.util.List;
 
 import org.eclipse.jgit.errors.MissingObjectException;
 import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.lib.PackWriter;
 import org.eclipse.jgit.lib.SampleDataRepositoryTestCase;
 import org.eclipse.jgit.lib.TextProgressMonitor;
 import org.eclipse.jgit.revwalk.RevObject;
 import org.eclipse.jgit.revwalk.RevWalk;
 import org.eclipse.jgit.storage.file.PackIndex.MutableEntry;
+import org.eclipse.jgit.storage.pack.PackWriter;
 import org.eclipse.jgit.transport.IndexPack;
 import org.eclipse.jgit.util.JGitTestUtil;
 
index e96ba038d0f20cf1f321b71172f65d45757d5d6f..23c61af8f7505ddd279e0cd0f2957d968c9a2593 100644 (file)
@@ -20,6 +20,7 @@ Export-Package: org.eclipse.jgit;version="0.9.0",
  org.eclipse.jgit.revwalk;version="0.9.0",
  org.eclipse.jgit.revwalk.filter;version="0.9.0",
  org.eclipse.jgit.storage.file;version="0.9.0",
+ org.eclipse.jgit.storage.pack;version="0.9.0",
  org.eclipse.jgit.transport;version="0.9.0",
  org.eclipse.jgit.treewalk;version="0.9.0",
  org.eclipse.jgit.treewalk.filter;version="0.9.0",
index cff44992775016bdc39198fcaf768999f6247c00..e9e3f4d65e58745a1a937211f37f8468d29ec7da 100644 (file)
@@ -43,7 +43,7 @@
 
 package org.eclipse.jgit.errors;
 
-import org.eclipse.jgit.lib.ObjectToPack;
+import org.eclipse.jgit.storage.pack.ObjectToPack;
 
 /** A previously selected representation is no longer available. */
 public class StoredObjectRepresentationNotAvailableException extends Exception {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/BinaryDelta.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/BinaryDelta.java
deleted file mode 100644 (file)
index a59b335..0000000
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com>
- * Copyright (C) 2006-2007, Shawn O. Pearce <spearce@spearce.org>
- * and other copyright owners as documented in the project's IP log.
- *
- * This program and the accompanying materials are made available
- * under the terms of the Eclipse Distribution License v1.0 which
- * accompanies this distribution, is reproduced below, and is
- * available at http://www.eclipse.org/org/documents/edl-v10.php
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above
- *   copyright notice, this list of conditions and the following
- *   disclaimer in the documentation and/or other materials provided
- *   with the distribution.
- *
- * - Neither the name of the Eclipse Foundation, Inc. nor the
- *   names of its contributors may be used to endorse or promote
- *   products derived from this software without specific prior
- *   written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package org.eclipse.jgit.lib;
-
-import org.eclipse.jgit.JGitText;
-
-/**
- * Recreate a stream from a base stream and a GIT pack delta.
- * <p>
- * This entire class is heavily cribbed from <code>patch-delta.c</code> in the
- * GIT project. The original delta patching code was written by Nicolas Pitre
- * (&lt;nico@cam.org&gt;).
- * </p>
- */
-public class BinaryDelta {
-
-       /**
-        * Apply the changes defined by delta to the data in base, yielding a new
-        * array of bytes.
-        *
-        * @param base
-        *            some byte representing an object of some kind.
-        * @param delta
-        *            a git pack delta defining the transform from one version to
-        *            another.
-        * @return patched base
-        */
-       public static final byte[] apply(final byte[] base, final byte[] delta) {
-               int deltaPtr = 0;
-
-               // Length of the base object (a variable length int).
-               //
-               int baseLen = 0;
-               int c, shift = 0;
-               do {
-                       c = delta[deltaPtr++] & 0xff;
-                       baseLen |= (c & 0x7f) << shift;
-                       shift += 7;
-               } while ((c & 0x80) != 0);
-               if (base.length != baseLen)
-                       throw new IllegalArgumentException(JGitText.get().baseLengthIncorrect);
-
-               // Length of the resulting object (a variable length int).
-               //
-               int resLen = 0;
-               shift = 0;
-               do {
-                       c = delta[deltaPtr++] & 0xff;
-                       resLen |= (c & 0x7f) << shift;
-                       shift += 7;
-               } while ((c & 0x80) != 0);
-
-               final byte[] result = new byte[resLen];
-               int resultPtr = 0;
-               while (deltaPtr < delta.length) {
-                       final int cmd = delta[deltaPtr++] & 0xff;
-                       if ((cmd & 0x80) != 0) {
-                               // Determine the segment of the base which should
-                               // be copied into the output. The segment is given
-                               // as an offset and a length.
-                               //
-                               int copyOffset = 0;
-                               if ((cmd & 0x01) != 0)
-                                       copyOffset = delta[deltaPtr++] & 0xff;
-                               if ((cmd & 0x02) != 0)
-                                       copyOffset |= (delta[deltaPtr++] & 0xff) << 8;
-                               if ((cmd & 0x04) != 0)
-                                       copyOffset |= (delta[deltaPtr++] & 0xff) << 16;
-                               if ((cmd & 0x08) != 0)
-                                       copyOffset |= (delta[deltaPtr++] & 0xff) << 24;
-
-                               int copySize = 0;
-                               if ((cmd & 0x10) != 0)
-                                       copySize = delta[deltaPtr++] & 0xff;
-                               if ((cmd & 0x20) != 0)
-                                       copySize |= (delta[deltaPtr++] & 0xff) << 8;
-                               if ((cmd & 0x40) != 0)
-                                       copySize |= (delta[deltaPtr++] & 0xff) << 16;
-                               if (copySize == 0)
-                                       copySize = 0x10000;
-
-                               System.arraycopy(base, copyOffset, result, resultPtr, copySize);
-                               resultPtr += copySize;
-                       } else if (cmd != 0) {
-                               // Anything else the data is literal within the delta
-                               // itself.
-                               //
-                               System.arraycopy(delta, deltaPtr, result, resultPtr, cmd);
-                               deltaPtr += cmd;
-                               resultPtr += cmd;
-                       } else {
-                               // cmd == 0 has been reserved for future encoding but
-                               // for now its not acceptable.
-                               //
-                               throw new IllegalArgumentException(JGitText.get().unsupportedCommand0);
-                       }
-               }
-
-               return result;
-       }
-}
index 670ead9efdbe46b0cbdb12e97c0ffbace941827a..29d2eb6f3be7fd4aced751392bca88d7cbd6b965 100644 (file)
@@ -46,6 +46,7 @@ package org.eclipse.jgit.lib;
 import java.io.IOException;
 
 import org.eclipse.jgit.errors.MissingObjectException;
+import org.eclipse.jgit.storage.pack.ObjectReuseAsIs;
 
 /**
  * Reads an {@link ObjectDatabase} for a single thread.
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectReuseAsIs.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectReuseAsIs.java
deleted file mode 100644 (file)
index f87b830..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright (C) 2010, Google Inc.
- * and other copyright owners as documented in the project's IP log.
- *
- * This program and the accompanying materials are made available
- * under the terms of the Eclipse Distribution License v1.0 which
- * accompanies this distribution, is reproduced below, and is
- * available at http://www.eclipse.org/org/documents/edl-v10.php
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above
- *   copyright notice, this list of conditions and the following
- *   disclaimer in the documentation and/or other materials provided
- *   with the distribution.
- *
- * - Neither the name of the Eclipse Foundation, Inc. nor the
- *   names of its contributors may be used to endorse or promote
- *   products derived from this software without specific prior
- *   written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package org.eclipse.jgit.lib;
-
-import java.io.IOException;
-
-import org.eclipse.jgit.errors.MissingObjectException;
-import org.eclipse.jgit.errors.StoredObjectRepresentationNotAvailableException;
-import org.eclipse.jgit.revwalk.RevObject;
-
-/**
- * Extension of {@link ObjectReader} that supports reusing objects in packs.
- * <p>
- * {@code ObjectReader} implementations may also optionally implement this
- * interface to support {@link PackWriter} with a means of copying an object
- * that is already in pack encoding format directly into the output stream,
- * without incurring decompression and recompression overheads.
- */
-public interface ObjectReuseAsIs {
-       /**
-        * Allocate a new {@code PackWriter} state structure for an object.
-        * <p>
-        * {@link PackWriter} allocates these objects to keep track of the
-        * per-object state, and how to load the objects efficiently into the
-        * generated stream. Implementers may subclass this type with additional
-        * object state, such as to remember what file and offset contains the
-        * object's pack encoded data.
-        *
-        * @param obj
-        *            identity of the object that will be packed. The object's
-        *            parsed status is undefined here. Implementers must not rely on
-        *            the object being parsed.
-        * @return a new instance for this object.
-        */
-       public ObjectToPack newObjectToPack(RevObject obj);
-
-       /**
-        * Select the best object representation for a packer.
-        * <p>
-        * Implementations should iterate through all available representations of
-        * an object, and pass them in turn to the PackWriter though
-        * {@link PackWriter#select(ObjectToPack, StoredObjectRepresentation)} so
-        * the writer can select the most suitable representation to reuse into the
-        * output stream.
-        *
-        * @param packer
-        *            the packer that will write the object in the near future.
-        * @param otp
-        *            the object to pack.
-        * @throws MissingObjectException
-        *             there is no representation available for the object, as it is
-        *             no longer in the repository. Packing will abort.
-        * @throws IOException
-        *             the repository cannot be accessed. Packing will abort.
-        */
-       public void selectObjectRepresentation(PackWriter packer, ObjectToPack otp)
-                       throws IOException, MissingObjectException;
-
-       /**
-        * Output a previously selected representation.
-        * <p>
-        * {@code PackWriter} invokes this method only if a representation
-        * previously given to it by {@code selectObjectRepresentation} was chosen
-        * for reuse into the output stream. The {@code otp} argument is an instance
-        * created by this reader's own {@code newObjectToPack}, and the
-        * representation data saved within it also originated from this reader.
-        * <p>
-        * Implementors must write the object header before copying the raw data to
-        * the output stream. The typical implementation is like:
-        *
-        * <pre>
-        * MyToPack mtp = (MyToPack) otp;
-        * byte[] raw = validate(mtp); // throw SORNAE here, if at all
-        * out.writeHeader(mtp, mtp.inflatedSize);
-        * out.write(raw);
-        * </pre>
-        *
-        * @param out
-        *            stream the object should be written to.
-        * @param otp
-        *            the object's saved representation information.
-        * @throws StoredObjectRepresentationNotAvailableException
-        *             the previously selected representation is no longer
-        *             available. If thrown before {@code out.writeHeader} the pack
-        *             writer will try to find another representation, and write
-        *             that one instead. If throw after {@code out.writeHeader},
-        *             packing will abort.
-        * @throws IOException
-        *             the stream's write method threw an exception. Packing will
-        *             abort.
-        */
-       public void copyObjectAsIs(PackOutputStream out, ObjectToPack otp)
-                       throws IOException, StoredObjectRepresentationNotAvailableException;
-}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectToPack.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectToPack.java
deleted file mode 100644 (file)
index 34a9696..0000000
+++ /dev/null
@@ -1,237 +0,0 @@
-/*
- * Copyright (C) 2008-2010, Google Inc.
- * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com>
- * and other copyright owners as documented in the project's IP log.
- *
- * This program and the accompanying materials are made available
- * under the terms of the Eclipse Distribution License v1.0 which
- * accompanies this distribution, is reproduced below, and is
- * available at http://www.eclipse.org/org/documents/edl-v10.php
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above
- *   copyright notice, this list of conditions and the following
- *   disclaimer in the documentation and/or other materials provided
- *   with the distribution.
- *
- * - Neither the name of the Eclipse Foundation, Inc. nor the
- *   names of its contributors may be used to endorse or promote
- *   products derived from this software without specific prior
- *   written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package org.eclipse.jgit.lib;
-
-import org.eclipse.jgit.revwalk.RevObject;
-import org.eclipse.jgit.transport.PackedObjectInfo;
-
-/**
- * Per-object state used by {@link PackWriter}.
- * <p>
- * {@code PackWriter} uses this class to track the things it needs to include in
- * the newly generated pack file, and how to efficiently obtain the raw data for
- * each object as they are written to the output stream.
- */
-public class ObjectToPack extends PackedObjectInfo {
-       private static final int WANT_WRITE = 1 << 0;
-
-       private static final int REUSE_AS_IS = 1 << 1;
-
-       private static final int TYPE_SHIFT = 5;
-
-       private static final int DELTA_SHIFT = 8;
-
-       private static final int NON_DELTA_MASK = 0xff;
-
-       /** Other object being packed that this will delta against. */
-       private ObjectId deltaBase;
-
-       /**
-        * Bit field, from bit 0 to bit 31:
-        * <ul>
-        * <li>1 bit: wantWrite</li>
-        * <li>1 bit: canReuseAsIs</li>
-        * <li>3 bits: unused</li>
-        * <li>3 bits: type</li>
-        * <li>--</li>
-        * <li>24 bits: deltaDepth</li>
-        * </ul>
-        */
-       private int flags;
-
-       /**
-        * Construct for the specified object id.
-        *
-        * @param src
-        *            object id of object for packing
-        * @param type
-        *            real type code of the object, not its in-pack type.
-        */
-       public ObjectToPack(AnyObjectId src, final int type) {
-               super(src);
-               flags = type << TYPE_SHIFT;
-       }
-
-       /**
-        * Construct for the specified object.
-        *
-        * @param obj
-        *            identity of the object that will be packed. The object's
-        *            parsed status is undefined here. Implementers must not rely on
-        *            the object being parsed.
-        */
-       public ObjectToPack(RevObject obj) {
-               this(obj, obj.getType());
-       }
-
-       /**
-        * @return delta base object id if object is going to be packed in delta
-        *         representation; null otherwise - if going to be packed as a
-        *         whole object.
-        */
-       ObjectId getDeltaBaseId() {
-               return deltaBase;
-       }
-
-       /**
-        * @return delta base object to pack if object is going to be packed in
-        *         delta representation and delta is specified as object to
-        *         pack; null otherwise - if going to be packed as a whole
-        *         object or delta base is specified only as id.
-        */
-       ObjectToPack getDeltaBase() {
-               if (deltaBase instanceof ObjectToPack)
-                       return (ObjectToPack) deltaBase;
-               return null;
-       }
-
-       /**
-        * Set delta base for the object. Delta base set by this method is used
-        * by {@link PackWriter} to write object - determines its representation
-        * in a created pack.
-        *
-        * @param deltaBase
-        *            delta base object or null if object should be packed as a
-        *            whole object.
-        *
-        */
-       void setDeltaBase(ObjectId deltaBase) {
-               this.deltaBase = deltaBase;
-       }
-
-       void clearDeltaBase() {
-               this.deltaBase = null;
-       }
-
-       /**
-        * @return true if object is going to be written as delta; false
-        *         otherwise.
-        */
-       boolean isDeltaRepresentation() {
-               return deltaBase != null;
-       }
-
-       /**
-        * Check if object is already written in a pack. This information is
-        * used to achieve delta-base precedence in a pack file.
-        *
-        * @return true if object is already written; false otherwise.
-        */
-       boolean isWritten() {
-               return getOffset() != 0;
-       }
-
-       int getType() {
-               return (flags >> TYPE_SHIFT) & 0x7;
-       }
-
-       int getDeltaDepth() {
-               return flags >>> DELTA_SHIFT;
-       }
-
-       void updateDeltaDepth() {
-               final int d;
-               if (deltaBase instanceof ObjectToPack)
-                       d = ((ObjectToPack) deltaBase).getDeltaDepth() + 1;
-               else if (deltaBase != null)
-                       d = 1;
-               else
-                       d = 0;
-               flags = (d << DELTA_SHIFT) | (flags & NON_DELTA_MASK);
-       }
-
-       boolean wantWrite() {
-               return (flags & WANT_WRITE) != 0;
-       }
-
-       void markWantWrite() {
-               flags |= WANT_WRITE;
-       }
-
-       boolean isReuseAsIs() {
-               return (flags & REUSE_AS_IS) != 0;
-       }
-
-       void setReuseAsIs() {
-               flags |= REUSE_AS_IS;
-       }
-
-       void clearReuseAsIs() {
-               flags &= ~REUSE_AS_IS;
-       }
-
-       int getFormat() {
-               if (isReuseAsIs()) {
-                       if (isDeltaRepresentation())
-                               return StoredObjectRepresentation.PACK_DELTA;
-                       return StoredObjectRepresentation.PACK_WHOLE;
-               }
-               return StoredObjectRepresentation.FORMAT_OTHER;
-       }
-
-       // Overload weight into CRC since we don't need them at the same time.
-       int getWeight() {
-               return getCRC();
-       }
-
-       void setWeight(int weight) {
-               setCRC(weight);
-       }
-
-       /**
-        * Remember a specific representation for reuse at a later time.
-        * <p>
-        * Implementers should remember the representation chosen, so it can be
-        * reused at a later time. {@link PackWriter} may invoke this method
-        * multiple times for the same object, each time saving the current best
-        * representation found.
-        *
-        * @param ref
-        *            the object representation.
-        */
-       public void select(StoredObjectRepresentation ref) {
-               // Empty by default.
-       }
-}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/PackOutputStream.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/PackOutputStream.java
deleted file mode 100644 (file)
index 48ec2b5..0000000
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * Copyright (C) 2008-2009, Google Inc.
- * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com>
- * and other copyright owners as documented in the project's IP log.
- *
- * This program and the accompanying materials are made available
- * under the terms of the Eclipse Distribution License v1.0 which
- * accompanies this distribution, is reproduced below, and is
- * available at http://www.eclipse.org/org/documents/edl-v10.php
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above
- *   copyright notice, this list of conditions and the following
- *   disclaimer in the documentation and/or other materials provided
- *   with the distribution.
- *
- * - Neither the name of the Eclipse Foundation, Inc. nor the
- *   names of its contributors may be used to endorse or promote
- *   products derived from this software without specific prior
- *   written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package org.eclipse.jgit.lib;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.security.MessageDigest;
-import java.util.zip.CRC32;
-
-import org.eclipse.jgit.util.NB;
-
-/** Custom output stream to support {@link PackWriter}. */
-public final class PackOutputStream extends OutputStream {
-       private final OutputStream out;
-
-       private final boolean ofsDelta;
-
-       private final CRC32 crc = new CRC32();
-
-       private final MessageDigest md = Constants.newMessageDigest();
-
-       private long count;
-
-       private byte[] headerBuffer = new byte[32];
-
-       private byte[] copyBuffer;
-
-       PackOutputStream(final OutputStream out, final boolean ofsDelta) {
-               this.out = out;
-               this.ofsDelta = ofsDelta;
-       }
-
-       @Override
-       public void write(final int b) throws IOException {
-               count++;
-               out.write(b);
-               crc.update(b);
-               md.update((byte) b);
-       }
-
-       @Override
-       public void write(final byte[] b, final int off, final int len)
-                       throws IOException {
-               count += len;
-               out.write(b, off, len);
-               crc.update(b, off, len);
-               md.update(b, off, len);
-       }
-
-       @Override
-       public void flush() throws IOException {
-               out.flush();
-       }
-
-       void writeFileHeader(int version, int objectCount) throws IOException {
-               System.arraycopy(Constants.PACK_SIGNATURE, 0, headerBuffer, 0, 4);
-               NB.encodeInt32(headerBuffer, 4, version);
-               NB.encodeInt32(headerBuffer, 8, objectCount);
-               write(headerBuffer, 0, 12);
-       }
-
-       /**
-        * Commits the object header onto the stream.
-        * <p>
-        * Once the header has been written, the object representation must be fully
-        * output, or packing must abort abnormally.
-        *
-        * @param otp
-        *            the object to pack. Header information is obtained.
-        * @param rawLength
-        *            number of bytes of the inflated content. For an object that is
-        *            in whole object format, this is the same as the object size.
-        *            For an object that is in a delta format, this is the size of
-        *            the inflated delta instruction stream.
-        * @throws IOException
-        *             the underlying stream refused to accept the header.
-        */
-       public void writeHeader(ObjectToPack otp, long rawLength)
-                       throws IOException {
-               if (otp.isDeltaRepresentation()) {
-                       if (ofsDelta) {
-                               ObjectToPack baseInPack = otp.getDeltaBase();
-                               if (baseInPack != null && baseInPack.isWritten()) {
-                                       final long start = count;
-                                       int n = encodeTypeSize(Constants.OBJ_OFS_DELTA, rawLength);
-                                       write(headerBuffer, 0, n);
-
-                                       long offsetDiff = start - baseInPack.getOffset();
-                                       n = headerBuffer.length - 1;
-                                       headerBuffer[n] = (byte) (offsetDiff & 0x7F);
-                                       while ((offsetDiff >>= 7) > 0)
-                                               headerBuffer[--n] = (byte) (0x80 | (--offsetDiff & 0x7F));
-                                       write(headerBuffer, n, headerBuffer.length - n);
-                                       return;
-                               }
-                       }
-
-                       int n = encodeTypeSize(Constants.OBJ_REF_DELTA, rawLength);
-                       otp.getDeltaBaseId().copyRawTo(headerBuffer, n);
-                       write(headerBuffer, 0, n + Constants.OBJECT_ID_LENGTH);
-               } else {
-                       int n = encodeTypeSize(otp.getType(), rawLength);
-                       write(headerBuffer, 0, n);
-               }
-       }
-
-       private int encodeTypeSize(int type, long rawLength) {
-               long nextLength = rawLength >>> 4;
-               headerBuffer[0] = (byte) ((nextLength > 0 ? 0x80 : 0x00)
-                               | (type << 4) | (rawLength & 0x0F));
-               rawLength = nextLength;
-               int n = 1;
-               while (rawLength > 0) {
-                       nextLength >>>= 7;
-                       headerBuffer[n++] = (byte) ((nextLength > 0 ? 0x80 : 0x00) | (rawLength & 0x7F));
-                       rawLength = nextLength;
-               }
-               return n;
-       }
-
-       /** @return a temporary buffer writers can use to copy data with. */
-       public byte[] getCopyBuffer() {
-               if (copyBuffer == null)
-                       copyBuffer = new byte[16 * 1024];
-               return copyBuffer;
-       }
-
-       /** @return total number of bytes written since stream start. */
-       long length() {
-               return count;
-       }
-
-       /** @return obtain the current CRC32 register. */
-       int getCRC32() {
-               return (int) crc.getValue();
-       }
-
-       /** Reinitialize the CRC32 register for a new region. */
-       void resetCRC32() {
-               crc.reset();
-       }
-
-       /** @return obtain the current SHA-1 digest. */
-       byte[] getDigest() {
-               return md.digest();
-       }
-}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/PackWriter.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/PackWriter.java
deleted file mode 100644 (file)
index a6f6b25..0000000
+++ /dev/null
@@ -1,881 +0,0 @@
-/*
- * Copyright (C) 2008-2010, Google Inc.
- * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com>
- * and other copyright owners as documented in the project's IP log.
- *
- * This program and the accompanying materials are made available
- * under the terms of the Eclipse Distribution License v1.0 which
- * accompanies this distribution, is reproduced below, and is
- * available at http://www.eclipse.org/org/documents/edl-v10.php
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above
- *   copyright notice, this list of conditions and the following
- *   disclaimer in the documentation and/or other materials provided
- *   with the distribution.
- *
- * - Neither the name of the Eclipse Foundation, Inc. nor the
- *   names of its contributors may be used to endorse or promote
- *   products derived from this software without specific prior
- *   written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package org.eclipse.jgit.lib;
-
-import static org.eclipse.jgit.lib.StoredObjectRepresentation.PACK_DELTA;
-import static org.eclipse.jgit.lib.StoredObjectRepresentation.PACK_WHOLE;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.security.MessageDigest;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-import java.util.zip.Deflater;
-
-import org.eclipse.jgit.JGitText;
-import org.eclipse.jgit.errors.CorruptObjectException;
-import org.eclipse.jgit.errors.IncorrectObjectTypeException;
-import org.eclipse.jgit.errors.MissingObjectException;
-import org.eclipse.jgit.errors.StoredObjectRepresentationNotAvailableException;
-import org.eclipse.jgit.revwalk.ObjectWalk;
-import org.eclipse.jgit.revwalk.RevFlag;
-import org.eclipse.jgit.revwalk.RevObject;
-import org.eclipse.jgit.revwalk.RevSort;
-import org.eclipse.jgit.storage.file.PackIndexWriter;
-
-/**
- * <p>
- * PackWriter class is responsible for generating pack files from specified set
- * of objects from repository. This implementation produce pack files in format
- * version 2.
- * </p>
- * <p>
- * Source of objects may be specified in two ways:
- * <ul>
- * <li>(usually) by providing sets of interesting and uninteresting objects in
- * repository - all interesting objects and their ancestors except uninteresting
- * objects and their ancestors will be included in pack, or</li>
- * <li>by providing iterator of {@link RevObject} specifying exact list and
- * order of objects in pack</li>
- * </ul>
- * Typical usage consists of creating instance intended for some pack,
- * configuring options, preparing the list of objects by calling
- * {@link #preparePack(Iterator)} or
- * {@link #preparePack(Collection, Collection)}, and finally
- * producing the stream with {@link #writePack(OutputStream)}.
- * </p>
- * <p>
- * Class provide set of configurable options and {@link ProgressMonitor}
- * support, as operations may take a long time for big repositories. Deltas
- * searching algorithm is <b>NOT IMPLEMENTED</b> yet - this implementation
- * relies only on deltas and objects reuse.
- * </p>
- * <p>
- * This class is not thread safe, it is intended to be used in one thread, with
- * one instance per created pack. Subsequent calls to writePack result in
- * undefined behavior.
- * </p>
- */
-public class PackWriter {
-       /**
-        * Title of {@link ProgressMonitor} task used during counting objects to
-        * pack.
-        *
-        * @see #preparePack(Collection, Collection)
-        */
-       public static final String COUNTING_OBJECTS_PROGRESS = JGitText.get().countingObjects;
-
-       /**
-        * Title of {@link ProgressMonitor} task used during searching for objects
-        * reuse or delta reuse.
-        *
-        * @see #writePack(OutputStream)
-        */
-       public static final String SEARCHING_REUSE_PROGRESS = JGitText.get().compressingObjects;
-
-       /**
-        * Title of {@link ProgressMonitor} task used during writing out pack
-        * (objects)
-        *
-        * @see #writePack(OutputStream)
-        */
-       public static final String WRITING_OBJECTS_PROGRESS = JGitText.get().writingObjects;
-
-       /**
-        * Default value of deltas reuse option.
-        *
-        * @see #setReuseDeltas(boolean)
-        */
-       public static final boolean DEFAULT_REUSE_DELTAS = true;
-
-       /**
-        * Default value of objects reuse option.
-        *
-        * @see #setReuseObjects(boolean)
-        */
-       public static final boolean DEFAULT_REUSE_OBJECTS = true;
-
-       /**
-        * Default value of delta base as offset option.
-        *
-        * @see #setDeltaBaseAsOffset(boolean)
-        */
-       public static final boolean DEFAULT_DELTA_BASE_AS_OFFSET = false;
-
-       /**
-        * Default value of maximum delta chain depth.
-        *
-        * @see #setMaxDeltaDepth(int)
-        */
-       public static final int DEFAULT_MAX_DELTA_DEPTH = 50;
-
-       private static final int PACK_VERSION_GENERATED = 2;
-
-       @SuppressWarnings("unchecked")
-       private final List<ObjectToPack> objectsLists[] = new List[Constants.OBJ_TAG + 1];
-       {
-               objectsLists[0] = Collections.<ObjectToPack> emptyList();
-               objectsLists[Constants.OBJ_COMMIT] = new ArrayList<ObjectToPack>();
-               objectsLists[Constants.OBJ_TREE] = new ArrayList<ObjectToPack>();
-               objectsLists[Constants.OBJ_BLOB] = new ArrayList<ObjectToPack>();
-               objectsLists[Constants.OBJ_TAG] = new ArrayList<ObjectToPack>();
-       }
-
-       private final ObjectIdSubclassMap<ObjectToPack> objectsMap = new ObjectIdSubclassMap<ObjectToPack>();
-
-       // edge objects for thin packs
-       private final ObjectIdSubclassMap<ObjectId> edgeObjects = new ObjectIdSubclassMap<ObjectId>();
-
-       private final Repository db;
-
-       private PackOutputStream out;
-
-       private final Deflater deflater;
-
-       private ProgressMonitor initMonitor;
-
-       private ProgressMonitor writeMonitor;
-
-       private final ObjectReader reader;
-
-       /** {@link #reader} recast to the reuse interface, if it supports it. */
-       private final ObjectReuseAsIs reuseSupport;
-
-       private List<ObjectToPack> sortedByName;
-
-       private byte packcsum[];
-
-       private boolean reuseDeltas = DEFAULT_REUSE_DELTAS;
-
-       private boolean reuseObjects = DEFAULT_REUSE_OBJECTS;
-
-       private boolean deltaBaseAsOffset = DEFAULT_DELTA_BASE_AS_OFFSET;
-
-       private int maxDeltaDepth = DEFAULT_MAX_DELTA_DEPTH;
-
-       private int outputVersion;
-
-       private boolean thin;
-
-       private boolean ignoreMissingUninteresting = true;
-
-       /**
-        * Create writer for specified repository.
-        * <p>
-        * Objects for packing are specified in {@link #preparePack(Iterator)} or
-        * {@link #preparePack(Collection, Collection)}.
-        *
-        * @param repo
-        *            repository where objects are stored.
-        * @param monitor
-        *            operations progress monitor, used within
-        *            {@link #preparePack(Iterator)},
-        *            {@link #preparePack(Collection, Collection)}
-        *            , or {@link #writePack(OutputStream)}.
-        */
-       public PackWriter(final Repository repo, final ProgressMonitor monitor) {
-               this(repo, monitor, monitor);
-       }
-
-       /**
-        * Create writer for specified repository.
-        * <p>
-        * Objects for packing are specified in {@link #preparePack(Iterator)} or
-        * {@link #preparePack(Collection, Collection)}.
-        *
-        * @param repo
-        *            repository where objects are stored.
-        * @param imonitor
-        *            operations progress monitor, used within
-        *            {@link #preparePack(Iterator)},
-        *            {@link #preparePack(Collection, Collection)}
-        * @param wmonitor
-        *            operations progress monitor, used within
-        *            {@link #writePack(OutputStream)}.
-        */
-       public PackWriter(final Repository repo, final ProgressMonitor imonitor,
-                       final ProgressMonitor wmonitor) {
-               this.db = repo;
-
-               reader = db.newObjectReader();
-               if (reader instanceof ObjectReuseAsIs)
-                       reuseSupport = ((ObjectReuseAsIs) reader);
-               else
-                       reuseSupport = null;
-
-               initMonitor = imonitor == null ? NullProgressMonitor.INSTANCE : imonitor;
-               writeMonitor = wmonitor == null ? NullProgressMonitor.INSTANCE : wmonitor;
-
-               final CoreConfig coreConfig = db.getConfig().get(CoreConfig.KEY);
-               this.deflater = new Deflater(coreConfig.getCompression());
-               outputVersion = coreConfig.getPackIndexVersion();
-       }
-
-       /**
-        * Check whether object is configured to reuse deltas existing in
-        * repository.
-        * <p>
-        * Default setting: {@value #DEFAULT_REUSE_DELTAS}
-        * </p>
-        *
-        * @return true if object is configured to reuse deltas; false otherwise.
-        */
-       public boolean isReuseDeltas() {
-               return reuseDeltas;
-       }
-
-       /**
-        * Set reuse deltas configuration option for this writer. When enabled,
-        * writer will search for delta representation of object in repository and
-        * use it if possible. Normally, only deltas with base to another object
-        * existing in set of objects to pack will be used. Exception is however
-        * thin-pack (see
-        * {@link #preparePack(Collection, Collection)} and
-        * {@link #preparePack(Iterator)}) where base object must exist on other
-        * side machine.
-        * <p>
-        * When raw delta data is directly copied from a pack file, checksum is
-        * computed to verify data.
-        * </p>
-        * <p>
-        * Default setting: {@value #DEFAULT_REUSE_DELTAS}
-        * </p>
-        *
-        * @param reuseDeltas
-        *            boolean indicating whether or not try to reuse deltas.
-        */
-       public void setReuseDeltas(boolean reuseDeltas) {
-               this.reuseDeltas = reuseDeltas;
-       }
-
-       /**
-        * Checks whether object is configured to reuse existing objects
-        * representation in repository.
-        * <p>
-        * Default setting: {@value #DEFAULT_REUSE_OBJECTS}
-        * </p>
-        *
-        * @return true if writer is configured to reuse objects representation from
-        *         pack; false otherwise.
-        */
-       public boolean isReuseObjects() {
-               return reuseObjects;
-       }
-
-       /**
-        * Set reuse objects configuration option for this writer. If enabled,
-        * writer searches for representation in a pack file. If possible,
-        * compressed data is directly copied from such a pack file. Data checksum
-        * is verified.
-        * <p>
-        * Default setting: {@value #DEFAULT_REUSE_OBJECTS}
-        * </p>
-        *
-        * @param reuseObjects
-        *            boolean indicating whether or not writer should reuse existing
-        *            objects representation.
-        */
-       public void setReuseObjects(boolean reuseObjects) {
-               this.reuseObjects = reuseObjects;
-       }
-
-       /**
-        * Check whether writer can store delta base as an offset (new style
-        * reducing pack size) or should store it as an object id (legacy style,
-        * compatible with old readers).
-        * <p>
-        * Default setting: {@value #DEFAULT_DELTA_BASE_AS_OFFSET}
-        * </p>
-        *
-        * @return true if delta base is stored as an offset; false if it is stored
-        *         as an object id.
-        */
-       public boolean isDeltaBaseAsOffset() {
-               return deltaBaseAsOffset;
-       }
-
-       /**
-        * Set writer delta base format. Delta base can be written as an offset in a
-        * pack file (new approach reducing file size) or as an object id (legacy
-        * approach, compatible with old readers).
-        * <p>
-        * Default setting: {@value #DEFAULT_DELTA_BASE_AS_OFFSET}
-        * </p>
-        *
-        * @param deltaBaseAsOffset
-        *            boolean indicating whether delta base can be stored as an
-        *            offset.
-        */
-       public void setDeltaBaseAsOffset(boolean deltaBaseAsOffset) {
-               this.deltaBaseAsOffset = deltaBaseAsOffset;
-       }
-
-       /**
-        * Get maximum depth of delta chain set up for this writer. Generated chains
-        * are not longer than this value.
-        * <p>
-        * Default setting: {@value #DEFAULT_MAX_DELTA_DEPTH}
-        * </p>
-        *
-        * @return maximum delta chain depth.
-        */
-       public int getMaxDeltaDepth() {
-               return maxDeltaDepth;
-       }
-
-       /**
-        * Set up maximum depth of delta chain for this writer. Generated chains are
-        * not longer than this value. Too low value causes low compression level,
-        * while too big makes unpacking (reading) longer.
-        * <p>
-        * Default setting: {@value #DEFAULT_MAX_DELTA_DEPTH}
-        * </p>
-        *
-        * @param maxDeltaDepth
-        *            maximum delta chain depth.
-        */
-       public void setMaxDeltaDepth(int maxDeltaDepth) {
-               this.maxDeltaDepth = maxDeltaDepth;
-       }
-
-       /** @return true if this writer is producing a thin pack. */
-       public boolean isThin() {
-               return thin;
-       }
-
-       /**
-        * @param packthin
-        *            a boolean indicating whether writer may pack objects with
-        *            delta base object not within set of objects to pack, but
-        *            belonging to party repository (uninteresting/boundary) as
-        *            determined by set; this kind of pack is used only for
-        *            transport; true - to produce thin pack, false - otherwise.
-        */
-       public void setThin(final boolean packthin) {
-               thin = packthin;
-       }
-
-       /**
-        * @return true to ignore objects that are uninteresting and also not found
-        *         on local disk; false to throw a {@link MissingObjectException}
-        *         out of {@link #preparePack(Collection, Collection)} if an
-        *         uninteresting object is not in the source repository. By default,
-        *         true, permitting gracefully ignoring of uninteresting objects.
-        */
-       public boolean isIgnoreMissingUninteresting() {
-               return ignoreMissingUninteresting;
-       }
-
-       /**
-        * @param ignore
-        *            true if writer should ignore non existing uninteresting
-        *            objects during construction set of objects to pack; false
-        *            otherwise - non existing uninteresting objects may cause
-        *            {@link MissingObjectException}
-        */
-       public void setIgnoreMissingUninteresting(final boolean ignore) {
-               ignoreMissingUninteresting = ignore;
-       }
-
-       /**
-        * Set the pack index file format version this instance will create.
-        *
-        * @param version
-        *            the version to write. The special version 0 designates the
-        *            oldest (most compatible) format available for the objects.
-        * @see PackIndexWriter
-        */
-       public void setIndexVersion(final int version) {
-               outputVersion = version;
-       }
-
-       /**
-        * Returns objects number in a pack file that was created by this writer.
-        *
-        * @return number of objects in pack.
-        */
-       public int getObjectsNumber() {
-               return objectsMap.size();
-       }
-
-       /**
-        * Prepare the list of objects to be written to the pack stream.
-        * <p>
-        * Iterator <b>exactly</b> determines which objects are included in a pack
-        * and order they appear in pack (except that objects order by type is not
-        * needed at input). This order should conform general rules of ordering
-        * objects in git - by recency and path (type and delta-base first is
-        * internally secured) and responsibility for guaranteeing this order is on
-        * a caller side. Iterator must return each id of object to write exactly
-        * once.
-        * </p>
-        * <p>
-        * When iterator returns object that has {@link RevFlag#UNINTERESTING} flag,
-        * this object won't be included in an output pack. Instead, it is recorded
-        * as edge-object (known to remote repository) for thin-pack. In such a case
-        * writer may pack objects with delta base object not within set of objects
-        * to pack, but belonging to party repository - those marked with
-        * {@link RevFlag#UNINTERESTING} flag. This type of pack is used only for
-        * transport.
-        * </p>
-        *
-        * @param objectsSource
-        *            iterator of object to store in a pack; order of objects within
-        *            each type is important, ordering by type is not needed;
-        *            allowed types for objects are {@link Constants#OBJ_COMMIT},
-        *            {@link Constants#OBJ_TREE}, {@link Constants#OBJ_BLOB} and
-        *            {@link Constants#OBJ_TAG}; objects returned by iterator may
-        *            be later reused by caller as object id and type are internally
-        *            copied in each iteration; if object returned by iterator has
-        *            {@link RevFlag#UNINTERESTING} flag set, it won't be included
-        *            in a pack, but is considered as edge-object for thin-pack.
-        * @throws IOException
-        *             when some I/O problem occur during reading objects.
-        */
-       public void preparePack(final Iterator<RevObject> objectsSource)
-                       throws IOException {
-               while (objectsSource.hasNext()) {
-                       addObject(objectsSource.next());
-               }
-       }
-
-       /**
-        * Prepare the list of objects to be written to the pack stream.
-        * <p>
-        * Basing on these 2 sets, another set of objects to put in a pack file is
-        * created: this set consists of all objects reachable (ancestors) from
-        * interesting objects, except uninteresting objects and their ancestors.
-        * This method uses class {@link ObjectWalk} extensively to find out that
-        * appropriate set of output objects and their optimal order in output pack.
-        * Order is consistent with general git in-pack rules: sort by object type,
-        * recency, path and delta-base first.
-        * </p>
-        *
-        * @param interestingObjects
-        *            collection of objects to be marked as interesting (start
-        *            points of graph traversal).
-        * @param uninterestingObjects
-        *            collection of objects to be marked as uninteresting (end
-        *            points of graph traversal).
-        * @throws IOException
-        *             when some I/O problem occur during reading objects.
-        */
-       public void preparePack(
-                       final Collection<? extends ObjectId> interestingObjects,
-                       final Collection<? extends ObjectId> uninterestingObjects)
-                       throws IOException {
-               ObjectWalk walker = setUpWalker(interestingObjects,
-                               uninterestingObjects);
-               findObjectsToPack(walker);
-       }
-
-       /**
-        * Determine if the pack file will contain the requested object.
-        *
-        * @param id
-        *            the object to test the existence of.
-        * @return true if the object will appear in the output pack file.
-        */
-       public boolean willInclude(final AnyObjectId id) {
-               return objectsMap.get(id) != null;
-       }
-
-       /**
-        * Computes SHA-1 of lexicographically sorted objects ids written in this
-        * pack, as used to name a pack file in repository.
-        *
-        * @return ObjectId representing SHA-1 name of a pack that was created.
-        */
-       public ObjectId computeName() {
-               final byte[] buf = new byte[Constants.OBJECT_ID_LENGTH];
-               final MessageDigest md = Constants.newMessageDigest();
-               for (ObjectToPack otp : sortByName()) {
-                       otp.copyRawTo(buf, 0);
-                       md.update(buf, 0, Constants.OBJECT_ID_LENGTH);
-               }
-               return ObjectId.fromRaw(md.digest());
-       }
-
-       /**
-        * Create an index file to match the pack file just written.
-        * <p>
-        * This method can only be invoked after {@link #preparePack(Iterator)} or
-        * {@link #preparePack(Collection, Collection)} has been
-        * invoked and completed successfully. Writing a corresponding index is an
-        * optional feature that not all pack users may require.
-        *
-        * @param indexStream
-        *            output for the index data. Caller is responsible for closing
-        *            this stream.
-        * @throws IOException
-        *             the index data could not be written to the supplied stream.
-        */
-       public void writeIndex(final OutputStream indexStream) throws IOException {
-               final List<ObjectToPack> list = sortByName();
-               final PackIndexWriter iw;
-               if (outputVersion <= 0)
-                       iw = PackIndexWriter.createOldestPossible(indexStream, list);
-               else
-                       iw = PackIndexWriter.createVersion(indexStream, outputVersion);
-               iw.write(list, packcsum);
-       }
-
-       private List<ObjectToPack> sortByName() {
-               if (sortedByName == null) {
-                       sortedByName = new ArrayList<ObjectToPack>(objectsMap.size());
-                       for (List<ObjectToPack> list : objectsLists) {
-                               for (ObjectToPack otp : list)
-                                       sortedByName.add(otp);
-                       }
-                       Collections.sort(sortedByName);
-               }
-               return sortedByName;
-       }
-
-       /**
-        * Write the prepared pack to the supplied stream.
-        * <p>
-        * At first, this method collects and sorts objects to pack, then deltas
-        * search is performed if set up accordingly, finally pack stream is
-        * written. {@link ProgressMonitor} tasks {@value #SEARCHING_REUSE_PROGRESS}
-        * (only if reuseDeltas or reuseObjects is enabled) and
-        * {@value #WRITING_OBJECTS_PROGRESS} are updated during packing.
-        * </p>
-        * <p>
-        * All reused objects data checksum (Adler32/CRC32) is computed and
-        * validated against existing checksum.
-        * </p>
-        *
-        * @param packStream
-        *            output stream of pack data. The stream should be buffered by
-        *            the caller. The caller is responsible for closing the stream.
-        * @throws IOException
-        *             an error occurred reading a local object's data to include in
-        *             the pack, or writing compressed object data to the output
-        *             stream.
-        */
-       public void writePack(OutputStream packStream) throws IOException {
-               if ((reuseDeltas || reuseObjects) && reuseSupport != null)
-                       searchForReuse();
-
-               out = new PackOutputStream(packStream, isDeltaBaseAsOffset());
-
-               writeMonitor.beginTask(WRITING_OBJECTS_PROGRESS, getObjectsNumber());
-               out.writeFileHeader(PACK_VERSION_GENERATED, getObjectsNumber());
-               writeObjects();
-               writeChecksum();
-
-               out = null;
-               reader.release();
-               writeMonitor.endTask();
-       }
-
-       private void searchForReuse() throws IOException {
-               initMonitor.beginTask(SEARCHING_REUSE_PROGRESS, getObjectsNumber());
-               for (List<ObjectToPack> list : objectsLists) {
-                       for (ObjectToPack otp : list) {
-                               if (initMonitor.isCancelled())
-                                       throw new IOException(
-                                                       JGitText.get().packingCancelledDuringObjectsWriting);
-                               reuseSupport.selectObjectRepresentation(this, otp);
-                               initMonitor.update(1);
-                       }
-               }
-               initMonitor.endTask();
-       }
-
-       private void writeObjects() throws IOException {
-               for (List<ObjectToPack> list : objectsLists) {
-                       for (ObjectToPack otp : list) {
-                               if (writeMonitor.isCancelled())
-                                       throw new IOException(
-                                                       JGitText.get().packingCancelledDuringObjectsWriting);
-                               if (!otp.isWritten())
-                                       writeObject(otp);
-                       }
-               }
-       }
-
-       private void writeObject(final ObjectToPack otp) throws IOException {
-               if (otp.isWritten())
-                       return; // We shouldn't be here.
-
-               otp.markWantWrite();
-               if (otp.isDeltaRepresentation())
-                       writeBaseFirst(otp);
-
-               out.resetCRC32();
-               otp.setOffset(out.length());
-
-               while (otp.isReuseAsIs()) {
-                       try {
-                               reuseSupport.copyObjectAsIs(out, otp);
-                               otp.setCRC(out.getCRC32());
-                               writeMonitor.update(1);
-                               return;
-                       } catch (StoredObjectRepresentationNotAvailableException gone) {
-                               if (otp.getOffset() == out.length()) {
-                                       redoSearchForReuse(otp);
-                                       continue;
-                               } else {
-                                       // Object writing already started, we cannot recover.
-                                       //
-                                       CorruptObjectException coe;
-                                       coe = new CorruptObjectException(otp, "");
-                                       coe.initCause(gone);
-                                       throw coe;
-                               }
-                       }
-               }
-
-               // If we reached here, reuse wasn't possible.
-               //
-               writeWholeObjectDeflate(otp);
-               otp.setCRC(out.getCRC32());
-               writeMonitor.update(1);
-       }
-
-       private void writeBaseFirst(final ObjectToPack otp) throws IOException {
-               ObjectToPack baseInPack = otp.getDeltaBase();
-               if (baseInPack != null) {
-                       if (!baseInPack.isWritten()) {
-                               if (baseInPack.wantWrite()) {
-                                       // There is a cycle. Our caller is trying to write the
-                                       // object we want as a base, and called us. Turn off
-                                       // delta reuse so we can find another form.
-                                       //
-                                       reuseDeltas = false;
-                                       redoSearchForReuse(otp);
-                                       reuseDeltas = true;
-                               } else {
-                                       writeObject(baseInPack);
-                               }
-                       }
-               } else if (!thin) {
-                       // This should never occur, the base isn't in the pack and
-                       // the pack isn't allowed to reference base outside objects.
-                       // Write the object as a whole form, even if that is slow.
-                       //
-                       otp.clearDeltaBase();
-                       otp.clearReuseAsIs();
-               }
-       }
-
-       private void redoSearchForReuse(final ObjectToPack otp) throws IOException,
-                       MissingObjectException {
-               otp.clearDeltaBase();
-               otp.clearReuseAsIs();
-               reuseSupport.selectObjectRepresentation(this, otp);
-       }
-
-       private void writeWholeObjectDeflate(final ObjectToPack otp)
-                       throws IOException {
-               final ObjectLoader loader = db.openObject(reader, otp);
-               final byte[] data = loader.getCachedBytes();
-               out.writeHeader(otp, data.length);
-               deflater.reset();
-               deflater.setInput(data, 0, data.length);
-               deflater.finish();
-
-               byte[] buf = out.getCopyBuffer();
-               do {
-                       final int n = deflater.deflate(buf, 0, buf.length);
-                       if (n > 0)
-                               out.write(buf, 0, n);
-               } while (!deflater.finished());
-       }
-
-       private void writeChecksum() throws IOException {
-               packcsum = out.getDigest();
-               out.write(packcsum);
-       }
-
-       private ObjectWalk setUpWalker(
-                       final Collection<? extends ObjectId> interestingObjects,
-                       final Collection<? extends ObjectId> uninterestingObjects)
-                       throws MissingObjectException, IOException,
-                       IncorrectObjectTypeException {
-               final ObjectWalk walker = new ObjectWalk(db);
-               walker.setRetainBody(false);
-               walker.sort(RevSort.COMMIT_TIME_DESC);
-               if (thin)
-                       walker.sort(RevSort.BOUNDARY, true);
-
-               for (ObjectId id : interestingObjects) {
-                       RevObject o = walker.parseAny(id);
-                       walker.markStart(o);
-               }
-               if (uninterestingObjects != null) {
-                       for (ObjectId id : uninterestingObjects) {
-                               final RevObject o;
-                               try {
-                                       o = walker.parseAny(id);
-                               } catch (MissingObjectException x) {
-                                       if (ignoreMissingUninteresting)
-                                               continue;
-                                       throw x;
-                               }
-                               walker.markUninteresting(o);
-                       }
-               }
-               return walker;
-       }
-
-       private void findObjectsToPack(final ObjectWalk walker)
-                       throws MissingObjectException, IncorrectObjectTypeException,
-                       IOException {
-               initMonitor.beginTask(COUNTING_OBJECTS_PROGRESS,
-                               ProgressMonitor.UNKNOWN);
-               RevObject o;
-
-               while ((o = walker.next()) != null) {
-                       addObject(o);
-                       initMonitor.update(1);
-               }
-               while ((o = walker.nextObject()) != null) {
-                       addObject(o);
-                       initMonitor.update(1);
-               }
-               initMonitor.endTask();
-       }
-
-       /**
-        * Include one object to the output file.
-        * <p>
-        * Objects are written in the order they are added. If the same object is
-        * added twice, it may be written twice, creating a larger than necessary
-        * file.
-        *
-        * @param object
-        *            the object to add.
-        * @throws IncorrectObjectTypeException
-        *             the object is an unsupported type.
-        */
-       public void addObject(final RevObject object)
-                       throws IncorrectObjectTypeException {
-               if (object.has(RevFlag.UNINTERESTING)) {
-                       edgeObjects.add(object);
-                       thin = true;
-                       return;
-               }
-
-               final ObjectToPack otp;
-               if (reuseSupport != null)
-                       otp = reuseSupport.newObjectToPack(object);
-               else
-                       otp = new ObjectToPack(object);
-               try {
-                       objectsLists[object.getType()].add(otp);
-               } catch (ArrayIndexOutOfBoundsException x) {
-                       throw new IncorrectObjectTypeException(object,
-                                       JGitText.get().incorrectObjectType_COMMITnorTREEnorBLOBnorTAG);
-               } catch (UnsupportedOperationException x) {
-                       // index pointing to "dummy" empty list
-                       throw new IncorrectObjectTypeException(object,
-                                       JGitText.get().incorrectObjectType_COMMITnorTREEnorBLOBnorTAG);
-               }
-               objectsMap.add(otp);
-       }
-
-       /**
-        * Select an object representation for this writer.
-        * <p>
-        * An {@link ObjectReader} implementation should invoke this method once for
-        * each representation available for an object, to allow the writer to find
-        * the most suitable one for the output.
-        *
-        * @param otp
-        *            the object being packed.
-        * @param next
-        *            the next available representation from the repository.
-        */
-       public void select(ObjectToPack otp, StoredObjectRepresentation next) {
-               int nFmt = next.getFormat();
-               int nWeight;
-               if (otp.isReuseAsIs()) {
-                       // We've already chosen to reuse a packed form, if next
-                       // cannot beat that break out early.
-                       //
-                       if (PACK_WHOLE < nFmt)
-                               return; // next isn't packed
-                       else if (PACK_DELTA < nFmt && otp.isDeltaRepresentation())
-                               return; // next isn't a delta, but we are
-
-                       nWeight = next.getWeight();
-                       if (otp.getWeight() <= nWeight)
-                               return; // next would be bigger
-               } else
-                       nWeight = next.getWeight();
-
-               if (nFmt == PACK_DELTA && reuseDeltas) {
-                       ObjectId baseId = next.getDeltaBase();
-                       ObjectToPack ptr = objectsMap.get(baseId);
-                       if (ptr != null) {
-                               otp.setDeltaBase(ptr);
-                               otp.setReuseAsIs();
-                               otp.setWeight(nWeight);
-                       } else if (thin && edgeObjects.contains(baseId)) {
-                               otp.setDeltaBase(baseId);
-                               otp.setReuseAsIs();
-                               otp.setWeight(nWeight);
-                       } else {
-                               otp.clearDeltaBase();
-                               otp.clearReuseAsIs();
-                       }
-               } else if (nFmt == PACK_WHOLE && reuseObjects) {
-                       otp.clearDeltaBase();
-                       otp.setReuseAsIs();
-                       otp.setWeight(nWeight);
-               } else {
-                       otp.clearDeltaBase();
-                       otp.clearReuseAsIs();
-               }
-
-               otp.select(next);
-       }
-}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/StoredObjectRepresentation.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/StoredObjectRepresentation.java
deleted file mode 100644 (file)
index 0eb05f5..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2010, Google Inc.
- * and other copyright owners as documented in the project's IP log.
- *
- * This program and the accompanying materials are made available
- * under the terms of the Eclipse Distribution License v1.0 which
- * accompanies this distribution, is reproduced below, and is
- * available at http://www.eclipse.org/org/documents/edl-v10.php
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above
- *   copyright notice, this list of conditions and the following
- *   disclaimer in the documentation and/or other materials provided
- *   with the distribution.
- *
- * - Neither the name of the Eclipse Foundation, Inc. nor the
- *   names of its contributors may be used to endorse or promote
- *   products derived from this software without specific prior
- *   written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-package org.eclipse.jgit.lib;
-
-/**
- * An object representation {@link PackWriter} can consider for packing.
- */
-public class StoredObjectRepresentation {
-       /** Special unknown value for {@link #getWeight()}. */
-       public static final int WEIGHT_UNKNOWN = Integer.MAX_VALUE;
-
-       /** Stored in pack format, as a delta to another object. */
-       public static final int PACK_DELTA = 0;
-
-       /** Stored in pack format, without delta. */
-       public static final int PACK_WHOLE = 1;
-
-       /** Only available after inflating to canonical format. */
-       public static final int FORMAT_OTHER = 2;
-
-       /**
-        * @return relative size of this object's packed form. The special value
-        *         {@link #WEIGHT_UNKNOWN} can be returned to indicate the
-        *         implementation doesn't know, or cannot supply the weight up
-        *         front.
-        */
-       public int getWeight() {
-               return WEIGHT_UNKNOWN;
-       }
-
-       /**
-        * @return true if this is a delta against another object and this is stored
-        *         in pack delta format.
-        */
-       public int getFormat() {
-               return FORMAT_OTHER;
-       }
-
-       /**
-        * @return identity of the object this delta applies to in order to recover
-        *         the original object content. This method should only be called if
-        *         {@link #getFormat()} returned {@link #PACK_DELTA}.
-        */
-       public ObjectId getDeltaBase() {
-               return null;
-       }
-}
index 79730d0551cd88a19f38addca8d3e6589021015e..194561238d39d9aa5bb83c64212e2b9a44411cf4 100644 (file)
@@ -54,8 +54,8 @@ import org.eclipse.jgit.lib.ObjectId;
 import org.eclipse.jgit.lib.ObjectIdSubclassMap;
 import org.eclipse.jgit.lib.ObjectInserter;
 import org.eclipse.jgit.lib.ObjectLoader;
-import org.eclipse.jgit.lib.ObjectToPack;
-import org.eclipse.jgit.lib.PackWriter;
+import org.eclipse.jgit.storage.pack.ObjectToPack;
+import org.eclipse.jgit.storage.pack.PackWriter;
 
 /**
  * The cached instance of an {@link ObjectDirectory}.
index 6266a7c084bd732009a58f905272b636b90e0248..f0609897a376c7cf5f8532301cc5a86542098256 100644 (file)
@@ -50,8 +50,8 @@ import org.eclipse.jgit.lib.AnyObjectId;
 import org.eclipse.jgit.lib.ObjectDatabase;
 import org.eclipse.jgit.lib.ObjectLoader;
 import org.eclipse.jgit.lib.ObjectReader;
-import org.eclipse.jgit.lib.ObjectToPack;
-import org.eclipse.jgit.lib.PackWriter;
+import org.eclipse.jgit.storage.pack.ObjectToPack;
+import org.eclipse.jgit.storage.pack.PackWriter;
 
 abstract class FileObjectDatabase extends ObjectDatabase {
        @Override
index 6ddd66e6d32c8d79a8d0ca716d932ccd15a42690..08bb8e60d59945293b48e6696f8223a6ba4d223c 100644 (file)
@@ -46,7 +46,7 @@ package org.eclipse.jgit.storage.file;
 import java.io.IOException;
 
 import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.lib.StoredObjectRepresentation;
+import org.eclipse.jgit.storage.pack.StoredObjectRepresentation;
 
 class LocalObjectRepresentation extends StoredObjectRepresentation {
        static LocalObjectRepresentation newWhole(PackFile f, long p, long length) {
index e1b25426778539e179d952eff83b04a5e6f02245..b4bf37a5e9241c840dac875df244e5240c058c75 100644 (file)
@@ -43,9 +43,9 @@
 
 package org.eclipse.jgit.storage.file;
 
-import org.eclipse.jgit.lib.ObjectToPack;
-import org.eclipse.jgit.lib.StoredObjectRepresentation;
 import org.eclipse.jgit.revwalk.RevObject;
+import org.eclipse.jgit.storage.pack.ObjectToPack;
+import org.eclipse.jgit.storage.pack.StoredObjectRepresentation;
 
 /** {@link ObjectToPack} for {@link ObjectDirectory}. */
 class LocalObjectToPack extends ObjectToPack {
index 2936efd296608da3cf29782d3bf7e54c6ea258b6..7020b7a67c4d0494f0ed68ab1b5393b50fdfeff1 100644 (file)
@@ -68,10 +68,10 @@ import org.eclipse.jgit.lib.ObjectDatabase;
 import org.eclipse.jgit.lib.ObjectId;
 import org.eclipse.jgit.lib.ObjectInserter;
 import org.eclipse.jgit.lib.ObjectLoader;
-import org.eclipse.jgit.lib.ObjectToPack;
-import org.eclipse.jgit.lib.PackWriter;
 import org.eclipse.jgit.lib.RepositoryCache;
 import org.eclipse.jgit.lib.RepositoryCache.FileKey;
+import org.eclipse.jgit.storage.pack.ObjectToPack;
+import org.eclipse.jgit.storage.pack.PackWriter;
 import org.eclipse.jgit.util.FS;
 
 /**
index de9c8eca5f85d53bccfbad434ea4a72532dcdd2d..f68019c40fd342a229e86fe8134d7bc8ff24408e 100644 (file)
@@ -67,11 +67,11 @@ import org.eclipse.jgit.errors.PackInvalidException;
 import org.eclipse.jgit.errors.PackMismatchException;
 import org.eclipse.jgit.errors.StoredObjectRepresentationNotAvailableException;
 import org.eclipse.jgit.lib.AnyObjectId;
-import org.eclipse.jgit.lib.BinaryDelta;
 import org.eclipse.jgit.lib.Constants;
 import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.lib.ObjectToPack;
-import org.eclipse.jgit.lib.PackOutputStream;
+import org.eclipse.jgit.storage.pack.BinaryDelta;
+import org.eclipse.jgit.storage.pack.ObjectToPack;
+import org.eclipse.jgit.storage.pack.PackOutputStream;
 import org.eclipse.jgit.util.LongList;
 import org.eclipse.jgit.util.NB;
 import org.eclipse.jgit.util.RawParseUtils;
index d359de07e9bd608910f874293dde89edbc31623f..d5c2fd79dd758cce26c1045e9e3b8482c79e4e91 100644 (file)
@@ -55,11 +55,11 @@ import org.eclipse.jgit.lib.Constants;
 import org.eclipse.jgit.lib.InflaterCache;
 import org.eclipse.jgit.lib.ObjectLoader;
 import org.eclipse.jgit.lib.ObjectReader;
-import org.eclipse.jgit.lib.ObjectReuseAsIs;
-import org.eclipse.jgit.lib.ObjectToPack;
-import org.eclipse.jgit.lib.PackOutputStream;
-import org.eclipse.jgit.lib.PackWriter;
 import org.eclipse.jgit.revwalk.RevObject;
+import org.eclipse.jgit.storage.pack.ObjectReuseAsIs;
+import org.eclipse.jgit.storage.pack.ObjectToPack;
+import org.eclipse.jgit.storage.pack.PackOutputStream;
+import org.eclipse.jgit.storage.pack.PackWriter;
 
 /** Active handle to a ByteWindow. */
 final class WindowCursor extends ObjectReader implements ObjectReuseAsIs {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/BinaryDelta.java b/org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/BinaryDelta.java
new file mode 100644 (file)
index 0000000..027ffd6
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com>
+ * Copyright (C) 2006-2007, Shawn O. Pearce <spearce@spearce.org>
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ *   copyright notice, this list of conditions and the following
+ *   disclaimer in the documentation and/or other materials provided
+ *   with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ *   names of its contributors may be used to endorse or promote
+ *   products derived from this software without specific prior
+ *   written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.eclipse.jgit.storage.pack;
+
+import org.eclipse.jgit.JGitText;
+
+/**
+ * Recreate a stream from a base stream and a GIT pack delta.
+ * <p>
+ * This entire class is heavily cribbed from <code>patch-delta.c</code> in the
+ * GIT project. The original delta patching code was written by Nicolas Pitre
+ * (&lt;nico@cam.org&gt;).
+ * </p>
+ */
+public class BinaryDelta {
+
+       /**
+        * Apply the changes defined by delta to the data in base, yielding a new
+        * array of bytes.
+        *
+        * @param base
+        *            some byte representing an object of some kind.
+        * @param delta
+        *            a git pack delta defining the transform from one version to
+        *            another.
+        * @return patched base
+        */
+       public static final byte[] apply(final byte[] base, final byte[] delta) {
+               int deltaPtr = 0;
+
+               // Length of the base object (a variable length int).
+               //
+               int baseLen = 0;
+               int c, shift = 0;
+               do {
+                       c = delta[deltaPtr++] & 0xff;
+                       baseLen |= (c & 0x7f) << shift;
+                       shift += 7;
+               } while ((c & 0x80) != 0);
+               if (base.length != baseLen)
+                       throw new IllegalArgumentException(JGitText.get().baseLengthIncorrect);
+
+               // Length of the resulting object (a variable length int).
+               //
+               int resLen = 0;
+               shift = 0;
+               do {
+                       c = delta[deltaPtr++] & 0xff;
+                       resLen |= (c & 0x7f) << shift;
+                       shift += 7;
+               } while ((c & 0x80) != 0);
+
+               final byte[] result = new byte[resLen];
+               int resultPtr = 0;
+               while (deltaPtr < delta.length) {
+                       final int cmd = delta[deltaPtr++] & 0xff;
+                       if ((cmd & 0x80) != 0) {
+                               // Determine the segment of the base which should
+                               // be copied into the output. The segment is given
+                               // as an offset and a length.
+                               //
+                               int copyOffset = 0;
+                               if ((cmd & 0x01) != 0)
+                                       copyOffset = delta[deltaPtr++] & 0xff;
+                               if ((cmd & 0x02) != 0)
+                                       copyOffset |= (delta[deltaPtr++] & 0xff) << 8;
+                               if ((cmd & 0x04) != 0)
+                                       copyOffset |= (delta[deltaPtr++] & 0xff) << 16;
+                               if ((cmd & 0x08) != 0)
+                                       copyOffset |= (delta[deltaPtr++] & 0xff) << 24;
+
+                               int copySize = 0;
+                               if ((cmd & 0x10) != 0)
+                                       copySize = delta[deltaPtr++] & 0xff;
+                               if ((cmd & 0x20) != 0)
+                                       copySize |= (delta[deltaPtr++] & 0xff) << 8;
+                               if ((cmd & 0x40) != 0)
+                                       copySize |= (delta[deltaPtr++] & 0xff) << 16;
+                               if (copySize == 0)
+                                       copySize = 0x10000;
+
+                               System.arraycopy(base, copyOffset, result, resultPtr, copySize);
+                               resultPtr += copySize;
+                       } else if (cmd != 0) {
+                               // Anything else the data is literal within the delta
+                               // itself.
+                               //
+                               System.arraycopy(delta, deltaPtr, result, resultPtr, cmd);
+                               deltaPtr += cmd;
+                               resultPtr += cmd;
+                       } else {
+                               // cmd == 0 has been reserved for future encoding but
+                               // for now its not acceptable.
+                               //
+                               throw new IllegalArgumentException(JGitText.get().unsupportedCommand0);
+                       }
+               }
+
+               return result;
+       }
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/ObjectReuseAsIs.java b/org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/ObjectReuseAsIs.java
new file mode 100644 (file)
index 0000000..a815e93
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2010, Google Inc.
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ *   copyright notice, this list of conditions and the following
+ *   disclaimer in the documentation and/or other materials provided
+ *   with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ *   names of its contributors may be used to endorse or promote
+ *   products derived from this software without specific prior
+ *   written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.eclipse.jgit.storage.pack;
+
+import java.io.IOException;
+
+import org.eclipse.jgit.errors.MissingObjectException;
+import org.eclipse.jgit.errors.StoredObjectRepresentationNotAvailableException;
+import org.eclipse.jgit.lib.ObjectReader;
+import org.eclipse.jgit.revwalk.RevObject;
+
+/**
+ * Extension of {@link ObjectReader} that supports reusing objects in packs.
+ * <p>
+ * {@code ObjectReader} implementations may also optionally implement this
+ * interface to support {@link PackWriter} with a means of copying an object
+ * that is already in pack encoding format directly into the output stream,
+ * without incurring decompression and recompression overheads.
+ */
+public interface ObjectReuseAsIs {
+       /**
+        * Allocate a new {@code PackWriter} state structure for an object.
+        * <p>
+        * {@link PackWriter} allocates these objects to keep track of the
+        * per-object state, and how to load the objects efficiently into the
+        * generated stream. Implementers may subclass this type with additional
+        * object state, such as to remember what file and offset contains the
+        * object's pack encoded data.
+        *
+        * @param obj
+        *            identity of the object that will be packed. The object's
+        *            parsed status is undefined here. Implementers must not rely on
+        *            the object being parsed.
+        * @return a new instance for this object.
+        */
+       public ObjectToPack newObjectToPack(RevObject obj);
+
+       /**
+        * Select the best object representation for a packer.
+        * <p>
+        * Implementations should iterate through all available representations of
+        * an object, and pass them in turn to the PackWriter though
+        * {@link PackWriter#select(ObjectToPack, StoredObjectRepresentation)} so
+        * the writer can select the most suitable representation to reuse into the
+        * output stream.
+        *
+        * @param packer
+        *            the packer that will write the object in the near future.
+        * @param otp
+        *            the object to pack.
+        * @throws MissingObjectException
+        *             there is no representation available for the object, as it is
+        *             no longer in the repository. Packing will abort.
+        * @throws IOException
+        *             the repository cannot be accessed. Packing will abort.
+        */
+       public void selectObjectRepresentation(PackWriter packer, ObjectToPack otp)
+                       throws IOException, MissingObjectException;
+
+       /**
+        * Output a previously selected representation.
+        * <p>
+        * {@code PackWriter} invokes this method only if a representation
+        * previously given to it by {@code selectObjectRepresentation} was chosen
+        * for reuse into the output stream. The {@code otp} argument is an instance
+        * created by this reader's own {@code newObjectToPack}, and the
+        * representation data saved within it also originated from this reader.
+        * <p>
+        * Implementors must write the object header before copying the raw data to
+        * the output stream. The typical implementation is like:
+        *
+        * <pre>
+        * MyToPack mtp = (MyToPack) otp;
+        * byte[] raw = validate(mtp); // throw SORNAE here, if at all
+        * out.writeHeader(mtp, mtp.inflatedSize);
+        * out.write(raw);
+        * </pre>
+        *
+        * @param out
+        *            stream the object should be written to.
+        * @param otp
+        *            the object's saved representation information.
+        * @throws StoredObjectRepresentationNotAvailableException
+        *             the previously selected representation is no longer
+        *             available. If thrown before {@code out.writeHeader} the pack
+        *             writer will try to find another representation, and write
+        *             that one instead. If throw after {@code out.writeHeader},
+        *             packing will abort.
+        * @throws IOException
+        *             the stream's write method threw an exception. Packing will
+        *             abort.
+        */
+       public void copyObjectAsIs(PackOutputStream out, ObjectToPack otp)
+                       throws IOException, StoredObjectRepresentationNotAvailableException;
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/ObjectToPack.java b/org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/ObjectToPack.java
new file mode 100644 (file)
index 0000000..773ce44
--- /dev/null
@@ -0,0 +1,239 @@
+/*
+ * Copyright (C) 2008-2010, Google Inc.
+ * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com>
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ *   copyright notice, this list of conditions and the following
+ *   disclaimer in the documentation and/or other materials provided
+ *   with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ *   names of its contributors may be used to endorse or promote
+ *   products derived from this software without specific prior
+ *   written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.eclipse.jgit.storage.pack;
+
+import org.eclipse.jgit.lib.AnyObjectId;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.revwalk.RevObject;
+import org.eclipse.jgit.transport.PackedObjectInfo;
+
+/**
+ * Per-object state used by {@link PackWriter}.
+ * <p>
+ * {@code PackWriter} uses this class to track the things it needs to include in
+ * the newly generated pack file, and how to efficiently obtain the raw data for
+ * each object as they are written to the output stream.
+ */
+public class ObjectToPack extends PackedObjectInfo {
+       private static final int WANT_WRITE = 1 << 0;
+
+       private static final int REUSE_AS_IS = 1 << 1;
+
+       private static final int TYPE_SHIFT = 5;
+
+       private static final int DELTA_SHIFT = 8;
+
+       private static final int NON_DELTA_MASK = 0xff;
+
+       /** Other object being packed that this will delta against. */
+       private ObjectId deltaBase;
+
+       /**
+        * Bit field, from bit 0 to bit 31:
+        * <ul>
+        * <li>1 bit: wantWrite</li>
+        * <li>1 bit: canReuseAsIs</li>
+        * <li>3 bits: unused</li>
+        * <li>3 bits: type</li>
+        * <li>--</li>
+        * <li>24 bits: deltaDepth</li>
+        * </ul>
+        */
+       private int flags;
+
+       /**
+        * Construct for the specified object id.
+        *
+        * @param src
+        *            object id of object for packing
+        * @param type
+        *            real type code of the object, not its in-pack type.
+        */
+       public ObjectToPack(AnyObjectId src, final int type) {
+               super(src);
+               flags = type << TYPE_SHIFT;
+       }
+
+       /**
+        * Construct for the specified object.
+        *
+        * @param obj
+        *            identity of the object that will be packed. The object's
+        *            parsed status is undefined here. Implementers must not rely on
+        *            the object being parsed.
+        */
+       public ObjectToPack(RevObject obj) {
+               this(obj, obj.getType());
+       }
+
+       /**
+        * @return delta base object id if object is going to be packed in delta
+        *         representation; null otherwise - if going to be packed as a
+        *         whole object.
+        */
+       ObjectId getDeltaBaseId() {
+               return deltaBase;
+       }
+
+       /**
+        * @return delta base object to pack if object is going to be packed in
+        *         delta representation and delta is specified as object to
+        *         pack; null otherwise - if going to be packed as a whole
+        *         object or delta base is specified only as id.
+        */
+       ObjectToPack getDeltaBase() {
+               if (deltaBase instanceof ObjectToPack)
+                       return (ObjectToPack) deltaBase;
+               return null;
+       }
+
+       /**
+        * Set delta base for the object. Delta base set by this method is used
+        * by {@link PackWriter} to write object - determines its representation
+        * in a created pack.
+        *
+        * @param deltaBase
+        *            delta base object or null if object should be packed as a
+        *            whole object.
+        *
+        */
+       void setDeltaBase(ObjectId deltaBase) {
+               this.deltaBase = deltaBase;
+       }
+
+       void clearDeltaBase() {
+               this.deltaBase = null;
+       }
+
+       /**
+        * @return true if object is going to be written as delta; false
+        *         otherwise.
+        */
+       boolean isDeltaRepresentation() {
+               return deltaBase != null;
+       }
+
+       /**
+        * Check if object is already written in a pack. This information is
+        * used to achieve delta-base precedence in a pack file.
+        *
+        * @return true if object is already written; false otherwise.
+        */
+       boolean isWritten() {
+               return getOffset() != 0;
+       }
+
+       int getType() {
+               return (flags >> TYPE_SHIFT) & 0x7;
+       }
+
+       int getDeltaDepth() {
+               return flags >>> DELTA_SHIFT;
+       }
+
+       void updateDeltaDepth() {
+               final int d;
+               if (deltaBase instanceof ObjectToPack)
+                       d = ((ObjectToPack) deltaBase).getDeltaDepth() + 1;
+               else if (deltaBase != null)
+                       d = 1;
+               else
+                       d = 0;
+               flags = (d << DELTA_SHIFT) | (flags & NON_DELTA_MASK);
+       }
+
+       boolean wantWrite() {
+               return (flags & WANT_WRITE) != 0;
+       }
+
+       void markWantWrite() {
+               flags |= WANT_WRITE;
+       }
+
+       boolean isReuseAsIs() {
+               return (flags & REUSE_AS_IS) != 0;
+       }
+
+       void setReuseAsIs() {
+               flags |= REUSE_AS_IS;
+       }
+
+       void clearReuseAsIs() {
+               flags &= ~REUSE_AS_IS;
+       }
+
+       int getFormat() {
+               if (isReuseAsIs()) {
+                       if (isDeltaRepresentation())
+                               return StoredObjectRepresentation.PACK_DELTA;
+                       return StoredObjectRepresentation.PACK_WHOLE;
+               }
+               return StoredObjectRepresentation.FORMAT_OTHER;
+       }
+
+       // Overload weight into CRC since we don't need them at the same time.
+       int getWeight() {
+               return getCRC();
+       }
+
+       void setWeight(int weight) {
+               setCRC(weight);
+       }
+
+       /**
+        * Remember a specific representation for reuse at a later time.
+        * <p>
+        * Implementers should remember the representation chosen, so it can be
+        * reused at a later time. {@link PackWriter} may invoke this method
+        * multiple times for the same object, each time saving the current best
+        * representation found.
+        *
+        * @param ref
+        *            the object representation.
+        */
+       public void select(StoredObjectRepresentation ref) {
+               // Empty by default.
+       }
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/PackOutputStream.java b/org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/PackOutputStream.java
new file mode 100644 (file)
index 0000000..bc20f89
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2008-2009, Google Inc.
+ * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com>
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ *   copyright notice, this list of conditions and the following
+ *   disclaimer in the documentation and/or other materials provided
+ *   with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ *   names of its contributors may be used to endorse or promote
+ *   products derived from this software without specific prior
+ *   written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.eclipse.jgit.storage.pack;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.security.MessageDigest;
+import java.util.zip.CRC32;
+
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.util.NB;
+
+/** Custom output stream to support {@link PackWriter}. */
+public final class PackOutputStream extends OutputStream {
+       private final OutputStream out;
+
+       private final boolean ofsDelta;
+
+       private final CRC32 crc = new CRC32();
+
+       private final MessageDigest md = Constants.newMessageDigest();
+
+       private long count;
+
+       private byte[] headerBuffer = new byte[32];
+
+       private byte[] copyBuffer;
+
+       PackOutputStream(final OutputStream out, final boolean ofsDelta) {
+               this.out = out;
+               this.ofsDelta = ofsDelta;
+       }
+
+       @Override
+       public void write(final int b) throws IOException {
+               count++;
+               out.write(b);
+               crc.update(b);
+               md.update((byte) b);
+       }
+
+       @Override
+       public void write(final byte[] b, final int off, final int len)
+                       throws IOException {
+               count += len;
+               out.write(b, off, len);
+               crc.update(b, off, len);
+               md.update(b, off, len);
+       }
+
+       @Override
+       public void flush() throws IOException {
+               out.flush();
+       }
+
+       void writeFileHeader(int version, int objectCount) throws IOException {
+               System.arraycopy(Constants.PACK_SIGNATURE, 0, headerBuffer, 0, 4);
+               NB.encodeInt32(headerBuffer, 4, version);
+               NB.encodeInt32(headerBuffer, 8, objectCount);
+               write(headerBuffer, 0, 12);
+       }
+
+       /**
+        * Commits the object header onto the stream.
+        * <p>
+        * Once the header has been written, the object representation must be fully
+        * output, or packing must abort abnormally.
+        *
+        * @param otp
+        *            the object to pack. Header information is obtained.
+        * @param rawLength
+        *            number of bytes of the inflated content. For an object that is
+        *            in whole object format, this is the same as the object size.
+        *            For an object that is in a delta format, this is the size of
+        *            the inflated delta instruction stream.
+        * @throws IOException
+        *             the underlying stream refused to accept the header.
+        */
+       public void writeHeader(ObjectToPack otp, long rawLength)
+                       throws IOException {
+               if (otp.isDeltaRepresentation()) {
+                       if (ofsDelta) {
+                               ObjectToPack baseInPack = otp.getDeltaBase();
+                               if (baseInPack != null && baseInPack.isWritten()) {
+                                       final long start = count;
+                                       int n = encodeTypeSize(Constants.OBJ_OFS_DELTA, rawLength);
+                                       write(headerBuffer, 0, n);
+
+                                       long offsetDiff = start - baseInPack.getOffset();
+                                       n = headerBuffer.length - 1;
+                                       headerBuffer[n] = (byte) (offsetDiff & 0x7F);
+                                       while ((offsetDiff >>= 7) > 0)
+                                               headerBuffer[--n] = (byte) (0x80 | (--offsetDiff & 0x7F));
+                                       write(headerBuffer, n, headerBuffer.length - n);
+                                       return;
+                               }
+                       }
+
+                       int n = encodeTypeSize(Constants.OBJ_REF_DELTA, rawLength);
+                       otp.getDeltaBaseId().copyRawTo(headerBuffer, n);
+                       write(headerBuffer, 0, n + Constants.OBJECT_ID_LENGTH);
+               } else {
+                       int n = encodeTypeSize(otp.getType(), rawLength);
+                       write(headerBuffer, 0, n);
+               }
+       }
+
+       private int encodeTypeSize(int type, long rawLength) {
+               long nextLength = rawLength >>> 4;
+               headerBuffer[0] = (byte) ((nextLength > 0 ? 0x80 : 0x00)
+                               | (type << 4) | (rawLength & 0x0F));
+               rawLength = nextLength;
+               int n = 1;
+               while (rawLength > 0) {
+                       nextLength >>>= 7;
+                       headerBuffer[n++] = (byte) ((nextLength > 0 ? 0x80 : 0x00) | (rawLength & 0x7F));
+                       rawLength = nextLength;
+               }
+               return n;
+       }
+
+       /** @return a temporary buffer writers can use to copy data with. */
+       public byte[] getCopyBuffer() {
+               if (copyBuffer == null)
+                       copyBuffer = new byte[16 * 1024];
+               return copyBuffer;
+       }
+
+       /** @return total number of bytes written since stream start. */
+       long length() {
+               return count;
+       }
+
+       /** @return obtain the current CRC32 register. */
+       int getCRC32() {
+               return (int) crc.getValue();
+       }
+
+       /** Reinitialize the CRC32 register for a new region. */
+       void resetCRC32() {
+               crc.reset();
+       }
+
+       /** @return obtain the current SHA-1 digest. */
+       byte[] getDigest() {
+               return md.digest();
+       }
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/PackWriter.java b/org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/PackWriter.java
new file mode 100644 (file)
index 0000000..031ea2b
--- /dev/null
@@ -0,0 +1,891 @@
+/*
+ * Copyright (C) 2008-2010, Google Inc.
+ * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com>
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ *   copyright notice, this list of conditions and the following
+ *   disclaimer in the documentation and/or other materials provided
+ *   with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ *   names of its contributors may be used to endorse or promote
+ *   products derived from this software without specific prior
+ *   written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.eclipse.jgit.storage.pack;
+
+import static org.eclipse.jgit.storage.pack.StoredObjectRepresentation.PACK_DELTA;
+import static org.eclipse.jgit.storage.pack.StoredObjectRepresentation.PACK_WHOLE;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.security.MessageDigest;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.zip.Deflater;
+
+import org.eclipse.jgit.JGitText;
+import org.eclipse.jgit.errors.CorruptObjectException;
+import org.eclipse.jgit.errors.IncorrectObjectTypeException;
+import org.eclipse.jgit.errors.MissingObjectException;
+import org.eclipse.jgit.errors.StoredObjectRepresentationNotAvailableException;
+import org.eclipse.jgit.lib.AnyObjectId;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.CoreConfig;
+import org.eclipse.jgit.lib.NullProgressMonitor;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.ObjectIdSubclassMap;
+import org.eclipse.jgit.lib.ObjectLoader;
+import org.eclipse.jgit.lib.ObjectReader;
+import org.eclipse.jgit.lib.ProgressMonitor;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.revwalk.ObjectWalk;
+import org.eclipse.jgit.revwalk.RevFlag;
+import org.eclipse.jgit.revwalk.RevObject;
+import org.eclipse.jgit.revwalk.RevSort;
+import org.eclipse.jgit.storage.file.PackIndexWriter;
+
+/**
+ * <p>
+ * PackWriter class is responsible for generating pack files from specified set
+ * of objects from repository. This implementation produce pack files in format
+ * version 2.
+ * </p>
+ * <p>
+ * Source of objects may be specified in two ways:
+ * <ul>
+ * <li>(usually) by providing sets of interesting and uninteresting objects in
+ * repository - all interesting objects and their ancestors except uninteresting
+ * objects and their ancestors will be included in pack, or</li>
+ * <li>by providing iterator of {@link RevObject} specifying exact list and
+ * order of objects in pack</li>
+ * </ul>
+ * Typical usage consists of creating instance intended for some pack,
+ * configuring options, preparing the list of objects by calling
+ * {@link #preparePack(Iterator)} or
+ * {@link #preparePack(Collection, Collection)}, and finally
+ * producing the stream with {@link #writePack(OutputStream)}.
+ * </p>
+ * <p>
+ * Class provide set of configurable options and {@link ProgressMonitor}
+ * support, as operations may take a long time for big repositories. Deltas
+ * searching algorithm is <b>NOT IMPLEMENTED</b> yet - this implementation
+ * relies only on deltas and objects reuse.
+ * </p>
+ * <p>
+ * This class is not thread safe, it is intended to be used in one thread, with
+ * one instance per created pack. Subsequent calls to writePack result in
+ * undefined behavior.
+ * </p>
+ */
+public class PackWriter {
+       /**
+        * Title of {@link ProgressMonitor} task used during counting objects to
+        * pack.
+        *
+        * @see #preparePack(Collection, Collection)
+        */
+       public static final String COUNTING_OBJECTS_PROGRESS = JGitText.get().countingObjects;
+
+       /**
+        * Title of {@link ProgressMonitor} task used during searching for objects
+        * reuse or delta reuse.
+        *
+        * @see #writePack(OutputStream)
+        */
+       public static final String SEARCHING_REUSE_PROGRESS = JGitText.get().compressingObjects;
+
+       /**
+        * Title of {@link ProgressMonitor} task used during writing out pack
+        * (objects)
+        *
+        * @see #writePack(OutputStream)
+        */
+       public static final String WRITING_OBJECTS_PROGRESS = JGitText.get().writingObjects;
+
+       /**
+        * Default value of deltas reuse option.
+        *
+        * @see #setReuseDeltas(boolean)
+        */
+       public static final boolean DEFAULT_REUSE_DELTAS = true;
+
+       /**
+        * Default value of objects reuse option.
+        *
+        * @see #setReuseObjects(boolean)
+        */
+       public static final boolean DEFAULT_REUSE_OBJECTS = true;
+
+       /**
+        * Default value of delta base as offset option.
+        *
+        * @see #setDeltaBaseAsOffset(boolean)
+        */
+       public static final boolean DEFAULT_DELTA_BASE_AS_OFFSET = false;
+
+       /**
+        * Default value of maximum delta chain depth.
+        *
+        * @see #setMaxDeltaDepth(int)
+        */
+       public static final int DEFAULT_MAX_DELTA_DEPTH = 50;
+
+       private static final int PACK_VERSION_GENERATED = 2;
+
+       @SuppressWarnings("unchecked")
+       private final List<ObjectToPack> objectsLists[] = new List[Constants.OBJ_TAG + 1];
+       {
+               objectsLists[0] = Collections.<ObjectToPack> emptyList();
+               objectsLists[Constants.OBJ_COMMIT] = new ArrayList<ObjectToPack>();
+               objectsLists[Constants.OBJ_TREE] = new ArrayList<ObjectToPack>();
+               objectsLists[Constants.OBJ_BLOB] = new ArrayList<ObjectToPack>();
+               objectsLists[Constants.OBJ_TAG] = new ArrayList<ObjectToPack>();
+       }
+
+       private final ObjectIdSubclassMap<ObjectToPack> objectsMap = new ObjectIdSubclassMap<ObjectToPack>();
+
+       // edge objects for thin packs
+       private final ObjectIdSubclassMap<ObjectId> edgeObjects = new ObjectIdSubclassMap<ObjectId>();
+
+       private final Repository db;
+
+       private PackOutputStream out;
+
+       private final Deflater deflater;
+
+       private ProgressMonitor initMonitor;
+
+       private ProgressMonitor writeMonitor;
+
+       private final ObjectReader reader;
+
+       /** {@link #reader} recast to the reuse interface, if it supports it. */
+       private final ObjectReuseAsIs reuseSupport;
+
+       private List<ObjectToPack> sortedByName;
+
+       private byte packcsum[];
+
+       private boolean reuseDeltas = DEFAULT_REUSE_DELTAS;
+
+       private boolean reuseObjects = DEFAULT_REUSE_OBJECTS;
+
+       private boolean deltaBaseAsOffset = DEFAULT_DELTA_BASE_AS_OFFSET;
+
+       private int maxDeltaDepth = DEFAULT_MAX_DELTA_DEPTH;
+
+       private int outputVersion;
+
+       private boolean thin;
+
+       private boolean ignoreMissingUninteresting = true;
+
+       /**
+        * Create writer for specified repository.
+        * <p>
+        * Objects for packing are specified in {@link #preparePack(Iterator)} or
+        * {@link #preparePack(Collection, Collection)}.
+        *
+        * @param repo
+        *            repository where objects are stored.
+        * @param monitor
+        *            operations progress monitor, used within
+        *            {@link #preparePack(Iterator)},
+        *            {@link #preparePack(Collection, Collection)}
+        *            , or {@link #writePack(OutputStream)}.
+        */
+       public PackWriter(final Repository repo, final ProgressMonitor monitor) {
+               this(repo, monitor, monitor);
+       }
+
+       /**
+        * Create writer for specified repository.
+        * <p>
+        * Objects for packing are specified in {@link #preparePack(Iterator)} or
+        * {@link #preparePack(Collection, Collection)}.
+        *
+        * @param repo
+        *            repository where objects are stored.
+        * @param imonitor
+        *            operations progress monitor, used within
+        *            {@link #preparePack(Iterator)},
+        *            {@link #preparePack(Collection, Collection)}
+        * @param wmonitor
+        *            operations progress monitor, used within
+        *            {@link #writePack(OutputStream)}.
+        */
+       public PackWriter(final Repository repo, final ProgressMonitor imonitor,
+                       final ProgressMonitor wmonitor) {
+               this.db = repo;
+
+               reader = db.newObjectReader();
+               if (reader instanceof ObjectReuseAsIs)
+                       reuseSupport = ((ObjectReuseAsIs) reader);
+               else
+                       reuseSupport = null;
+
+               initMonitor = imonitor == null ? NullProgressMonitor.INSTANCE : imonitor;
+               writeMonitor = wmonitor == null ? NullProgressMonitor.INSTANCE : wmonitor;
+
+               final CoreConfig coreConfig = db.getConfig().get(CoreConfig.KEY);
+               this.deflater = new Deflater(coreConfig.getCompression());
+               outputVersion = coreConfig.getPackIndexVersion();
+       }
+
+       /**
+        * Check whether object is configured to reuse deltas existing in
+        * repository.
+        * <p>
+        * Default setting: {@value #DEFAULT_REUSE_DELTAS}
+        * </p>
+        *
+        * @return true if object is configured to reuse deltas; false otherwise.
+        */
+       public boolean isReuseDeltas() {
+               return reuseDeltas;
+       }
+
+       /**
+        * Set reuse deltas configuration option for this writer. When enabled,
+        * writer will search for delta representation of object in repository and
+        * use it if possible. Normally, only deltas with base to another object
+        * existing in set of objects to pack will be used. Exception is however
+        * thin-pack (see
+        * {@link #preparePack(Collection, Collection)} and
+        * {@link #preparePack(Iterator)}) where base object must exist on other
+        * side machine.
+        * <p>
+        * When raw delta data is directly copied from a pack file, checksum is
+        * computed to verify data.
+        * </p>
+        * <p>
+        * Default setting: {@value #DEFAULT_REUSE_DELTAS}
+        * </p>
+        *
+        * @param reuseDeltas
+        *            boolean indicating whether or not try to reuse deltas.
+        */
+       public void setReuseDeltas(boolean reuseDeltas) {
+               this.reuseDeltas = reuseDeltas;
+       }
+
+       /**
+        * Checks whether object is configured to reuse existing objects
+        * representation in repository.
+        * <p>
+        * Default setting: {@value #DEFAULT_REUSE_OBJECTS}
+        * </p>
+        *
+        * @return true if writer is configured to reuse objects representation from
+        *         pack; false otherwise.
+        */
+       public boolean isReuseObjects() {
+               return reuseObjects;
+       }
+
+       /**
+        * Set reuse objects configuration option for this writer. If enabled,
+        * writer searches for representation in a pack file. If possible,
+        * compressed data is directly copied from such a pack file. Data checksum
+        * is verified.
+        * <p>
+        * Default setting: {@value #DEFAULT_REUSE_OBJECTS}
+        * </p>
+        *
+        * @param reuseObjects
+        *            boolean indicating whether or not writer should reuse existing
+        *            objects representation.
+        */
+       public void setReuseObjects(boolean reuseObjects) {
+               this.reuseObjects = reuseObjects;
+       }
+
+       /**
+        * Check whether writer can store delta base as an offset (new style
+        * reducing pack size) or should store it as an object id (legacy style,
+        * compatible with old readers).
+        * <p>
+        * Default setting: {@value #DEFAULT_DELTA_BASE_AS_OFFSET}
+        * </p>
+        *
+        * @return true if delta base is stored as an offset; false if it is stored
+        *         as an object id.
+        */
+       public boolean isDeltaBaseAsOffset() {
+               return deltaBaseAsOffset;
+       }
+
+       /**
+        * Set writer delta base format. Delta base can be written as an offset in a
+        * pack file (new approach reducing file size) or as an object id (legacy
+        * approach, compatible with old readers).
+        * <p>
+        * Default setting: {@value #DEFAULT_DELTA_BASE_AS_OFFSET}
+        * </p>
+        *
+        * @param deltaBaseAsOffset
+        *            boolean indicating whether delta base can be stored as an
+        *            offset.
+        */
+       public void setDeltaBaseAsOffset(boolean deltaBaseAsOffset) {
+               this.deltaBaseAsOffset = deltaBaseAsOffset;
+       }
+
+       /**
+        * Get maximum depth of delta chain set up for this writer. Generated chains
+        * are not longer than this value.
+        * <p>
+        * Default setting: {@value #DEFAULT_MAX_DELTA_DEPTH}
+        * </p>
+        *
+        * @return maximum delta chain depth.
+        */
+       public int getMaxDeltaDepth() {
+               return maxDeltaDepth;
+       }
+
+       /**
+        * Set up maximum depth of delta chain for this writer. Generated chains are
+        * not longer than this value. Too low value causes low compression level,
+        * while too big makes unpacking (reading) longer.
+        * <p>
+        * Default setting: {@value #DEFAULT_MAX_DELTA_DEPTH}
+        * </p>
+        *
+        * @param maxDeltaDepth
+        *            maximum delta chain depth.
+        */
+       public void setMaxDeltaDepth(int maxDeltaDepth) {
+               this.maxDeltaDepth = maxDeltaDepth;
+       }
+
+       /** @return true if this writer is producing a thin pack. */
+       public boolean isThin() {
+               return thin;
+       }
+
+       /**
+        * @param packthin
+        *            a boolean indicating whether writer may pack objects with
+        *            delta base object not within set of objects to pack, but
+        *            belonging to party repository (uninteresting/boundary) as
+        *            determined by set; this kind of pack is used only for
+        *            transport; true - to produce thin pack, false - otherwise.
+        */
+       public void setThin(final boolean packthin) {
+               thin = packthin;
+       }
+
+       /**
+        * @return true to ignore objects that are uninteresting and also not found
+        *         on local disk; false to throw a {@link MissingObjectException}
+        *         out of {@link #preparePack(Collection, Collection)} if an
+        *         uninteresting object is not in the source repository. By default,
+        *         true, permitting gracefully ignoring of uninteresting objects.
+        */
+       public boolean isIgnoreMissingUninteresting() {
+               return ignoreMissingUninteresting;
+       }
+
+       /**
+        * @param ignore
+        *            true if writer should ignore non existing uninteresting
+        *            objects during construction set of objects to pack; false
+        *            otherwise - non existing uninteresting objects may cause
+        *            {@link MissingObjectException}
+        */
+       public void setIgnoreMissingUninteresting(final boolean ignore) {
+               ignoreMissingUninteresting = ignore;
+       }
+
+       /**
+        * Set the pack index file format version this instance will create.
+        *
+        * @param version
+        *            the version to write. The special version 0 designates the
+        *            oldest (most compatible) format available for the objects.
+        * @see PackIndexWriter
+        */
+       public void setIndexVersion(final int version) {
+               outputVersion = version;
+       }
+
+       /**
+        * Returns objects number in a pack file that was created by this writer.
+        *
+        * @return number of objects in pack.
+        */
+       public int getObjectsNumber() {
+               return objectsMap.size();
+       }
+
+       /**
+        * Prepare the list of objects to be written to the pack stream.
+        * <p>
+        * Iterator <b>exactly</b> determines which objects are included in a pack
+        * and order they appear in pack (except that objects order by type is not
+        * needed at input). This order should conform general rules of ordering
+        * objects in git - by recency and path (type and delta-base first is
+        * internally secured) and responsibility for guaranteeing this order is on
+        * a caller side. Iterator must return each id of object to write exactly
+        * once.
+        * </p>
+        * <p>
+        * When iterator returns object that has {@link RevFlag#UNINTERESTING} flag,
+        * this object won't be included in an output pack. Instead, it is recorded
+        * as edge-object (known to remote repository) for thin-pack. In such a case
+        * writer may pack objects with delta base object not within set of objects
+        * to pack, but belonging to party repository - those marked with
+        * {@link RevFlag#UNINTERESTING} flag. This type of pack is used only for
+        * transport.
+        * </p>
+        *
+        * @param objectsSource
+        *            iterator of object to store in a pack; order of objects within
+        *            each type is important, ordering by type is not needed;
+        *            allowed types for objects are {@link Constants#OBJ_COMMIT},
+        *            {@link Constants#OBJ_TREE}, {@link Constants#OBJ_BLOB} and
+        *            {@link Constants#OBJ_TAG}; objects returned by iterator may
+        *            be later reused by caller as object id and type are internally
+        *            copied in each iteration; if object returned by iterator has
+        *            {@link RevFlag#UNINTERESTING} flag set, it won't be included
+        *            in a pack, but is considered as edge-object for thin-pack.
+        * @throws IOException
+        *             when some I/O problem occur during reading objects.
+        */
+       public void preparePack(final Iterator<RevObject> objectsSource)
+                       throws IOException {
+               while (objectsSource.hasNext()) {
+                       addObject(objectsSource.next());
+               }
+       }
+
+       /**
+        * Prepare the list of objects to be written to the pack stream.
+        * <p>
+        * Basing on these 2 sets, another set of objects to put in a pack file is
+        * created: this set consists of all objects reachable (ancestors) from
+        * interesting objects, except uninteresting objects and their ancestors.
+        * This method uses class {@link ObjectWalk} extensively to find out that
+        * appropriate set of output objects and their optimal order in output pack.
+        * Order is consistent with general git in-pack rules: sort by object type,
+        * recency, path and delta-base first.
+        * </p>
+        *
+        * @param interestingObjects
+        *            collection of objects to be marked as interesting (start
+        *            points of graph traversal).
+        * @param uninterestingObjects
+        *            collection of objects to be marked as uninteresting (end
+        *            points of graph traversal).
+        * @throws IOException
+        *             when some I/O problem occur during reading objects.
+        */
+       public void preparePack(
+                       final Collection<? extends ObjectId> interestingObjects,
+                       final Collection<? extends ObjectId> uninterestingObjects)
+                       throws IOException {
+               ObjectWalk walker = setUpWalker(interestingObjects,
+                               uninterestingObjects);
+               findObjectsToPack(walker);
+       }
+
+       /**
+        * Determine if the pack file will contain the requested object.
+        *
+        * @param id
+        *            the object to test the existence of.
+        * @return true if the object will appear in the output pack file.
+        */
+       public boolean willInclude(final AnyObjectId id) {
+               return objectsMap.get(id) != null;
+       }
+
+       /**
+        * Computes SHA-1 of lexicographically sorted objects ids written in this
+        * pack, as used to name a pack file in repository.
+        *
+        * @return ObjectId representing SHA-1 name of a pack that was created.
+        */
+       public ObjectId computeName() {
+               final byte[] buf = new byte[Constants.OBJECT_ID_LENGTH];
+               final MessageDigest md = Constants.newMessageDigest();
+               for (ObjectToPack otp : sortByName()) {
+                       otp.copyRawTo(buf, 0);
+                       md.update(buf, 0, Constants.OBJECT_ID_LENGTH);
+               }
+               return ObjectId.fromRaw(md.digest());
+       }
+
+       /**
+        * Create an index file to match the pack file just written.
+        * <p>
+        * This method can only be invoked after {@link #preparePack(Iterator)} or
+        * {@link #preparePack(Collection, Collection)} has been
+        * invoked and completed successfully. Writing a corresponding index is an
+        * optional feature that not all pack users may require.
+        *
+        * @param indexStream
+        *            output for the index data. Caller is responsible for closing
+        *            this stream.
+        * @throws IOException
+        *             the index data could not be written to the supplied stream.
+        */
+       public void writeIndex(final OutputStream indexStream) throws IOException {
+               final List<ObjectToPack> list = sortByName();
+               final PackIndexWriter iw;
+               if (outputVersion <= 0)
+                       iw = PackIndexWriter.createOldestPossible(indexStream, list);
+               else
+                       iw = PackIndexWriter.createVersion(indexStream, outputVersion);
+               iw.write(list, packcsum);
+       }
+
+       private List<ObjectToPack> sortByName() {
+               if (sortedByName == null) {
+                       sortedByName = new ArrayList<ObjectToPack>(objectsMap.size());
+                       for (List<ObjectToPack> list : objectsLists) {
+                               for (ObjectToPack otp : list)
+                                       sortedByName.add(otp);
+                       }
+                       Collections.sort(sortedByName);
+               }
+               return sortedByName;
+       }
+
+       /**
+        * Write the prepared pack to the supplied stream.
+        * <p>
+        * At first, this method collects and sorts objects to pack, then deltas
+        * search is performed if set up accordingly, finally pack stream is
+        * written. {@link ProgressMonitor} tasks {@value #SEARCHING_REUSE_PROGRESS}
+        * (only if reuseDeltas or reuseObjects is enabled) and
+        * {@value #WRITING_OBJECTS_PROGRESS} are updated during packing.
+        * </p>
+        * <p>
+        * All reused objects data checksum (Adler32/CRC32) is computed and
+        * validated against existing checksum.
+        * </p>
+        *
+        * @param packStream
+        *            output stream of pack data. The stream should be buffered by
+        *            the caller. The caller is responsible for closing the stream.
+        * @throws IOException
+        *             an error occurred reading a local object's data to include in
+        *             the pack, or writing compressed object data to the output
+        *             stream.
+        */
+       public void writePack(OutputStream packStream) throws IOException {
+               if ((reuseDeltas || reuseObjects) && reuseSupport != null)
+                       searchForReuse();
+
+               out = new PackOutputStream(packStream, isDeltaBaseAsOffset());
+
+               writeMonitor.beginTask(WRITING_OBJECTS_PROGRESS, getObjectsNumber());
+               out.writeFileHeader(PACK_VERSION_GENERATED, getObjectsNumber());
+               writeObjects();
+               writeChecksum();
+
+               out = null;
+               reader.release();
+               writeMonitor.endTask();
+       }
+
+       private void searchForReuse() throws IOException {
+               initMonitor.beginTask(SEARCHING_REUSE_PROGRESS, getObjectsNumber());
+               for (List<ObjectToPack> list : objectsLists) {
+                       for (ObjectToPack otp : list) {
+                               if (initMonitor.isCancelled())
+                                       throw new IOException(
+                                                       JGitText.get().packingCancelledDuringObjectsWriting);
+                               reuseSupport.selectObjectRepresentation(this, otp);
+                               initMonitor.update(1);
+                       }
+               }
+               initMonitor.endTask();
+       }
+
+       private void writeObjects() throws IOException {
+               for (List<ObjectToPack> list : objectsLists) {
+                       for (ObjectToPack otp : list) {
+                               if (writeMonitor.isCancelled())
+                                       throw new IOException(
+                                                       JGitText.get().packingCancelledDuringObjectsWriting);
+                               if (!otp.isWritten())
+                                       writeObject(otp);
+                       }
+               }
+       }
+
+       private void writeObject(final ObjectToPack otp) throws IOException {
+               if (otp.isWritten())
+                       return; // We shouldn't be here.
+
+               otp.markWantWrite();
+               if (otp.isDeltaRepresentation())
+                       writeBaseFirst(otp);
+
+               out.resetCRC32();
+               otp.setOffset(out.length());
+
+               while (otp.isReuseAsIs()) {
+                       try {
+                               reuseSupport.copyObjectAsIs(out, otp);
+                               otp.setCRC(out.getCRC32());
+                               writeMonitor.update(1);
+                               return;
+                       } catch (StoredObjectRepresentationNotAvailableException gone) {
+                               if (otp.getOffset() == out.length()) {
+                                       redoSearchForReuse(otp);
+                                       continue;
+                               } else {
+                                       // Object writing already started, we cannot recover.
+                                       //
+                                       CorruptObjectException coe;
+                                       coe = new CorruptObjectException(otp, "");
+                                       coe.initCause(gone);
+                                       throw coe;
+                               }
+                       }
+               }
+
+               // If we reached here, reuse wasn't possible.
+               //
+               writeWholeObjectDeflate(otp);
+               otp.setCRC(out.getCRC32());
+               writeMonitor.update(1);
+       }
+
+       private void writeBaseFirst(final ObjectToPack otp) throws IOException {
+               ObjectToPack baseInPack = otp.getDeltaBase();
+               if (baseInPack != null) {
+                       if (!baseInPack.isWritten()) {
+                               if (baseInPack.wantWrite()) {
+                                       // There is a cycle. Our caller is trying to write the
+                                       // object we want as a base, and called us. Turn off
+                                       // delta reuse so we can find another form.
+                                       //
+                                       reuseDeltas = false;
+                                       redoSearchForReuse(otp);
+                                       reuseDeltas = true;
+                               } else {
+                                       writeObject(baseInPack);
+                               }
+                       }
+               } else if (!thin) {
+                       // This should never occur, the base isn't in the pack and
+                       // the pack isn't allowed to reference base outside objects.
+                       // Write the object as a whole form, even if that is slow.
+                       //
+                       otp.clearDeltaBase();
+                       otp.clearReuseAsIs();
+               }
+       }
+
+       private void redoSearchForReuse(final ObjectToPack otp) throws IOException,
+                       MissingObjectException {
+               otp.clearDeltaBase();
+               otp.clearReuseAsIs();
+               reuseSupport.selectObjectRepresentation(this, otp);
+       }
+
+       private void writeWholeObjectDeflate(final ObjectToPack otp)
+                       throws IOException {
+               final ObjectLoader loader = db.openObject(reader, otp);
+               final byte[] data = loader.getCachedBytes();
+               out.writeHeader(otp, data.length);
+               deflater.reset();
+               deflater.setInput(data, 0, data.length);
+               deflater.finish();
+
+               byte[] buf = out.getCopyBuffer();
+               do {
+                       final int n = deflater.deflate(buf, 0, buf.length);
+                       if (n > 0)
+                               out.write(buf, 0, n);
+               } while (!deflater.finished());
+       }
+
+       private void writeChecksum() throws IOException {
+               packcsum = out.getDigest();
+               out.write(packcsum);
+       }
+
+       private ObjectWalk setUpWalker(
+                       final Collection<? extends ObjectId> interestingObjects,
+                       final Collection<? extends ObjectId> uninterestingObjects)
+                       throws MissingObjectException, IOException,
+                       IncorrectObjectTypeException {
+               final ObjectWalk walker = new ObjectWalk(db);
+               walker.setRetainBody(false);
+               walker.sort(RevSort.COMMIT_TIME_DESC);
+               if (thin)
+                       walker.sort(RevSort.BOUNDARY, true);
+
+               for (ObjectId id : interestingObjects) {
+                       RevObject o = walker.parseAny(id);
+                       walker.markStart(o);
+               }
+               if (uninterestingObjects != null) {
+                       for (ObjectId id : uninterestingObjects) {
+                               final RevObject o;
+                               try {
+                                       o = walker.parseAny(id);
+                               } catch (MissingObjectException x) {
+                                       if (ignoreMissingUninteresting)
+                                               continue;
+                                       throw x;
+                               }
+                               walker.markUninteresting(o);
+                       }
+               }
+               return walker;
+       }
+
+       private void findObjectsToPack(final ObjectWalk walker)
+                       throws MissingObjectException, IncorrectObjectTypeException,
+                       IOException {
+               initMonitor.beginTask(COUNTING_OBJECTS_PROGRESS,
+                               ProgressMonitor.UNKNOWN);
+               RevObject o;
+
+               while ((o = walker.next()) != null) {
+                       addObject(o);
+                       initMonitor.update(1);
+               }
+               while ((o = walker.nextObject()) != null) {
+                       addObject(o);
+                       initMonitor.update(1);
+               }
+               initMonitor.endTask();
+       }
+
+       /**
+        * Include one object to the output file.
+        * <p>
+        * Objects are written in the order they are added. If the same object is
+        * added twice, it may be written twice, creating a larger than necessary
+        * file.
+        *
+        * @param object
+        *            the object to add.
+        * @throws IncorrectObjectTypeException
+        *             the object is an unsupported type.
+        */
+       public void addObject(final RevObject object)
+                       throws IncorrectObjectTypeException {
+               if (object.has(RevFlag.UNINTERESTING)) {
+                       edgeObjects.add(object);
+                       thin = true;
+                       return;
+               }
+
+               final ObjectToPack otp;
+               if (reuseSupport != null)
+                       otp = reuseSupport.newObjectToPack(object);
+               else
+                       otp = new ObjectToPack(object);
+               try {
+                       objectsLists[object.getType()].add(otp);
+               } catch (ArrayIndexOutOfBoundsException x) {
+                       throw new IncorrectObjectTypeException(object,
+                                       JGitText.get().incorrectObjectType_COMMITnorTREEnorBLOBnorTAG);
+               } catch (UnsupportedOperationException x) {
+                       // index pointing to "dummy" empty list
+                       throw new IncorrectObjectTypeException(object,
+                                       JGitText.get().incorrectObjectType_COMMITnorTREEnorBLOBnorTAG);
+               }
+               objectsMap.add(otp);
+       }
+
+       /**
+        * Select an object representation for this writer.
+        * <p>
+        * An {@link ObjectReader} implementation should invoke this method once for
+        * each representation available for an object, to allow the writer to find
+        * the most suitable one for the output.
+        *
+        * @param otp
+        *            the object being packed.
+        * @param next
+        *            the next available representation from the repository.
+        */
+       public void select(ObjectToPack otp, StoredObjectRepresentation next) {
+               int nFmt = next.getFormat();
+               int nWeight;
+               if (otp.isReuseAsIs()) {
+                       // We've already chosen to reuse a packed form, if next
+                       // cannot beat that break out early.
+                       //
+                       if (PACK_WHOLE < nFmt)
+                               return; // next isn't packed
+                       else if (PACK_DELTA < nFmt && otp.isDeltaRepresentation())
+                               return; // next isn't a delta, but we are
+
+                       nWeight = next.getWeight();
+                       if (otp.getWeight() <= nWeight)
+                               return; // next would be bigger
+               } else
+                       nWeight = next.getWeight();
+
+               if (nFmt == PACK_DELTA && reuseDeltas) {
+                       ObjectId baseId = next.getDeltaBase();
+                       ObjectToPack ptr = objectsMap.get(baseId);
+                       if (ptr != null) {
+                               otp.setDeltaBase(ptr);
+                               otp.setReuseAsIs();
+                               otp.setWeight(nWeight);
+                       } else if (thin && edgeObjects.contains(baseId)) {
+                               otp.setDeltaBase(baseId);
+                               otp.setReuseAsIs();
+                               otp.setWeight(nWeight);
+                       } else {
+                               otp.clearDeltaBase();
+                               otp.clearReuseAsIs();
+                       }
+               } else if (nFmt == PACK_WHOLE && reuseObjects) {
+                       otp.clearDeltaBase();
+                       otp.setReuseAsIs();
+                       otp.setWeight(nWeight);
+               } else {
+                       otp.clearDeltaBase();
+                       otp.clearReuseAsIs();
+               }
+
+               otp.select(next);
+       }
+}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/StoredObjectRepresentation.java b/org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/StoredObjectRepresentation.java
new file mode 100644 (file)
index 0000000..334ea5e
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2010, Google Inc.
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ *   copyright notice, this list of conditions and the following
+ *   disclaimer in the documentation and/or other materials provided
+ *   with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ *   names of its contributors may be used to endorse or promote
+ *   products derived from this software without specific prior
+ *   written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.eclipse.jgit.storage.pack;
+
+import org.eclipse.jgit.lib.ObjectId;
+
+/**
+ * An object representation {@link PackWriter} can consider for packing.
+ */
+public class StoredObjectRepresentation {
+       /** Special unknown value for {@link #getWeight()}. */
+       public static final int WEIGHT_UNKNOWN = Integer.MAX_VALUE;
+
+       /** Stored in pack format, as a delta to another object. */
+       public static final int PACK_DELTA = 0;
+
+       /** Stored in pack format, without delta. */
+       public static final int PACK_WHOLE = 1;
+
+       /** Only available after inflating to canonical format. */
+       public static final int FORMAT_OTHER = 2;
+
+       /**
+        * @return relative size of this object's packed form. The special value
+        *         {@link #WEIGHT_UNKNOWN} can be returned to indicate the
+        *         implementation doesn't know, or cannot supply the weight up
+        *         front.
+        */
+       public int getWeight() {
+               return WEIGHT_UNKNOWN;
+       }
+
+       /**
+        * @return true if this is a delta against another object and this is stored
+        *         in pack delta format.
+        */
+       public int getFormat() {
+               return FORMAT_OTHER;
+       }
+
+       /**
+        * @return identity of the object this delta applies to in order to recover
+        *         the original object content. This method should only be called if
+        *         {@link #getFormat()} returned {@link #PACK_DELTA}.
+        */
+       public ObjectId getDeltaBase() {
+               return null;
+       }
+}
index 44ccd2d6ad9923fe1164aa71a0532ed80cbbbfc4..72460c91cb468140727b5c5bc4b6aa9176768f4e 100644 (file)
@@ -56,9 +56,9 @@ import org.eclipse.jgit.errors.NotSupportedException;
 import org.eclipse.jgit.errors.PackProtocolException;
 import org.eclipse.jgit.errors.TransportException;
 import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.lib.PackWriter;
 import org.eclipse.jgit.lib.ProgressMonitor;
 import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.storage.pack.PackWriter;
 import org.eclipse.jgit.transport.RemoteRefUpdate.Status;
 
 /**
index 7e91557b09b364406d7a0a04dea4c525fda9ee99..c5e9baad54dc13a3b0fb7650648ee5e233191df3 100644 (file)
@@ -57,11 +57,11 @@ import org.eclipse.jgit.JGitText;
 import org.eclipse.jgit.lib.AnyObjectId;
 import org.eclipse.jgit.lib.Constants;
 import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.lib.PackWriter;
 import org.eclipse.jgit.lib.ProgressMonitor;
 import org.eclipse.jgit.lib.Ref;
 import org.eclipse.jgit.lib.Repository;
 import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.storage.pack.PackWriter;
 
 /**
  * Creates a Git bundle file, for sneaker-net transport to another system.
index 5a37825ceaee6ba740e58623e9aae54459d40f53..ade9ffed819eade10b836105128e60e7be3db49a 100644 (file)
@@ -65,7 +65,6 @@ import org.eclipse.jgit.JGitText;
 import org.eclipse.jgit.errors.CorruptObjectException;
 import org.eclipse.jgit.errors.MissingObjectException;
 import org.eclipse.jgit.lib.AnyObjectId;
-import org.eclipse.jgit.lib.BinaryDelta;
 import org.eclipse.jgit.lib.Constants;
 import org.eclipse.jgit.lib.CoreConfig;
 import org.eclipse.jgit.lib.InflaterCache;
@@ -80,6 +79,7 @@ import org.eclipse.jgit.lib.Repository;
 import org.eclipse.jgit.lib.ObjectReader;
 import org.eclipse.jgit.storage.file.PackIndexWriter;
 import org.eclipse.jgit.storage.file.PackLock;
+import org.eclipse.jgit.storage.pack.BinaryDelta;
 import org.eclipse.jgit.util.NB;
 
 /** Indexes Git pack files for local use. */
index 712ad3ff7540340028e7e43ec7994af99bed9017..17c37cf5b7a1d620b888400ccc11c627fb87d027 100644 (file)
@@ -60,7 +60,6 @@ import org.eclipse.jgit.errors.MissingObjectException;
 import org.eclipse.jgit.errors.PackProtocolException;
 import org.eclipse.jgit.lib.NullProgressMonitor;
 import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.lib.PackWriter;
 import org.eclipse.jgit.lib.ProgressMonitor;
 import org.eclipse.jgit.lib.Ref;
 import org.eclipse.jgit.lib.Repository;
@@ -70,6 +69,7 @@ import org.eclipse.jgit.revwalk.RevFlagSet;
 import org.eclipse.jgit.revwalk.RevObject;
 import org.eclipse.jgit.revwalk.RevTag;
 import org.eclipse.jgit.revwalk.RevWalk;
+import org.eclipse.jgit.storage.pack.PackWriter;
 import org.eclipse.jgit.transport.BasePackFetchConnection.MultiAck;
 import org.eclipse.jgit.transport.RefAdvertiser.PacketLineOutRefAdvertiser;
 import org.eclipse.jgit.util.io.InterruptTimer;
index 0edf9678e4a4df2a9aeccbfca7a85fd5a948f2a5..1ab6081c096f9ce9a218177c58fc5e4219dd4830 100644 (file)
@@ -61,12 +61,12 @@ import org.eclipse.jgit.lib.AnyObjectId;
 import org.eclipse.jgit.lib.Constants;
 import org.eclipse.jgit.lib.ObjectId;
 import org.eclipse.jgit.lib.ObjectIdRef;
-import org.eclipse.jgit.lib.PackWriter;
 import org.eclipse.jgit.lib.ProgressMonitor;
 import org.eclipse.jgit.lib.Ref;
 import org.eclipse.jgit.lib.RefWriter;
 import org.eclipse.jgit.lib.Repository;
 import org.eclipse.jgit.lib.Ref.Storage;
+import org.eclipse.jgit.storage.pack.PackWriter;
 import org.eclipse.jgit.transport.RemoteRefUpdate.Status;
 
 /**