{"thread":{"id":"14113","subject":"[JGIT PATCH 00/10] Support writing pack index version 2","startedAt":"2008-06-24T02:09:58Z","lastAt":"2008-06-25T04:01:48Z","messageCount":14,"participants":["Shawn O. Pearce","Robin Rosenberg"],"isPatch":true,"patchVersion":1,"patchTotal":10},"messages":[{"id":"80807","messageId":"1214273408-70793-1-git-send-email-spearce@spearce.org","threadId":"14113","inReplyTo":null,"subject":"[JGIT PATCH 00/10] Support writing pack index version 2","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2008-06-24T02:09:58Z","receivedAt":"2008-06-24T02:09:58Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"This series adds support for writing pack index v2 formatted files\nout of IndexPack, and thus any pack we fetch over the network.  It\nalso abstracts out the index formatting functions so we can reuse\nthem efficiently inside of PackWriter to support creating packs on\nthe local disk, or to upload packs directly over a dumb transport.\n\nI started down this path because we're missing index v2 support and\nthat is likely to become a default in the near future for C Git,\nand because I want to support push over sftp style URLs now that\nMarek has a pack writing implementation.\n\n----\n\nThe following changes since commit 535041bba0836a3488fbd465adb171a2c70c9415:\n  Florian Koeberle (1):\n        Added the package fnmatch and two exceptions.\n\nare available in the git repository at:\n\n  repo.or.cz:/srv/git/egit/spearce.git index-v2\n\nShawn O. Pearce (10):\n      Extract inner ObjectEntry from IndexPack class\n      Make ObjectEntry's position field private\n      Rename ObjectEntry to PackedObjectInfo\n      Document PackedObjectInfo and make it public for reuse\n      Refactor pack index writing to a common API\n      Reuse the magic tOc constant for pack index headers\n      Add 64 bit network byte order encoding to NB\n      Compute packed object entry CRC32 data during IndexPack\n      Add support for writing pack index v2 files\n      Default IndexPack to honor pack.indexversion configuration\n\n .../src/org/spearce/jgit/lib/CoreConfig.java       |   11 +\n .../src/org/spearce/jgit/lib/PackIndex.java        |    3 +-\n .../src/org/spearce/jgit/lib/PackIndexWriter.java  |  267 ++++++++++++++++++++\n .../org/spearce/jgit/lib/PackIndexWriterV1.java    |   78 ++++++\n .../org/spearce/jgit/lib/PackIndexWriterV2.java    |  101 ++++++++\n .../src/org/spearce/jgit/pgm/IndexPack.java        |    4 +\n .../src/org/spearce/jgit/transport/IndexPack.java  |  225 ++++++++++-------\n .../spearce/jgit/transport/PackedObjectInfo.java   |  109 ++++++++\n org.spearce.jgit/src/org/spearce/jgit/util/NB.java |   37 +++\n 9 files changed, 743 insertions(+), 92 deletions(-)\n create mode 100644 org.spearce.jgit/src/org/spearce/jgit/lib/PackIndexWriter.java\n create mode 100644 org.spearce.jgit/src/org/spearce/jgit/lib/PackIndexWriterV1.java\n create mode 100644 org.spearce.jgit/src/org/spearce/jgit/lib/PackIndexWriterV2.java\n create mode 100644 org.spearce.jgit/src/org/spearce/jgit/transport/PackedObjectInfo.java\n"},{"id":"80808","messageId":"1214273408-70793-2-git-send-email-spearce@spearce.org","threadId":"14113","inReplyTo":"1214273408-70793-1-git-send-email-spearce@spearce.org","subject":"[JGIT PATCH 01/10] Extract inner ObjectEntry from IndexPack class","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2008-06-24T02:09:59Z","receivedAt":"2008-06-24T02:09:59Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"This type is useful not just for IndexPack but also for PackWriter\nas it is essentially the index record (ObjectId and offset).  Both\ndata items are necessary to compute a valid index record, so we can\nunify the index writing code if we have a common type.\n\nSigned-off-by: Shawn O. Pearce <spearce@spearce.org>\n---\n .../src/org/spearce/jgit/transport/IndexPack.java  |   10 ----\n .../org/spearce/jgit/transport/ObjectEntry.java    |   51 ++++++++++++++++++++\n 2 files changed, 51 insertions(+), 10 deletions(-)\n create mode 100644 org.spearce.jgit/src/org/spearce/jgit/transport/ObjectEntry.java\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/transport/IndexPack.java b/org.spearce.jgit/src/org/spearce/jgit/transport/IndexPack.java\nindex bec211c..e182cfc 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/transport/IndexPack.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/transport/IndexPack.java\n@@ -54,7 +54,6 @@ import java.util.zip.Deflater;\n import java.util.zip.Inflater;\n \n import org.spearce.jgit.errors.CorruptObjectException;\n-import org.spearce.jgit.lib.AnyObjectId;\n import org.spearce.jgit.lib.BinaryDelta;\n import org.spearce.jgit.lib.Constants;\n import org.spearce.jgit.lib.InflaterCache;\n@@ -715,15 +714,6 @@ public class IndexPack {\n \t\t\t\t+ dfe.getMessage());\n \t}\n \n-\tprivate static class ObjectEntry extends ObjectId {\n-\t\tfinal long pos;\n-\n-\t\tObjectEntry(final long headerOffset, final AnyObjectId id) {\n-\t\t\tsuper(id);\n-\t\t\tpos = headerOffset;\n-\t\t}\n-\t}\n-\n \tprivate static class UnresolvedDelta {\n \t\tfinal long position;\n \ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/transport/ObjectEntry.java b/org.spearce.jgit/src/org/spearce/jgit/transport/ObjectEntry.java\nnew file mode 100644\nindex 0000000..58d2eb2\n--- /dev/null\n+++ b/org.spearce.jgit/src/org/spearce/jgit/transport/ObjectEntry.java\n@@ -0,0 +1,51 @@\n+/*\n+ * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>\n+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>\n+ *\n+ * All rights reserved.\n+ *\n+ * Redistribution and use in source and binary forms, with or\n+ * without modification, are permitted provided that the following\n+ * conditions are met:\n+ *\n+ * - Redistributions of source code must retain the above copyright\n+ *   notice, this list of conditions and the following disclaimer.\n+ *\n+ * - Redistributions in binary form must reproduce the above\n+ *   copyright notice, this list of conditions and the following\n+ *   disclaimer in the documentation and/or other materials provided\n+ *   with the distribution.\n+ *\n+ * - Neither the name of the Git Development Community nor the\n+ *   names of its contributors may be used to endorse or promote\n+ *   products derived from this software without specific prior\n+ *   written permission.\n+ *\n+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND\n+ * CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES,\n+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\n+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+package org.spearce.jgit.transport;\n+\n+import org.spearce.jgit.lib.AnyObjectId;\n+import org.spearce.jgit.lib.ObjectId;\n+\n+class ObjectEntry extends ObjectId {\n+\tfinal long pos;\n+\n+\tObjectEntry(final long headerOffset, final AnyObjectId id) {\n+\t\tsuper(id);\n+\t\tpos = headerOffset;\n+\t}\n+}\n-- \n1.5.6.74.g8a5e\n"},{"id":"80809","messageId":"1214273408-70793-3-git-send-email-spearce@spearce.org","threadId":"14113","inReplyTo":"1214273408-70793-2-git-send-email-spearce@spearce.org","subject":"[JGIT PATCH 02/10] Make ObjectEntry's position field private","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2008-06-24T02:10:00Z","receivedAt":"2008-06-24T02:10:00Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"PackWriter calls this getOffset() and hides the field as a private\nfield as part of its related ObjectToPack class.  We do that here\nas part of ObjectEntry's API so we can later replace that part of\nObjectToPack by inheriting from ObjectEntry.\n\nSigned-off-by: Shawn O. Pearce <spearce@spearce.org>\n---\n .../src/org/spearce/jgit/transport/IndexPack.java  |   11 ++++++-----\n .../org/spearce/jgit/transport/ObjectEntry.java    |   12 ++++++++++--\n 2 files changed, 16 insertions(+), 7 deletions(-)\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/transport/IndexPack.java b/org.spearce.jgit/src/org/spearce/jgit/transport/IndexPack.java\nindex e182cfc..19a4b7b 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/transport/IndexPack.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/transport/IndexPack.java\n@@ -281,8 +281,9 @@ public class IndexPack {\n \t}\n \n \tprivate void resolveDeltas(final ObjectEntry oe) throws IOException {\n-\t\tif (baseById.containsKey(oe) || baseByPos.containsKey(new Long(oe.pos)))\n-\t\t\tresolveDeltas(oe.pos, Constants.OBJ_BAD, null, oe);\n+\t\tif (baseById.containsKey(oe)\n+\t\t\t\t|| baseByPos.containsKey(new Long(oe.getOffset())))\n+\t\t\tresolveDeltas(oe.getOffset(), Constants.OBJ_BAD, null, oe);\n \t}\n \n \tprivate void resolveDeltas(final long pos, int type, byte[] data,\n@@ -381,7 +382,7 @@ public class IndexPack {\n \t\t\twriteWhole(def, typeCode, data);\n \t\t\tend = packOut.getFilePointer();\n \n-\t\t\tresolveChildDeltas(oe.pos, typeCode, data, oe);\n+\t\t\tresolveChildDeltas(oe.getOffset(), typeCode, data, oe);\n \t\t\tif (progress.isCancelled())\n \t\t\t\tthrow new IOException(\"Download cancelled during indexing\");\n \t\t}\n@@ -458,9 +459,9 @@ public class IndexPack {\n \t\t\t}\n \t\t\tfor (int i = 0; i < entryCount; i++) {\n \t\t\t\tfinal ObjectEntry oe = entries[i];\n-\t\t\t\tif (oe.pos >>> 1 > Integer.MAX_VALUE)\n+\t\t\t\tif (oe.getOffset() >>> 1 > Integer.MAX_VALUE)\n \t\t\t\t\tthrow new IOException(\"Pack too large for index version 1\");\n-\t\t\t\tNB.encodeInt32(rawoe, 0, (int) oe.pos);\n+\t\t\t\tNB.encodeInt32(rawoe, 0, (int) oe.getOffset());\n \t\t\t\toe.copyRawTo(rawoe, 4);\n \t\t\t\tos.write(rawoe);\n \t\t\t\td.update(rawoe);\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/transport/ObjectEntry.java b/org.spearce.jgit/src/org/spearce/jgit/transport/ObjectEntry.java\nindex 58d2eb2..10a8f4d 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/transport/ObjectEntry.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/transport/ObjectEntry.java\n@@ -42,10 +42,18 @@ import org.spearce.jgit.lib.AnyObjectId;\n import org.spearce.jgit.lib.ObjectId;\n \n class ObjectEntry extends ObjectId {\n-\tfinal long pos;\n+\tprivate long offset;\n \n \tObjectEntry(final long headerOffset, final AnyObjectId id) {\n \t\tsuper(id);\n-\t\tpos = headerOffset;\n+\t\toffset = headerOffset;\n+\t}\n+\n+\t/**\n+\t * @return offset in pack when object has been already written, or -1 if it\n+\t *         has not been written yet\n+\t */\n+\tlong getOffset() {\n+\t\treturn offset;\n \t}\n }\n-- \n1.5.6.74.g8a5e\n"},{"id":"80810","messageId":"1214273408-70793-4-git-send-email-spearce@spearce.org","threadId":"14113","inReplyTo":"1214273408-70793-3-git-send-email-spearce@spearce.org","subject":"[JGIT PATCH 03/10] Rename ObjectEntry to PackedObjectInfo","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2008-06-24T02:10:01Z","receivedAt":"2008-06-24T02:10:01Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Technically this class contains information about a packed object,\ndata which is necessary to access it or to create the index record\nto support random access to the object's information.  Calling it\njust ObjectEntry is no longer a very sufficient name.\n\nSigned-off-by: Shawn O. Pearce <spearce@spearce.org>\n---\n .../src/org/spearce/jgit/transport/IndexPack.java  |   26 ++++----\n .../org/spearce/jgit/transport/ObjectEntry.java    |   59 --------------------\n .../spearce/jgit/transport/PackedObjectInfo.java   |   59 ++++++++++++++++++++\n 3 files changed, 72 insertions(+), 72 deletions(-)\n delete mode 100644 org.spearce.jgit/src/org/spearce/jgit/transport/ObjectEntry.java\n create mode 100644 org.spearce.jgit/src/org/spearce/jgit/transport/PackedObjectInfo.java\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/transport/IndexPack.java b/org.spearce.jgit/src/org/spearce/jgit/transport/IndexPack.java\nindex 19a4b7b..ad4bcae 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/transport/IndexPack.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/transport/IndexPack.java\n@@ -129,7 +129,7 @@ public class IndexPack {\n \n \tprivate long objectCount;\n \n-\tprivate ObjectEntry[] entries;\n+\tprivate PackedObjectInfo[] entries;\n \n \tprivate int deltaCount;\n \n@@ -208,7 +208,7 @@ public class IndexPack {\n \t\t\ttry {\n \t\t\t\treadPackHeader();\n \n-\t\t\t\tentries = new ObjectEntry[(int) objectCount];\n+\t\t\t\tentries = new PackedObjectInfo[(int) objectCount];\n \t\t\t\tbaseById = new ObjectIdMap<ArrayList<UnresolvedDelta>>();\n \t\t\t\tbaseByPos = new HashMap<Long, ArrayList<UnresolvedDelta>>();\n \n@@ -280,14 +280,14 @@ public class IndexPack {\n \t\tprogress.endTask();\n \t}\n \n-\tprivate void resolveDeltas(final ObjectEntry oe) throws IOException {\n+\tprivate void resolveDeltas(final PackedObjectInfo oe) throws IOException {\n \t\tif (baseById.containsKey(oe)\n \t\t\t\t|| baseByPos.containsKey(new Long(oe.getOffset())))\n \t\t\tresolveDeltas(oe.getOffset(), Constants.OBJ_BAD, null, oe);\n \t}\n \n \tprivate void resolveDeltas(final long pos, int type, byte[] data,\n-\t\t\tObjectEntry oe) throws IOException {\n+\t\t\tPackedObjectInfo oe) throws IOException {\n \t\tposition(pos);\n \t\tint c = readFromFile();\n \t\tfinal int typeCode = (c >> 4) & 7;\n@@ -331,7 +331,7 @@ public class IndexPack {\n \t\t\tobjectDigest.update((byte) 0);\n \t\t\tobjectDigest.update(data);\n \t\t\ttempObjectId.fromRaw(objectDigest.digest(), 0);\n-\t\t\toe = new ObjectEntry(pos, tempObjectId);\n+\t\t\toe = new PackedObjectInfo(pos, tempObjectId);\n \t\t\tentries[entryCount++] = oe;\n \t\t}\n \n@@ -339,7 +339,7 @@ public class IndexPack {\n \t}\n \n \tprivate void resolveChildDeltas(final long pos, int type, byte[] data,\n-\t\t\tObjectEntry oe) throws IOException {\n+\t\t\tPackedObjectInfo oe) throws IOException {\n \t\tfinal ArrayList<UnresolvedDelta> a = baseById.remove(oe);\n \t\tfinal ArrayList<UnresolvedDelta> b = baseByPos.remove(new Long(pos));\n \t\tint ai = 0, bi = 0;\n@@ -374,9 +374,9 @@ public class IndexPack {\n \t\t\tfinal ObjectLoader ldr = repo.openObject(baseId);\n \t\t\tfinal byte[] data = ldr.getBytes();\n \t\t\tfinal int typeCode = ldr.getType();\n-\t\t\tfinal ObjectEntry oe;\n+\t\t\tfinal PackedObjectInfo oe;\n \n-\t\t\toe = new ObjectEntry(end, baseId);\n+\t\t\toe = new PackedObjectInfo(end, baseId);\n \t\t\tentries[entryCount++] = oe;\n \t\t\tpackOut.seek(end);\n \t\t\twriteWhole(def, typeCode, data);\n@@ -432,9 +432,9 @@ public class IndexPack {\n \t}\n \n \tprivate void growEntries() {\n-\t\tfinal ObjectEntry[] ne;\n+\t\tfinal PackedObjectInfo[] ne;\n \n-\t\tne = new ObjectEntry[(int) objectCount + baseById.size()];\n+\t\tne = new PackedObjectInfo[(int) objectCount + baseById.size()];\n \t\tSystem.arraycopy(entries, 0, ne, 0, entryCount);\n \t\tentries = ne;\n \t}\n@@ -458,7 +458,7 @@ public class IndexPack {\n \t\t\t\td.update(rawoe, 0, 4);\n \t\t\t}\n \t\t\tfor (int i = 0; i < entryCount; i++) {\n-\t\t\t\tfinal ObjectEntry oe = entries[i];\n+\t\t\t\tfinal PackedObjectInfo oe = entries[i];\n \t\t\t\tif (oe.getOffset() >>> 1 > Integer.MAX_VALUE)\n \t\t\t\t\tthrow new IOException(\"Pack too large for index version 1\");\n \t\t\t\tNB.encodeInt32(rawoe, 0, (int) oe.getOffset());\n@@ -578,7 +578,7 @@ public class IndexPack {\n \t\tobjectDigest.update((byte) 0);\n \t\tinflateFromInput(true);\n \t\ttempObjectId.fromRaw(objectDigest.digest(), 0);\n-\t\tentries[entryCount++] = new ObjectEntry(pos, tempObjectId);\n+\t\tentries[entryCount++] = new PackedObjectInfo(pos, tempObjectId);\n \t}\n \n \t// Current position of {@link #bOffset} within the entire file.\n@@ -739,7 +739,7 @@ public class IndexPack {\n \t\tfinal MessageDigest d = Constants.newMessageDigest();\n \t\tfinal byte[] oeBytes = new byte[Constants.OBJECT_ID_LENGTH];\n \t\tfor (int i = 0; i < entryCount; i++) {\n-\t\t\tfinal ObjectEntry oe = entries[i];\n+\t\t\tfinal PackedObjectInfo oe = entries[i];\n \t\t\toe.copyRawTo(oeBytes, 0);\n \t\t\td.update(oeBytes);\n \t\t}\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/transport/ObjectEntry.java b/org.spearce.jgit/src/org/spearce/jgit/transport/ObjectEntry.java\ndeleted file mode 100644\nindex 10a8f4d..0000000\n--- a/org.spearce.jgit/src/org/spearce/jgit/transport/ObjectEntry.java\n+++ /dev/null\n@@ -1,59 +0,0 @@\n-/*\n- * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>\n- * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>\n- *\n- * All rights reserved.\n- *\n- * Redistribution and use in source and binary forms, with or\n- * without modification, are permitted provided that the following\n- * conditions are met:\n- *\n- * - Redistributions of source code must retain the above copyright\n- *   notice, this list of conditions and the following disclaimer.\n- *\n- * - Redistributions in binary form must reproduce the above\n- *   copyright notice, this list of conditions and the following\n- *   disclaimer in the documentation and/or other materials provided\n- *   with the distribution.\n- *\n- * - Neither the name of the Git Development Community nor the\n- *   names of its contributors may be used to endorse or promote\n- *   products derived from this software without specific prior\n- *   written permission.\n- *\n- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND\n- * CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES,\n- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\n- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n- */\n-\n-package org.spearce.jgit.transport;\n-\n-import org.spearce.jgit.lib.AnyObjectId;\n-import org.spearce.jgit.lib.ObjectId;\n-\n-class ObjectEntry extends ObjectId {\n-\tprivate long offset;\n-\n-\tObjectEntry(final long headerOffset, final AnyObjectId id) {\n-\t\tsuper(id);\n-\t\toffset = headerOffset;\n-\t}\n-\n-\t/**\n-\t * @return offset in pack when object has been already written, or -1 if it\n-\t *         has not been written yet\n-\t */\n-\tlong getOffset() {\n-\t\treturn offset;\n-\t}\n-}\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/transport/PackedObjectInfo.java b/org.spearce.jgit/src/org/spearce/jgit/transport/PackedObjectInfo.java\nnew file mode 100644\nindex 0000000..eaedee9\n--- /dev/null\n+++ b/org.spearce.jgit/src/org/spearce/jgit/transport/PackedObjectInfo.java\n@@ -0,0 +1,59 @@\n+/*\n+ * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>\n+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>\n+ *\n+ * All rights reserved.\n+ *\n+ * Redistribution and use in source and binary forms, with or\n+ * without modification, are permitted provided that the following\n+ * conditions are met:\n+ *\n+ * - Redistributions of source code must retain the above copyright\n+ *   notice, this list of conditions and the following disclaimer.\n+ *\n+ * - Redistributions in binary form must reproduce the above\n+ *   copyright notice, this list of conditions and the following\n+ *   disclaimer in the documentation and/or other materials provided\n+ *   with the distribution.\n+ *\n+ * - Neither the name of the Git Development Community nor the\n+ *   names of its contributors may be used to endorse or promote\n+ *   products derived from this software without specific prior\n+ *   written permission.\n+ *\n+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND\n+ * CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES,\n+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\n+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+package org.spearce.jgit.transport;\n+\n+import org.spearce.jgit.lib.AnyObjectId;\n+import org.spearce.jgit.lib.ObjectId;\n+\n+class PackedObjectInfo extends ObjectId {\n+\tprivate long offset;\n+\n+\tPackedObjectInfo(final long headerOffset, final AnyObjectId id) {\n+\t\tsuper(id);\n+\t\toffset = headerOffset;\n+\t}\n+\n+\t/**\n+\t * @return offset in pack when object has been already written, or -1 if it\n+\t *         has not been written yet\n+\t */\n+\tlong getOffset() {\n+\t\treturn offset;\n+\t}\n+}\n-- \n1.5.6.74.g8a5e\n"},{"id":"80811","messageId":"1214273408-70793-5-git-send-email-spearce@spearce.org","threadId":"14113","inReplyTo":"1214273408-70793-4-git-send-email-spearce@spearce.org","subject":"[JGIT PATCH 04/10] Document PackedObjectInfo and make it public for reuse","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2008-06-24T02:10:02Z","receivedAt":"2008-06-24T02:10:02Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Classes outside of transport may wish to use this abstraction,\nso we mark it public, expose the offset field, and document\nas much of the API as possible.\n\nSigned-off-by: Shawn O. Pearce <spearce@spearce.org>\n---\n .../spearce/jgit/transport/PackedObjectInfo.java   |   33 ++++++++++++++++++--\n 1 files changed, 30 insertions(+), 3 deletions(-)\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/transport/PackedObjectInfo.java b/org.spearce.jgit/src/org/spearce/jgit/transport/PackedObjectInfo.java\nindex eaedee9..58feada 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/transport/PackedObjectInfo.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/transport/PackedObjectInfo.java\n@@ -41,7 +41,14 @@ package org.spearce.jgit.transport;\n import org.spearce.jgit.lib.AnyObjectId;\n import org.spearce.jgit.lib.ObjectId;\n \n-class PackedObjectInfo extends ObjectId {\n+/**\n+ * Description of an object stored in a pack file, including offset.\n+ * <p>\n+ * When objects are stored in packs Git needs the ObjectId and the offset\n+ * (starting position of the object data) to perform random-access reads of\n+ * objects from the pack. This extension of ObjectId includes the offset.\n+ */\n+public class PackedObjectInfo extends ObjectId {\n \tprivate long offset;\n \n \tPackedObjectInfo(final long headerOffset, final AnyObjectId id) {\n@@ -50,10 +57,30 @@ class PackedObjectInfo extends ObjectId {\n \t}\n \n \t/**\n-\t * @return offset in pack when object has been already written, or -1 if it\n+\t * Create a new structure to remember information about an object.\n+\t * \n+\t * @param id\n+\t *            the identity of the object the new instance tracks.\n+\t */\n+\tpublic PackedObjectInfo(final AnyObjectId id) {\n+\t\tsuper(id);\n+\t}\n+\n+\t/**\n+\t * @return offset in pack when object has been already written, or 0 if it\n \t *         has not been written yet\n \t */\n-\tlong getOffset() {\n+\tpublic long getOffset() {\n \t\treturn offset;\n \t}\n+\n+\t/**\n+\t * Set the offset in pack when object has been written to.\n+\t * \n+\t * @param offset\n+\t *            offset where written object starts\n+\t */\n+\tpublic void setOffset(final long offset) {\n+\t\tthis.offset = offset;\n+\t}\n }\n-- \n1.5.6.74.g8a5e\n"},{"id":"80812","messageId":"1214273408-70793-6-git-send-email-spearce@spearce.org","threadId":"14113","inReplyTo":"1214273408-70793-5-git-send-email-spearce@spearce.org","subject":"[JGIT PATCH 05/10] Refactor pack index writing to a common API","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2008-06-24T02:10:03Z","receivedAt":"2008-06-24T02:10:03Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"To repack a repository or to push a pack file over a dumb transport\nwe need to create a .idx file to match the .pack.  This means\nthe index writing features of transport.IndexPack are needed by\nPackWriter, and/or dumb protocol transports.\n\nThis refactoring creates a PackIndexWriter class structure that\nmirrors the PackIndex (reader) structure we already have in place\nfor PackIndexV1 and PackIndexV2.\n\nAt present only PackIndexV1 is supported as we do not have access\nto the CRC data necessary to write PackIndexV2 style files.\n\nSigned-off-by: Shawn O. Pearce <spearce@spearce.org>\n---\n .../src/org/spearce/jgit/lib/PackIndexWriter.java  |  243 ++++++++++++++++++++\n .../org/spearce/jgit/lib/PackIndexWriterV1.java    |   78 +++++++\n .../src/org/spearce/jgit/transport/IndexPack.java  |   37 +---\n 3 files changed, 330 insertions(+), 28 deletions(-)\n create mode 100644 org.spearce.jgit/src/org/spearce/jgit/lib/PackIndexWriter.java\n create mode 100644 org.spearce.jgit/src/org/spearce/jgit/lib/PackIndexWriterV1.java\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/PackIndexWriter.java b/org.spearce.jgit/src/org/spearce/jgit/lib/PackIndexWriter.java\nnew file mode 100644\nindex 0000000..473e6cf\n--- /dev/null\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/PackIndexWriter.java\n@@ -0,0 +1,243 @@\n+/*\n+ * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>\n+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>\n+ *\n+ * All rights reserved.\n+ *\n+ * Redistribution and use in source and binary forms, with or\n+ * without modification, are permitted provided that the following\n+ * conditions are met:\n+ *\n+ * - Redistributions of source code must retain the above copyright\n+ *   notice, this list of conditions and the following disclaimer.\n+ *\n+ * - Redistributions in binary form must reproduce the above\n+ *   copyright notice, this list of conditions and the following\n+ *   disclaimer in the documentation and/or other materials provided\n+ *   with the distribution.\n+ *\n+ * - Neither the name of the Git Development Community nor the\n+ *   names of its contributors may be used to endorse or promote\n+ *   products derived from this software without specific prior\n+ *   written permission.\n+ *\n+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND\n+ * CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES,\n+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\n+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+package org.spearce.jgit.lib;\n+\n+import java.io.BufferedOutputStream;\n+import java.io.IOException;\n+import java.io.OutputStream;\n+import java.security.DigestOutputStream;\n+import java.util.List;\n+\n+import org.spearce.jgit.transport.PackedObjectInfo;\n+import org.spearce.jgit.util.NB;\n+\n+/**\n+ * Creates a table of contents to support random access by {@link PackFile}.\n+ * <p>\n+ * Pack index files (the <code>.idx</code> suffix in a pack file pair)\n+ * provides random access to any object in the pack by associating an ObjectId\n+ * to the byte offset within the pack where the object's data can be read.\n+ */\n+public abstract class PackIndexWriter {\n+\t/**\n+\t * Create a new writer for the oldest (most widely understood) format.\n+\t * <p>\n+\t * This method selects an index format that can accurate describe the\n+\t * supplied objects and that will be the most compatible format with older\n+\t * Git implementations.\n+\t * <p>\n+\t * Index version 1 is widely recognized by all Git implementations, but\n+\t * index version 2 (and later) is not as well recognized as it was\n+\t * introduced more than a year later. Index version 1 can only be used if\n+\t * the resulting pack file is under 4 gigabytes in size; packs larger than\n+\t * that limit must use index version 2.\n+\t * \n+\t * @param dst\n+\t *            the stream the index data will be written to. If not already\n+\t *            buffered it will be automatically wrapped in a buffered\n+\t *            stream. Callers are always responsible for closing the stream.\n+\t * @param objs\n+\t *            the objects the caller needs to store in the index. Entries\n+\t *            will be examined until a format can be conclusively selected.\n+\t * @return a new writer to output an index file of the requested format to\n+\t *         the supplied stream.\n+\t * @throws IllegalArgumentException\n+\t *             no recognized pack index version can support the supplied\n+\t *             objects. This is likely a bug in the implementation.\n+\t */\n+\t@SuppressWarnings(\"fallthrough\")\n+\tpublic static PackIndexWriter createOldestPossible(final OutputStream dst,\n+\t\t\tfinal List<PackedObjectInfo> objs) {\n+\t\tint version = 1;\n+\t\tLOOP: for (final PackedObjectInfo oe : objs) {\n+\t\t\tswitch (version) {\n+\t\t\tcase 1:\n+\t\t\t\tif (PackIndexWriterV1.canStore(oe))\n+\t\t\t\t\tcontinue;\n+\t\t\t\tversion = 2;\n+\t\t\tcase 2:\n+\t\t\t\tbreak LOOP;\n+\t\t\t}\n+\t\t}\n+\t\treturn createVersion(dst, version);\n+\t}\n+\n+\t/**\n+\t * Create a new writer instance for a specific index format version.\n+\t * \n+\t * @param dst\n+\t *            the stream the index data will be written to. If not already\n+\t *            buffered it will be automatically wrapped in a buffered\n+\t *            stream. Callers are always responsible for closing the stream.\n+\t * @param version\n+\t *            index format version number required by the caller. Exactly\n+\t *            this formatted version will be written.\n+\t * @return a new writer to output an index file of the requested format to\n+\t *         the supplied stream.\n+\t * @throws IllegalArgumentException\n+\t *             the version requested is not supported by this\n+\t *             implementation.\n+\t */\n+\tpublic static PackIndexWriter createVersion(final OutputStream dst,\n+\t\t\tfinal int version) {\n+\t\tswitch (version) {\n+\t\tcase 1:\n+\t\t\treturn new PackIndexWriterV1(dst);\n+\t\tdefault:\n+\t\t\tthrow new IllegalArgumentException(\n+\t\t\t\t\t\"Unsupported pack index version \" + version);\n+\t\t}\n+\t}\n+\n+\t/** The index data stream we are responsible for creating. */\n+\tprotected final DigestOutputStream out;\n+\n+\t/** A temporary buffer for use during IO to {link #out}. */\n+\tprotected final byte[] tmp;\n+\n+\t/** The entries this writer must pack. */\n+\tprotected List<PackedObjectInfo> entries;\n+\n+\t/** SHA-1 checksum for the entire pack data. */\n+\tprotected byte[] packChecksum;\n+\n+\t/**\n+\t * Create a new writer instance.\n+\t * \n+\t * @param dst\n+\t *            the stream this instance outputs to. If not already buffered\n+\t *            it will be automatically wrapped in a buffered stream.\n+\t */\n+\tprotected PackIndexWriter(final OutputStream dst) {\n+\t\tout = new DigestOutputStream(dst instanceof BufferedOutputStream ? dst\n+\t\t\t\t: new BufferedOutputStream(dst), Constants.newMessageDigest());\n+\t\ttmp = new byte[4 + Constants.OBJECT_ID_LENGTH];\n+\t}\n+\n+\t/**\n+\t * Write all object entries to the index stream.\n+\t * <p>\n+\t * After writing the stream passed to the factory is flushed but remains\n+\t * open. Callers are always responsible for closing the output stream.\n+\t * \n+\t * @param toStore\n+\t *            sorted list of objects to store in the index. The caller must\n+\t *            have previously sorted the list using {@link PackedObjectInfo}'s\n+\t *            native {@link Comparable} implementation.\n+\t * @param packDataChecksum\n+\t *            checksum signature of the entire pack data content. This is\n+\t *            traditionally the last 20 bytes of the pack file's own stream.\n+\t * @throws IOException\n+\t *             an error occurred while writing to the output stream, or this\n+\t *             index format cannot store the object data supplied.\n+\t */\n+\tpublic void write(final List<PackedObjectInfo> toStore,\n+\t\t\tfinal byte[] packDataChecksum) throws IOException {\n+\t\tentries = toStore;\n+\t\tpackChecksum = packDataChecksum;\n+\t\twriteImpl();\n+\t\tout.flush();\n+\t}\n+\n+\t/**\n+\t * Writes the index file to {@link #out}.\n+\t * <p>\n+\t * Implementations should go something like:\n+\t * \n+\t * <pre>\n+\t * writeFanOutTable();\n+\t * for (final PackedObjectInfo po : entries)\n+\t * \twriteOneEntry(po);\n+\t * writeChecksumFooter();\n+\t * </pre>\n+\t * \n+\t * <p>\n+\t * Where the logic for <code>writeOneEntry</code> is specific to the index\n+\t * format in use. Additional headers/footers may be used if necessary and\n+\t * the {@link #entries} collection may be iterated over more than once if\n+\t * necessary. Implementors therefore have complete control over the data.\n+\t * \n+\t * @throws IOException\n+\t *             an error occurred while writing to the output stream, or this\n+\t *             index format cannot store the object data supplied.\n+\t */\n+\tprotected abstract void writeImpl() throws IOException;\n+\n+\t/**\n+\t * Output the standard 256 entry first-level fan-out table.\n+\t * <p>\n+\t * The fan-out table is 4 KB in size, holding 256 32-bit unsigned integer\n+\t * counts. Each count represents the number of objects within this index\n+\t * whose {@link ObjectId#getFirstByte()} matches the count's position in the\n+\t * fan-out table.\n+\t * \n+\t * @throws IOException\n+\t *             an error occurred while writing to the output stream.\n+\t */\n+\tprotected void writeFanOutTable() throws IOException {\n+\t\tfinal int[] fanout = new int[256];\n+\t\tfor (final PackedObjectInfo po : entries)\n+\t\t\tfanout[po.getFirstByte() & 0xff]++;\n+\t\tfor (int i = 1; i < 256; i++)\n+\t\t\tfanout[i] += fanout[i - 1];\n+\t\tfor (final int n : fanout) {\n+\t\t\tNB.encodeInt32(tmp, 0, n);\n+\t\t\tout.write(tmp, 0, 4);\n+\t\t}\n+\t}\n+\n+\t/**\n+\t * Output the standard two-checksum index footer.\n+\t * <p>\n+\t * The standard footer contains two checksums (20 byte SHA-1 values):\n+\t * <ol>\n+\t * <li>Pack data checksum - taken from the last 20 bytes of the pack file.</li>\n+\t * <li>Index data checksum - checksum of all index bytes written, including\n+\t * the pack data checksum above.</li>\n+\t * </ol>\n+\t * \n+\t * @throws IOException\n+\t *             an error occurred while writing to the output stream.\n+\t */\n+\tprotected void writeChecksumFooter() throws IOException {\n+\t\tout.write(packChecksum);\n+\t\tout.on(false);\n+\t\tout.write(out.getMessageDigest().digest());\n+\t}\n+}\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/PackIndexWriterV1.java b/org.spearce.jgit/src/org/spearce/jgit/lib/PackIndexWriterV1.java\nnew file mode 100644\nindex 0000000..b790a28\n--- /dev/null\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/PackIndexWriterV1.java\n@@ -0,0 +1,78 @@\n+/*\n+ * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>\n+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>\n+ *\n+ * All rights reserved.\n+ *\n+ * Redistribution and use in source and binary forms, with or\n+ * without modification, are permitted provided that the following\n+ * conditions are met:\n+ *\n+ * - Redistributions of source code must retain the above copyright\n+ *   notice, this list of conditions and the following disclaimer.\n+ *\n+ * - Redistributions in binary form must reproduce the above\n+ *   copyright notice, this list of conditions and the following\n+ *   disclaimer in the documentation and/or other materials provided\n+ *   with the distribution.\n+ *\n+ * - Neither the name of the Git Development Community nor the\n+ *   names of its contributors may be used to endorse or promote\n+ *   products derived from this software without specific prior\n+ *   written permission.\n+ *\n+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND\n+ * CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES,\n+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\n+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+package org.spearce.jgit.lib;\n+\n+import java.io.IOException;\n+import java.io.OutputStream;\n+\n+import org.spearce.jgit.transport.PackedObjectInfo;\n+import org.spearce.jgit.util.NB;\n+\n+/**\n+ * Creates the version 1 (old style) pack table of contents files.\n+ * \n+ * @see PackIndexWriter\n+ * @see PackIndexV1\n+ */\n+class PackIndexWriterV1 extends PackIndexWriter {\n+\tstatic boolean canStore(final PackedObjectInfo oe) {\n+\t\t// We are limited to 4 GB per pack as offset is 32 bit unsigned int.\n+\t\t//\n+\t\treturn oe.getOffset() >>> 1 < Integer.MAX_VALUE;\n+\t}\n+\n+\tPackIndexWriterV1(final OutputStream dst) {\n+\t\tsuper(dst);\n+\t}\n+\n+\t@Override\n+\tprotected void writeImpl() throws IOException {\n+\t\twriteFanOutTable();\n+\n+\t\tfor (final PackedObjectInfo oe : entries) {\n+\t\t\tif (!canStore(oe))\n+\t\t\t\tthrow new IOException(\"Pack too large for index version 1\");\n+\t\t\tNB.encodeInt32(tmp, 0, (int) oe.getOffset());\n+\t\t\toe.copyRawTo(tmp, 4);\n+\t\t\tout.write(tmp);\n+\t\t}\n+\n+\t\twriteChecksumFooter();\n+\t}\n+}\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/transport/IndexPack.java b/org.spearce.jgit/src/org/spearce/jgit/transport/IndexPack.java\nindex ad4bcae..60e0bce 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/transport/IndexPack.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/transport/IndexPack.java\n@@ -38,7 +38,6 @@\n \n package org.spearce.jgit.transport;\n \n-import java.io.BufferedOutputStream;\n import java.io.EOFException;\n import java.io.File;\n import java.io.FileOutputStream;\n@@ -49,6 +48,7 @@ import java.security.MessageDigest;\n import java.util.ArrayList;\n import java.util.Arrays;\n import java.util.HashMap;\n+import java.util.List;\n import java.util.zip.DataFormatException;\n import java.util.zip.Deflater;\n import java.util.zip.Inflater;\n@@ -61,6 +61,7 @@ import org.spearce.jgit.lib.MutableObjectId;\n import org.spearce.jgit.lib.ObjectId;\n import org.spearce.jgit.lib.ObjectIdMap;\n import org.spearce.jgit.lib.ObjectLoader;\n+import org.spearce.jgit.lib.PackIndexWriter;\n import org.spearce.jgit.lib.ProgressMonitor;\n import org.spearce.jgit.lib.Repository;\n import org.spearce.jgit.util.NB;\n@@ -441,34 +442,14 @@ public class IndexPack {\n \n \tprivate void writeIdx() throws IOException {\n \t\tArrays.sort(entries, 0, entryCount);\n-\t\tfinal int[] fanout = new int[256];\n-\t\tfor (int i = 0; i < entryCount; i++)\n-\t\t\tfanout[entries[i].getFirstByte() & 0xff]++;\n-\t\tfor (int i = 1; i < 256; i++)\n-\t\t\tfanout[i] += fanout[i - 1];\n-\n-\t\tfinal BufferedOutputStream os = new BufferedOutputStream(\n-\t\t\t\tnew FileOutputStream(dstIdx), BUFFER_SIZE);\n+\t\tList<PackedObjectInfo> list = Arrays.asList(entries);\n+\t\tif (entryCount < entries.length)\n+\t\t\tlist = list.subList(0, entryCount);\n+\n+\t\tfinal FileOutputStream os = new FileOutputStream(dstIdx);\n \t\ttry {\n-\t\t\tfinal byte[] rawoe = new byte[4 + Constants.OBJECT_ID_LENGTH];\n-\t\t\tfinal MessageDigest d = Constants.newMessageDigest();\n-\t\t\tfor (int i = 0; i < 256; i++) {\n-\t\t\t\tNB.encodeInt32(rawoe, 0, fanout[i]);\n-\t\t\t\tos.write(rawoe, 0, 4);\n-\t\t\t\td.update(rawoe, 0, 4);\n-\t\t\t}\n-\t\t\tfor (int i = 0; i < entryCount; i++) {\n-\t\t\t\tfinal PackedObjectInfo oe = entries[i];\n-\t\t\t\tif (oe.getOffset() >>> 1 > Integer.MAX_VALUE)\n-\t\t\t\t\tthrow new IOException(\"Pack too large for index version 1\");\n-\t\t\t\tNB.encodeInt32(rawoe, 0, (int) oe.getOffset());\n-\t\t\t\toe.copyRawTo(rawoe, 4);\n-\t\t\t\tos.write(rawoe);\n-\t\t\t\td.update(rawoe);\n-\t\t\t}\n-\t\t\tos.write(packcsum);\n-\t\t\td.update(packcsum);\n-\t\t\tos.write(d.digest());\n+\t\t\tPackIndexWriter.createOldestPossible(os, list)\n+\t\t\t\t\t.write(list, packcsum);\n \t\t} finally {\n \t\t\tos.close();\n \t\t}\n-- \n1.5.6.74.g8a5e\n"},{"id":"80813","messageId":"1214273408-70793-7-git-send-email-spearce@spearce.org","threadId":"14113","inReplyTo":"1214273408-70793-6-git-send-email-spearce@spearce.org","subject":"[JGIT PATCH 06/10] Reuse the magic tOc constant for pack index headers","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2008-06-24T02:10:04Z","receivedAt":"2008-06-24T02:10:04Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"We need this constant to detect version 2 index files at read time,\nbut we also need it to create version 2 index files.\n\nSigned-off-by: Shawn O. Pearce <spearce@spearce.org>\n---\n .../src/org/spearce/jgit/lib/PackIndex.java        |    3 ++-\n .../src/org/spearce/jgit/lib/PackIndexWriter.java  |    3 +++\n 2 files changed, 5 insertions(+), 1 deletions(-)\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/PackIndex.java b/org.spearce.jgit/src/org/spearce/jgit/lib/PackIndex.java\nindex 3935d4f..ef4b13d 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/lib/PackIndex.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/PackIndex.java\n@@ -42,6 +42,7 @@ import java.io.File;\n import java.io.FileInputStream;\n import java.io.FileNotFoundException;\n import java.io.IOException;\n+import java.util.Arrays;\n import java.util.Iterator;\n \n import org.spearce.jgit.util.NB;\n@@ -104,7 +105,7 @@ public abstract class PackIndex implements Iterable<PackIndex.MutableEntry> {\n \t}\n \n \tprivate static boolean isTOC(final byte[] h) {\n-\t\treturn h[0] == -1 && h[1] == 't' && h[2] == 'O' && h[3] == 'c';\n+\t\treturn Arrays.equals(h, PackIndexWriter.TOC);\n \t}\n \n \t/**\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/PackIndexWriter.java b/org.spearce.jgit/src/org/spearce/jgit/lib/PackIndexWriter.java\nindex 473e6cf..c9b27d2 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/lib/PackIndexWriter.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/PackIndexWriter.java\n@@ -55,6 +55,9 @@ import org.spearce.jgit.util.NB;\n  * to the byte offset within the pack where the object's data can be read.\n  */\n public abstract class PackIndexWriter {\n+\t/** Magic constant indicating post-version 1 format. */\n+\tprotected static final byte[] TOC = { -1, 't', 'O', 'c' };\n+\n \t/**\n \t * Create a new writer for the oldest (most widely understood) format.\n \t * <p>\n-- \n1.5.6.74.g8a5e\n"},{"id":"80816","messageId":"1214273408-70793-8-git-send-email-spearce@spearce.org","threadId":"14113","inReplyTo":"1214273408-70793-7-git-send-email-spearce@spearce.org","subject":"[JGIT PATCH 07/10] Add 64 bit network byte order encoding to NB","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2008-06-24T02:10:05Z","receivedAt":"2008-06-24T02:10:05Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"The pack index v2 file format uses a 64 bit network byte order\nelement for the 64 bit offset table.  We already have code to\nread these elements, but we do not yet have code to write such\nan element to an output file.\n\nSigned-off-by: Shawn O. Pearce <spearce@spearce.org>\n---\n org.spearce.jgit/src/org/spearce/jgit/util/NB.java |   37 ++++++++++++++++++++\n 1 files changed, 37 insertions(+), 0 deletions(-)\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/util/NB.java b/org.spearce.jgit/src/org/spearce/jgit/util/NB.java\nindex 61877b8..6bb65d4 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/util/NB.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/util/NB.java\n@@ -172,6 +172,43 @@ public final class NB {\n \t\tintbuf[offset] = (byte) v;\n \t}\n \n+\t/**\n+\t * Write a 64 bit integer as a sequence of 8 bytes (network byte order).\n+\t * \n+\t * @param intbuf\n+\t *            buffer to write the 48bytes of data into.\n+\t * @param offset\n+\t *            position within the buffer to begin writing to. This position\n+\t *            and the next 7 bytes after it (for a total of 8 bytes) will be\n+\t *            replaced.\n+\t * @param v\n+\t *            the value to write.\n+\t */\n+\tpublic static void encodeInt64(final byte[] intbuf, final int offset, long v) {\n+\t\tintbuf[offset + 7] = (byte) v;\n+\t\tv >>>= 8;\n+\n+\t\tintbuf[offset + 6] = (byte) v;\n+\t\tv >>>= 8;\n+\n+\t\tintbuf[offset + 5] = (byte) v;\n+\t\tv >>>= 8;\n+\n+\t\tintbuf[offset + 4] = (byte) v;\n+\t\tv >>>= 8;\n+\n+\t\tintbuf[offset + 3] = (byte) v;\n+\t\tv >>>= 8;\n+\n+\t\tintbuf[offset + 2] = (byte) v;\n+\t\tv >>>= 8;\n+\n+\t\tintbuf[offset + 1] = (byte) v;\n+\t\tv >>>= 8;\n+\n+\t\tintbuf[offset] = (byte) v;\n+\t}\n+\n \tprivate NB() {\n \t\t// Don't create instances of a static only utility.\n \t}\n-- \n1.5.6.74.g8a5e\n"},{"id":"80815","messageId":"1214273408-70793-9-git-send-email-spearce@spearce.org","threadId":"14113","inReplyTo":"1214273408-70793-8-git-send-email-spearce@spearce.org","subject":"[JGIT PATCH 08/10] Compute packed object entry CRC32 data during IndexPack","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2008-06-24T02:10:06Z","receivedAt":"2008-06-24T02:10:06Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"In order to create a pack index using the v2 file format we must\nhave the CRC32 data available for every object we discovered in\nthat pack stream.  We now compute this on the fly as we read the\nobject entries in from the input stream.  Always running the CRC\ncomputation isn't that expensive and we can be certain we would\nalways have the information necessary to create a v2 index file.\n\nSigned-off-by: Shawn O. Pearce <spearce@spearce.org>\n---\n .../src/org/spearce/jgit/transport/IndexPack.java  |  135 ++++++++++++++------\n .../spearce/jgit/transport/PackedObjectInfo.java   |   25 ++++-\n 2 files changed, 117 insertions(+), 43 deletions(-)\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/transport/IndexPack.java b/org.spearce.jgit/src/org/spearce/jgit/transport/IndexPack.java\nindex 60e0bce..047f0dc 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/transport/IndexPack.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/transport/IndexPack.java\n@@ -49,6 +49,7 @@ import java.util.ArrayList;\n import java.util.Arrays;\n import java.util.HashMap;\n import java.util.List;\n+import java.util.zip.CRC32;\n import java.util.zip.DataFormatException;\n import java.util.zip.Deflater;\n import java.util.zip.Inflater;\n@@ -136,6 +137,8 @@ public class IndexPack {\n \n \tprivate int entryCount;\n \n+\tprivate final CRC32 crc = new CRC32();\n+\n \tprivate ObjectIdMap<ArrayList<UnresolvedDelta>> baseById;\n \n \tprivate HashMap<Long, ArrayList<UnresolvedDelta>> baseByPos;\n@@ -282,13 +285,15 @@ public class IndexPack {\n \t}\n \n \tprivate void resolveDeltas(final PackedObjectInfo oe) throws IOException {\n+\t\tfinal int oldCRC = oe.getCRC();\n \t\tif (baseById.containsKey(oe)\n \t\t\t\t|| baseByPos.containsKey(new Long(oe.getOffset())))\n-\t\t\tresolveDeltas(oe.getOffset(), Constants.OBJ_BAD, null, oe);\n+\t\t\tresolveDeltas(oe.getOffset(), oldCRC, Constants.OBJ_BAD, null, oe);\n \t}\n \n-\tprivate void resolveDeltas(final long pos, int type, byte[] data,\n-\t\t\tPackedObjectInfo oe) throws IOException {\n+\tprivate void resolveDeltas(final long pos, final int oldCRC, int type,\n+\t\t\tbyte[] data, PackedObjectInfo oe) throws IOException {\n+\t\tcrc.reset();\n \t\tposition(pos);\n \t\tint c = readFromFile();\n \t\tfinal int typeCode = (c >> 4) & 7;\n@@ -309,14 +314,14 @@ public class IndexPack {\n \t\t\tdata = inflateFromFile((int) sz);\n \t\t\tbreak;\n \t\tcase Constants.OBJ_OFS_DELTA: {\n-\t\t\tc = readFromInput() & 0xff;\n+\t\t\tc = readFromFile() & 0xff;\n \t\t\twhile ((c & 128) != 0)\n-\t\t\t\tc = readFromInput() & 0xff;\n+\t\t\t\tc = readFromFile() & 0xff;\n \t\t\tdata = BinaryDelta.apply(data, inflateFromFile((int) sz));\n \t\t\tbreak;\n \t\t}\n \t\tcase Constants.OBJ_REF_DELTA: {\n-\t\t\tfillFromInput(20);\n+\t\t\tcrc.update(buf, fillFromFile(20), 20);\n \t\t\tuse(20);\n \t\t\tdata = BinaryDelta.apply(data, inflateFromFile((int) sz));\n \t\t\tbreak;\n@@ -325,6 +330,9 @@ public class IndexPack {\n \t\t\tthrow new IOException(\"Unknown object type \" + typeCode + \".\");\n \t\t}\n \n+\t\tfinal int crc32 = (int) crc.getValue();\n+\t\tif (oldCRC != crc32)\n+\t\t\tthrow new IOException(\"Corruption detected re-reading at \" + pos);\n \t\tif (oe == null) {\n \t\t\tobjectDigest.update(Constants.encodedTypeString(type));\n \t\t\tobjectDigest.update((byte) ' ');\n@@ -332,7 +340,8 @@ public class IndexPack {\n \t\t\tobjectDigest.update((byte) 0);\n \t\t\tobjectDigest.update(data);\n \t\t\ttempObjectId.fromRaw(objectDigest.digest(), 0);\n-\t\t\toe = new PackedObjectInfo(pos, tempObjectId);\n+\n+\t\t\toe = new PackedObjectInfo(pos, crc32, tempObjectId);\n \t\t\tentries[entryCount++] = oe;\n \t\t}\n \n@@ -349,20 +358,24 @@ public class IndexPack {\n \t\t\t\tfinal UnresolvedDelta ad = a.get(ai);\n \t\t\t\tfinal UnresolvedDelta bd = b.get(bi);\n \t\t\t\tif (ad.position < bd.position) {\n-\t\t\t\t\tresolveDeltas(ad.position, type, data, null);\n+\t\t\t\t\tresolveDeltas(ad.position, ad.crc, type, data, null);\n \t\t\t\t\tai++;\n \t\t\t\t} else {\n-\t\t\t\t\tresolveDeltas(bd.position, type, data, null);\n+\t\t\t\t\tresolveDeltas(bd.position, bd.crc, type, data, null);\n \t\t\t\t\tbi++;\n \t\t\t\t}\n \t\t\t}\n \t\t}\n \t\tif (a != null)\n-\t\t\twhile (ai < a.size())\n-\t\t\t\tresolveDeltas(a.get(ai++).position, type, data, null);\n+\t\t\twhile (ai < a.size()) {\n+\t\t\t\tfinal UnresolvedDelta ad = a.get(ai++);\n+\t\t\t\tresolveDeltas(ad.position, ad.crc, type, data, null);\n+\t\t\t}\n \t\tif (b != null)\n-\t\t\twhile (bi < b.size())\n-\t\t\t\tresolveDeltas(b.get(bi++).position, type, data, null);\n+\t\t\twhile (bi < b.size()) {\n+\t\t\t\tfinal UnresolvedDelta bd = b.get(bi++);\n+\t\t\t\tresolveDeltas(bd.position, bd.crc, type, data, null);\n+\t\t\t}\n \t}\n \n \tprivate void fixThinPack(final ProgressMonitor progress) throws IOException {\n@@ -377,10 +390,11 @@ public class IndexPack {\n \t\t\tfinal int typeCode = ldr.getType();\n \t\t\tfinal PackedObjectInfo oe;\n \n-\t\t\toe = new PackedObjectInfo(end, baseId);\n+\t\t\tcrc.reset();\n+\t\t\twriteWhole(def, typeCode, data);\n+\t\t\toe = new PackedObjectInfo(end, (int) crc.getValue(), baseId);\n \t\t\tentries[entryCount++] = oe;\n \t\t\tpackOut.seek(end);\n-\t\t\twriteWhole(def, typeCode, data);\n \t\t\tend = packOut.getFilePointer();\n \n \t\t\tresolveChildDeltas(oe.getOffset(), typeCode, data, oe);\n@@ -403,12 +417,16 @@ public class IndexPack {\n \t\t\tbuf[hdrlen++] = (byte) (sz & 0x7f);\n \t\t\tsz >>>= 7;\n \t\t}\n+\t\tcrc.update(buf, 0, hdrlen);\n \t\tpackOut.write(buf, 0, hdrlen);\n \t\tdef.reset();\n \t\tdef.setInput(data);\n \t\tdef.finish();\n-\t\twhile (!def.finished())\n-\t\t\tpackOut.write(buf, 0, def.deflate(buf));\n+\t\twhile (!def.finished()) {\n+\t\t\tfinal int datlen = def.deflate(buf);\n+\t\t\tcrc.update(buf, 0, datlen);\n+\t\t\tpackOut.write(buf, 0, datlen);\n+\t\t}\n \t}\n \n \tprivate void fixHeaderFooter() throws IOException {\n@@ -493,6 +511,7 @@ public class IndexPack {\n \tprivate void indexOneObject() throws IOException {\n \t\tfinal long pos = position();\n \n+\t\tcrc.reset();\n \t\tint c = readFromInput();\n \t\tfinal int typeCode = (c >> 4) & 7;\n \t\tlong sz = c & 15;\n@@ -511,11 +530,11 @@ public class IndexPack {\n \t\t\twhole(typeCode, pos, sz);\n \t\t\tbreak;\n \t\tcase Constants.OBJ_OFS_DELTA: {\n-\t\t\tc = readFromInput() & 0xff;\n+\t\t\tc = readFromInput();\n \t\t\tlong ofs = c & 127;\n \t\t\twhile ((c & 128) != 0) {\n \t\t\t\tofs += 1;\n-\t\t\t\tc = readFromInput() & 0xff;\n+\t\t\t\tc = readFromInput();\n \t\t\t\tofs <<= 7;\n \t\t\t\tofs += (c & 127);\n \t\t\t}\n@@ -525,25 +544,24 @@ public class IndexPack {\n \t\t\t\tr = new ArrayList<UnresolvedDelta>(8);\n \t\t\t\tbaseByPos.put(base, r);\n \t\t\t}\n-\t\t\tr.add(new UnresolvedDelta(pos));\n-\t\t\tdeltaCount++;\n \t\t\tinflateFromInput(false);\n+\t\t\tr.add(new UnresolvedDelta(pos, (int) crc.getValue()));\n+\t\t\tdeltaCount++;\n \t\t\tbreak;\n \t\t}\n \t\tcase Constants.OBJ_REF_DELTA: {\n \t\t\tc = fillFromInput(20);\n-\t\t\tfinal byte[] ref = new byte[20];\n-\t\t\tSystem.arraycopy(buf, c, ref, 0, 20);\n+\t\t\tcrc.update(buf, c, 20);\n+\t\t\tfinal ObjectId base = ObjectId.fromRaw(buf, c);\n \t\t\tuse(20);\n-\t\t\tfinal ObjectId base = ObjectId.fromRaw(ref);\n \t\t\tArrayList<UnresolvedDelta> r = baseById.get(base);\n \t\t\tif (r == null) {\n \t\t\t\tr = new ArrayList<UnresolvedDelta>(8);\n \t\t\t\tbaseById.put(base, r);\n \t\t\t}\n-\t\t\tr.add(new UnresolvedDelta(pos));\n-\t\t\tdeltaCount++;\n \t\t\tinflateFromInput(false);\n+\t\t\tr.add(new UnresolvedDelta(pos, (int) crc.getValue()));\n+\t\t\tdeltaCount++;\n \t\t\tbreak;\n \t\t}\n \t\tdefault:\n@@ -559,7 +577,9 @@ public class IndexPack {\n \t\tobjectDigest.update((byte) 0);\n \t\tinflateFromInput(true);\n \t\ttempObjectId.fromRaw(objectDigest.digest(), 0);\n-\t\tentries[entryCount++] = new PackedObjectInfo(pos, tempObjectId);\n+\n+\t\tfinal int crc32 = (int) crc.getValue();\n+\t\tentries[entryCount++] = new PackedObjectInfo(pos, crc32, tempObjectId);\n \t}\n \n \t// Current position of {@link #bOffset} within the entire file.\n@@ -579,15 +599,19 @@ public class IndexPack {\n \t\tif (bAvail == 0)\n \t\t\tfillFromInput(1);\n \t\tbAvail--;\n-\t\treturn buf[bOffset++] & 0xff;\n+\t\tfinal int b = buf[bOffset++] & 0xff;\n+\t\tcrc.update(b);\n+\t\treturn b;\n \t}\n \n \t// Consume exactly one byte from the buffer and return it.\n \tprivate int readFromFile() throws IOException {\n \t\tif (bAvail == 0)\n-\t\t\tfillFromFile();\n+\t\t\tfillFromFile(1);\n \t\tbAvail--;\n-\t\treturn buf[bOffset++] & 0xff;\n+\t\tfinal int b = buf[bOffset++] & 0xff;\n+\t\tcrc.update(b);\n+\t\treturn b;\n \t}\n \n \t// Consume cnt bytes from the buffer.\n@@ -615,13 +639,21 @@ public class IndexPack {\n \t}\n \n \t// Ensure at least need bytes are available in in {@link #buf}.\n-\tprivate int fillFromFile() throws IOException {\n-\t\tif (bAvail == 0) {\n-\t\t\tfinal int next = packOut.read(buf, 0, buf.length);\n+\tprivate int fillFromFile(final int need) throws IOException {\n+\t\tif (bAvail < need) {\n+\t\t\tint next = bOffset + bAvail;\n+\t\t\tint free = buf.length - next;\n+\t\t\tif (free + bAvail < need) {\n+\t\t\t\tif (bAvail > 0)\n+\t\t\t\t\tSystem.arraycopy(buf, bOffset, buf, 0, bAvail);\n+\t\t\t\tbOffset = 0;\n+\t\t\t\tnext = bAvail;\n+\t\t\t\tfree = buf.length - next;\n+\t\t\t}\n+\t\t\tnext = packOut.read(buf, next, free);\n \t\t\tif (next <= 0)\n \t\t\t\tthrow new EOFException(\"Packfile is truncated.\");\n-\t\t\tbAvail = next;\n-\t\t\tbOffset = 0;\n+\t\t\tbAvail += next;\n \t\t}\n \t\treturn bOffset;\n \t}\n@@ -642,11 +674,15 @@ public class IndexPack {\n \t\ttry {\n \t\t\tfinal byte[] dst = objectData;\n \t\t\tint n = 0;\n+\t\t\tint p = -1;\n \t\t\twhile (!inf.finished()) {\n \t\t\t\tif (inf.needsInput()) {\n-\t\t\t\t\tfinal int p = fillFromInput(1);\n+\t\t\t\t\tif (p >= 0) {\n+\t\t\t\t\t\tcrc.update(buf, p, bAvail);\n+\t\t\t\t\t\tuse(bAvail);\n+\t\t\t\t\t}\n+\t\t\t\t\tp = fillFromInput(1);\n \t\t\t\t\tinf.setInput(buf, p, bAvail);\n-\t\t\t\t\tuse(bAvail);\n \t\t\t\t}\n \n \t\t\t\tint free = dst.length - n;\n@@ -661,7 +697,11 @@ public class IndexPack {\n \t\t\t}\n \t\t\tif (digest)\n \t\t\t\tobjectDigest.update(dst, 0, n);\n-\t\t\tuse(-inf.getRemaining());\n+\t\t\tn = bAvail - inf.getRemaining();\n+\t\t\tif (n > 0) {\n+\t\t\t\tcrc.update(buf, p, n);\n+\t\t\t\tuse(n);\n+\t\t\t}\n \t\t} catch (DataFormatException dfe) {\n \t\t\tthrow corrupt(dfe);\n \t\t} finally {\n@@ -674,15 +714,23 @@ public class IndexPack {\n \t\ttry {\n \t\t\tfinal byte[] dst = new byte[sz];\n \t\t\tint n = 0;\n+\t\t\tint p = -1;\n \t\t\twhile (!inf.finished()) {\n \t\t\t\tif (inf.needsInput()) {\n-\t\t\t\t\tfinal int p = fillFromFile();\n+\t\t\t\t\tif (p >= 0) {\n+\t\t\t\t\t\tcrc.update(buf, p, bAvail);\n+\t\t\t\t\t\tuse(bAvail);\n+\t\t\t\t\t}\n+\t\t\t\t\tp = fillFromFile(1);\n \t\t\t\t\tinf.setInput(buf, p, bAvail);\n-\t\t\t\t\tuse(bAvail);\n \t\t\t\t}\n \t\t\t\tn += inf.inflate(dst, n, sz - n);\n \t\t\t}\n-\t\t\tuse(-inf.getRemaining());\n+\t\t\tn = bAvail - inf.getRemaining();\n+\t\t\tif (n > 0) {\n+\t\t\t\tcrc.update(buf, p, n);\n+\t\t\t\tuse(n);\n+\t\t\t}\n \t\t\treturn dst;\n \t\t} catch (DataFormatException dfe) {\n \t\t\tthrow corrupt(dfe);\n@@ -699,8 +747,11 @@ public class IndexPack {\n \tprivate static class UnresolvedDelta {\n \t\tfinal long position;\n \n-\t\tUnresolvedDelta(final long headerOffset) {\n+\t\tfinal int crc;\n+\n+\t\tUnresolvedDelta(final long headerOffset, final int crc32) {\n \t\t\tposition = headerOffset;\n+\t\t\tcrc = crc32;\n \t\t}\n \t}\n \ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/transport/PackedObjectInfo.java b/org.spearce.jgit/src/org/spearce/jgit/transport/PackedObjectInfo.java\nindex 58feada..eae34df 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/transport/PackedObjectInfo.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/transport/PackedObjectInfo.java\n@@ -51,9 +51,13 @@ import org.spearce.jgit.lib.ObjectId;\n public class PackedObjectInfo extends ObjectId {\n \tprivate long offset;\n \n-\tPackedObjectInfo(final long headerOffset, final AnyObjectId id) {\n+\tprivate int crc;\n+\n+\tPackedObjectInfo(final long headerOffset, final int packedCRC,\n+\t\t\tfinal AnyObjectId id) {\n \t\tsuper(id);\n \t\toffset = headerOffset;\n+\t\tcrc = packedCRC;\n \t}\n \n \t/**\n@@ -83,4 +87,23 @@ public class PackedObjectInfo extends ObjectId {\n \tpublic void setOffset(final long offset) {\n \t\tthis.offset = offset;\n \t}\n+\n+\t/**\n+\t * @return the 32 bit CRC checksum for the packed data.\n+\t */\n+\tpublic int getCRC() {\n+\t\treturn crc;\n+\t}\n+\n+\t/**\n+\t * Record the 32 bit CRC checksum for the packed data.\n+\t * \n+\t * @param crc\n+\t *            checksum of all packed data (including object type code,\n+\t *            inflated length and delta base reference) as computed by\n+\t *            {@link java.util.zip.CRC32}.\n+\t */\n+\tpublic void setCRC(final int crc) {\n+\t\tthis.crc = crc;\n+\t}\n }\n-- \n1.5.6.74.g8a5e\n"},{"id":"80817","messageId":"1214273408-70793-10-git-send-email-spearce@spearce.org","threadId":"14113","inReplyTo":"1214273408-70793-9-git-send-email-spearce@spearce.org","subject":"[JGIT PATCH 09/10] Add support for writing pack index v2 files","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2008-06-24T02:10:07Z","receivedAt":"2008-06-24T02:10:07Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"The v2 format is more robust for delta reuse as it has a CRC\nelement that covers the entire packed representation, permitting\nmore efficient delta-reuse during packing.  It also can address\nobjects in pack files larger than 4 GB, making it a better format\nfor the future.\n\nSigned-off-by: Shawn O. Pearce <spearce@spearce.org>\n---\n .../src/org/spearce/jgit/lib/PackIndexWriter.java  |   21 ++++\n .../org/spearce/jgit/lib/PackIndexWriterV2.java    |  101 ++++++++++++++++++++\n .../src/org/spearce/jgit/pgm/IndexPack.java        |    4 +\n .../src/org/spearce/jgit/transport/IndexPack.java  |   22 ++++-\n 4 files changed, 146 insertions(+), 2 deletions(-)\n create mode 100644 org.spearce.jgit/src/org/spearce/jgit/lib/PackIndexWriterV2.java\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/PackIndexWriter.java b/org.spearce.jgit/src/org/spearce/jgit/lib/PackIndexWriter.java\nindex c9b27d2..2d9d822 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/lib/PackIndexWriter.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/PackIndexWriter.java\n@@ -122,6 +122,8 @@ public abstract class PackIndexWriter {\n \t\tswitch (version) {\n \t\tcase 1:\n \t\t\treturn new PackIndexWriterV1(dst);\n+\t\tcase 2:\n+\t\t\treturn new PackIndexWriterV2(dst);\n \t\tdefault:\n \t\t\tthrow new IllegalArgumentException(\n \t\t\t\t\t\"Unsupported pack index version \" + version);\n@@ -203,6 +205,25 @@ public abstract class PackIndexWriter {\n \tprotected abstract void writeImpl() throws IOException;\n \n \t/**\n+\t * Output the version 2 (and later) TOC header, with version number.\n+\t * <p>\n+\t * Post version 1 all index files start with a TOC header that makes the\n+\t * file an invalid version 1 file, and then includes the version number.\n+\t * This header is necessary to recognize a version 1 from a version 2\n+\t * formatted index.\n+\t * \n+\t * @param version\n+\t *            version number of this index format being written.\n+\t * @throws IOException\n+\t *             an error occurred while writing to the output stream.\n+\t */\n+\tprotected void writeTOC(final int version) throws IOException {\n+\t\tout.write(TOC);\n+\t\tNB.encodeInt32(tmp, 0, version);\n+\t\tout.write(tmp, 0, 4);\n+\t}\n+\n+\t/**\n \t * Output the standard 256 entry first-level fan-out table.\n \t * <p>\n \t * The fan-out table is 4 KB in size, holding 256 32-bit unsigned integer\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/PackIndexWriterV2.java b/org.spearce.jgit/src/org/spearce/jgit/lib/PackIndexWriterV2.java\nnew file mode 100644\nindex 0000000..8fa4d1a\n--- /dev/null\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/PackIndexWriterV2.java\n@@ -0,0 +1,101 @@\n+/*\n+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>\n+ *\n+ * All rights reserved.\n+ *\n+ * Redistribution and use in source and binary forms, with or\n+ * without modification, are permitted provided that the following\n+ * conditions are met:\n+ *\n+ * - Redistributions of source code must retain the above copyright\n+ *   notice, this list of conditions and the following disclaimer.\n+ *\n+ * - Redistributions in binary form must reproduce the above\n+ *   copyright notice, this list of conditions and the following\n+ *   disclaimer in the documentation and/or other materials provided\n+ *   with the distribution.\n+ *\n+ * - Neither the name of the Git Development Community nor the\n+ *   names of its contributors may be used to endorse or promote\n+ *   products derived from this software without specific prior\n+ *   written permission.\n+ *\n+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND\n+ * CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES,\n+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\n+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+package org.spearce.jgit.lib;\n+\n+import java.io.IOException;\n+import java.io.OutputStream;\n+\n+import org.spearce.jgit.transport.PackedObjectInfo;\n+import org.spearce.jgit.util.NB;\n+\n+/**\n+ * Creates the version 2 pack table of contents files.\n+ * \n+ * @see PackIndexWriter\n+ * @see PackIndexV2\n+ */\n+class PackIndexWriterV2 extends PackIndexWriter {\n+\tPackIndexWriterV2(final OutputStream dst) {\n+\t\tsuper(dst);\n+\t}\n+\n+\t@Override\n+\tprotected void writeImpl() throws IOException {\n+\t\twriteTOC(2);\n+\t\twriteFanOutTable();\n+\t\twriteObjectNames();\n+\t\twriteCRCs();\n+\t\twriteOffset32();\n+\t\twriteOffset64();\n+\t\twriteChecksumFooter();\n+\t}\n+\n+\tprivate void writeObjectNames() throws IOException {\n+\t\tfor (final PackedObjectInfo oe : entries)\n+\t\t\toe.copyRawTo(out);\n+\t}\n+\n+\tprivate void writeCRCs() throws IOException {\n+\t\tfor (final PackedObjectInfo oe : entries) {\n+\t\t\tNB.encodeInt32(tmp, 0, oe.getCRC());\n+\t\t\tout.write(tmp, 0, 4);\n+\t\t}\n+\t}\n+\n+\tprivate void writeOffset32() throws IOException {\n+\t\tint o64 = 0;\n+\t\tfor (final PackedObjectInfo oe : entries) {\n+\t\t\tfinal long o = oe.getOffset();\n+\t\t\tif (o < Integer.MAX_VALUE)\n+\t\t\t\tNB.encodeInt32(tmp, 0, (int) o);\n+\t\t\telse\n+\t\t\t\tNB.encodeInt32(tmp, 0, (1 << 31) | o64++);\n+\t\t\tout.write(tmp, 0, 4);\n+\t\t}\n+\t}\n+\n+\tprivate void writeOffset64() throws IOException {\n+\t\tfor (final PackedObjectInfo oe : entries) {\n+\t\t\tfinal long o = oe.getOffset();\n+\t\t\tif (o > Integer.MAX_VALUE) {\n+\t\t\t\tNB.encodeInt64(tmp, 0, o);\n+\t\t\t\tout.write(tmp, 0, 8);\n+\t\t\t}\n+\t\t}\n+\t}\n+}\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/pgm/IndexPack.java b/org.spearce.jgit/src/org/spearce/jgit/pgm/IndexPack.java\nindex 5a82a35..60926c1 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/pgm/IndexPack.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/pgm/IndexPack.java\n@@ -47,10 +47,13 @@ class IndexPack extends TextBuiltin {\n \tvoid execute(final String[] args) throws Exception {\n \t\tboolean fixThin = false;\n \t\tint argi = 0;\n+\t\tint version = 0;\n \t\tfor (; argi < args.length; argi++) {\n \t\t\tfinal String a = args[argi];\n \t\t\tif (\"--fix-thin\".equals(a))\n \t\t\t\tfixThin = true;\n+\t\t\telse if (a.startsWith(\"--index-version=\"))\n+\t\t\t\tversion = Integer.parseInt(a.substring(a.indexOf('=') + 1));\n \t\t\telse if (\"--\".equals(a)) {\n \t\t\t\targi++;\n \t\t\t\tbreak;\n@@ -69,6 +72,7 @@ class IndexPack extends TextBuiltin {\n \t\tin = new BufferedInputStream(System.in);\n \t\tip = new org.spearce.jgit.transport.IndexPack(db, in, base);\n \t\tip.setFixThin(fixThin);\n+\t\tip.setIndexVersion(version);\n \t\tip.index(new TextProgressMonitor());\n \t}\n }\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/transport/IndexPack.java b/org.spearce.jgit/src/org/spearce/jgit/transport/IndexPack.java\nindex 047f0dc..06ef7cc 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/transport/IndexPack.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/transport/IndexPack.java\n@@ -125,6 +125,8 @@ public class IndexPack {\n \n \tprivate boolean fixThin;\n \n+\tprivate int outputVersion;\n+\n \tprivate final File dstPack;\n \n \tprivate final File dstIdx;\n@@ -185,6 +187,18 @@ public class IndexPack {\n \t}\n \n \t/**\n+\t * Set the pack index file format version this instance will create.\n+\t * \n+\t * @param version\n+\t *            the version to write. The special version 0 designates the\n+\t *            oldest (most compatible) format available for the objects.\n+\t * @see PackIndexWriter\n+\t */\n+\tpublic void setIndexVersion(final int version) {\n+\t\toutputVersion = version;\n+\t}\n+\n+\t/**\n \t * Configure this index pack instance to make a thin pack complete.\n \t * <p>\n \t * Thin packs are sometimes used during network transfers to allow a delta\n@@ -466,8 +480,12 @@ public class IndexPack {\n \n \t\tfinal FileOutputStream os = new FileOutputStream(dstIdx);\n \t\ttry {\n-\t\t\tPackIndexWriter.createOldestPossible(os, list)\n-\t\t\t\t\t.write(list, packcsum);\n+\t\t\tfinal PackIndexWriter iw;\n+\t\t\tif (outputVersion <= 0)\n+\t\t\t\tiw = PackIndexWriter.createOldestPossible(os, list);\n+\t\t\telse\n+\t\t\t\tiw = PackIndexWriter.createVersion(os, outputVersion);\n+\t\t\tiw.write(list, packcsum);\n \t\t} finally {\n \t\t\tos.close();\n \t\t}\n-- \n1.5.6.74.g8a5e\n"},{"id":"80814","messageId":"1214273408-70793-11-git-send-email-spearce@spearce.org","threadId":"14113","inReplyTo":"1214273408-70793-10-git-send-email-spearce@spearce.org","subject":"[JGIT PATCH 10/10] Default IndexPack to honor pack.indexversion configuration","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2008-06-24T02:10:08Z","receivedAt":"2008-06-24T02:10:08Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Users may already desire to create only v2 pack index files, as\nthe extra CRC code makes repacking faster due to quicker delta\nreuse code paths being available.  However we still must default\nto version 0 to select oldest version available to improve our\nchanges of being compatible with really old Git executables.\n\nSigned-off-by: Shawn O. Pearce <spearce@spearce.org>\n---\n .../src/org/spearce/jgit/lib/CoreConfig.java       |   11 +++++++++++\n .../src/org/spearce/jgit/transport/IndexPack.java  |    4 +++-\n 2 files changed, 14 insertions(+), 1 deletions(-)\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/CoreConfig.java b/org.spearce.jgit/src/org/spearce/jgit/lib/CoreConfig.java\nindex 01d4210..2dd8aea 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/lib/CoreConfig.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/CoreConfig.java\n@@ -48,8 +48,11 @@ public class CoreConfig {\n \n \tprivate final int compression;\n \n+\tprivate final int packIndexVersion;\n+\n \tCoreConfig(final RepositoryConfig rc) {\n \t\tcompression = rc.getInt(\"core\", \"compression\", DEFAULT_COMPRESSION);\n+\t\tpackIndexVersion = rc.getInt(\"pack\", \"indexversion\", 0);\n \t}\n \n \t/**\n@@ -59,4 +62,12 @@ public class CoreConfig {\n \tpublic int getCompression() {\n \t\treturn compression;\n \t}\n+\n+\t/**\n+\t * @return the preferred pack index file format; 0 for oldest possible.\n+\t * @see org.spearce.jgit.transport.IndexPack\n+\t */\n+\tpublic int getPackIndexVersion() {\n+\t\treturn packIndexVersion;\n+\t}\n }\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/transport/IndexPack.java b/org.spearce.jgit/src/org/spearce/jgit/transport/IndexPack.java\nindex 06ef7cc..8083cc8 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/transport/IndexPack.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/transport/IndexPack.java\n@@ -102,7 +102,9 @@ public class IndexPack {\n \t\tfinal File base;\n \n \t\tbase = new File(objdir, n.substring(0, n.length() - suffix.length()));\n-\t\treturn new IndexPack(db, is, base);\n+\t\tfinal IndexPack ip = new IndexPack(db, is, base);\n+\t\tip.setIndexVersion(db.getConfig().getCore().getPackIndexVersion());\n+\t\treturn ip;\n \t}\n \n \tprivate final Repository repo;\n-- \n1.5.6.74.g8a5e\n"},{"id":"81011","messageId":"200806250048.29892.robin.rosenberg.lists@dewire.com","threadId":"14113","inReplyTo":"1214273408-70793-1-git-send-email-spearce@spearce.org","subject":"Re: [JGIT PATCH 00/10] Support writing pack index version 2","fromName":"Robin Rosenberg","fromEmail":"robin.rosenberg.lists@dewire.com","sentAt":"2008-06-24T22:48:29Z","receivedAt":"2008-06-24T22:48:29Z","isPatch":true,"sender":{"key":"robin.rosenberg@dewire.com","avatar":"https://avatars.githubusercontent.com/u/46357?v=4"},"body":"\nOcular review looks fine, but nevertheless some tests break.\n\n-- robin\n\norg.spearce.jgit--All-Tests\norg.spearce.jgit.lib.PackIndexV2Test\ntestIteratorMethodsContract(org.spearce.jgit.lib.PackIndexV2Test)\njava.io.IOException: Unreadable pack index: /home/me/SW/EGIT.contrib/org.spearce.jgit.test/tst/pack-34be9032ac282b11fa9babdc2b2a93ca996c9c2f.idxV2\n\tat org.spearce.jgit.lib.PackIndex.open(PackIndex.java:95)\n\tat org.spearce.jgit.lib.PackIndexTest.setUp(PackIndexTest.java:54)\n\tat junit.framework.TestCase.runBare(TestCase.java:128)\n\tat junit.framework.TestResult$1.protect(TestResult.java:106)\n\tat junit.framework.TestResult.runProtected(TestResult.java:124)\n\tat junit.framework.TestResult.run(TestResult.java:109)\n\tat junit.framework.TestCase.run(TestCase.java:120)\n\tat junit.framework.TestSuite.runTest(TestSuite.java:230)\n\tat junit.framework.TestSuite.run(TestSuite.java:225)\n\tat org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestReference.run(JUnit3TestReference.java:130)\n\tat org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)\n\tat org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)\n\tat org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)\n\tat org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)\n\tat org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)\nCaused by: java.io.EOFException: Short read of block.\n\tat org.spearce.jgit.util.NB.readFully(NB.java:67)\n\tat org.spearce.jgit.lib.PackIndexV1.<init>(PackIndexV1.java:75)\n\tat org.spearce.jgit.lib.PackIndex.open(PackIndex.java:91)\n\t... 14 more\n\ntestIteratorReturnedValues1(org.spearce.jgit.lib.PackIndexV2Test) \n\tsame trace\n\ntestCompareEntriesOffsetsWithFindOffsets(org.spearce.jgit.lib.PackIndexV2Test)\n\tsame trace\n\ntestIteratorReturnedValues2(org.spearce.jgit.lib.PackIndexV2Test)\n\tsame trace\n\nTogether with Marek's packwrite patches the list gets even longer (his patches alone are \"green\"). I'm\nnot including them here.\n\n-- robin\n"},{"id":"81051","messageId":"20080625035409.GY11793@spearce.org","threadId":"14113","inReplyTo":"200806250048.29892.robin.rosenberg.lists@dewire.com","subject":"Re: [JGIT PATCH 00/10] Support writing pack index version 2","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2008-06-25T03:54:09Z","receivedAt":"2008-06-25T03:54:09Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Robin Rosenberg <robin.rosenberg.lists@dewire.com> wrote:\n> \n> Ocular review looks fine, but nevertheless some tests break.\n\nDammit.\n \n> org.spearce.jgit.lib.PackIndexV2Test\n> testIteratorMethodsContract(org.spearce.jgit.lib.PackIndexV2Test)\n> java.io.IOException: Unreadable pack index: /home/me/SW/EGIT.contrib/org.spearce.jgit.test/tst/pack-34be9032ac282b11fa9babdc2b2a93ca996c9c2f.idxV2\n> \tat org.spearce.jgit.lib.PackIndex.open(PackIndex.java:95)\n...\n> \tat org.spearce.jgit.lib.PackIndexV1.<init>(PackIndexV1.java:75)\n\nYea, OK, I know what that is.  I busted PackIndex.isTOC.\n\nI asked it to compare a 4 byte array (TOC only) to an 8 byte array\n(TOC + version) and of course 4 != 8 so it fails.  Thus all V2\nindex files look like V1 files.  Only they aren't; and then all\nhell breaks loose when we start treating parts of the V2 index as\ndifferent sections of the V1 index.\n\nI'll post a replacement patch in a minute.\n\n> Together with Marek's packwrite patches the list gets even longer (his patches alone are \"green\"). I'm\n> not including them here.\n\nThat's because Marek's branch includes additional tests for features\nhe added to PackIndexV2.  But all PackIndexV2 reading is busted.\n\n-- \nShawn.\n"},{"id":"81052","messageId":"20080625040148.GZ11793@spearce.org","threadId":"14113","inReplyTo":"1214273408-70793-7-git-send-email-spearce@spearce.org","subject":"[JGIT PATCH 06/10 v2] Reuse the magic tOc constant for pack index headers","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2008-06-25T04:01:48Z","receivedAt":"2008-06-25T04:01:48Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"We need this constant to detect version 2 index files at read time,\nbut we also need it to create version 2 index files.\n\nSigned-off-by: Shawn O. Pearce <spearce@spearce.org>\n---\n\n Fixed isTOC test to return true when h.length == 8, which\n is always the case as it has both the TOC and the version.\n\n Also rebased into my branch:\n \n   repo.or.cz:/srv/git/egit/spearce.git index-v2\n\n With this patch in the series all tests pass again.\n\n .../src/org/spearce/jgit/lib/PackIndex.java        |    6 +++++-\n .../src/org/spearce/jgit/lib/PackIndexWriter.java  |    3 +++\n 2 files changed, 8 insertions(+), 1 deletions(-)\n\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/PackIndex.java b/org.spearce.jgit/src/org/spearce/jgit/lib/PackIndex.java\nindex 3935d4f..c5718fa 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/lib/PackIndex.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/PackIndex.java\n@@ -104,7 +104,11 @@ public abstract class PackIndex implements Iterable<PackIndex.MutableEntry> {\n \t}\n \n \tprivate static boolean isTOC(final byte[] h) {\n-\t\treturn h[0] == -1 && h[1] == 't' && h[2] == 'O' && h[3] == 'c';\n+\t\tfinal byte[] toc = PackIndexWriter.TOC;\n+\t\tfor (int i = 0; i < toc.length; i++)\n+\t\t\tif (h[i] != toc[i])\n+\t\t\t\treturn false;\n+\t\treturn true;\n \t}\n \n \t/**\ndiff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/PackIndexWriter.java b/org.spearce.jgit/src/org/spearce/jgit/lib/PackIndexWriter.java\nindex 473e6cf..c9b27d2 100644\n--- a/org.spearce.jgit/src/org/spearce/jgit/lib/PackIndexWriter.java\n+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/PackIndexWriter.java\n@@ -55,6 +55,9 @@ import org.spearce.jgit.util.NB;\n  * to the byte offset within the pack where the object's data can be read.\n  */\n public abstract class PackIndexWriter {\n+\t/** Magic constant indicating post-version 1 format. */\n+\tprotected static final byte[] TOC = { -1, 't', 'O', 'c' };\n+\n \t/**\n \t * Create a new writer for the oldest (most widely understood) format.\n \t * <p>\n-- \n1.5.6.74.g8a5e\n\n-- \nShawn.\n"}]}