]> source.dussan.org Git - jgit.git/commitdiff
debug-show-packdelta: Dump a pack delta to the console 12/1112/1
authorShawn O. Pearce <spearce@spearce.org>
Fri, 9 Jul 2010 18:59:55 +0000 (11:59 -0700)
committerShawn O. Pearce <spearce@spearce.org>
Sat, 10 Jul 2010 02:12:32 +0000 (19:12 -0700)
This is a horribly crude application, it doesn't even verify that
the object its dumping is delta encoded.  Its method of getting the
delta is pretty abusive to the public PackWriter API, because right
now we don't want to expose the real internal low-level methods
actually required to do this.

Change-Id: I437a17ceb98708b5603a2061126eb251e82f4ed4
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
org.eclipse.jgit.pgm/META-INF/MANIFEST.MF
org.eclipse.jgit.pgm/META-INF/services/org.eclipse.jgit.pgm.TextBuiltin
org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/ShowPackDelta.java [new file with mode: 0644]
org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/PackOutputStream.java
org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/PackWriter.java

index 0a4376921a1f20f19d5c3dc8cc87340436cbc9f9..d6eac232e152c77b1a34f8d18b9d3b4c9d027371 100644 (file)
@@ -18,6 +18,7 @@ Import-Package: org.eclipse.jgit.api;version="[0.9.0,0.10.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 0d4a140e62c11c5e8efe79e88a114b7f54bf3a11..075cadef7904be0fb49c3fa285cc983665daeb8e 100644 (file)
@@ -30,6 +30,7 @@ org.eclipse.jgit.pgm.debug.RebuildCommitGraph
 org.eclipse.jgit.pgm.debug.ShowCacheTree
 org.eclipse.jgit.pgm.debug.ShowCommands
 org.eclipse.jgit.pgm.debug.ShowDirCache
+org.eclipse.jgit.pgm.debug.ShowPackDelta
 org.eclipse.jgit.pgm.debug.WriteDirCache
 
 org.eclipse.jgit.pgm.eclipse.Iplog
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/ShowPackDelta.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/ShowPackDelta.java
new file mode 100644 (file)
index 0000000..1718ef3
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * 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.pgm.debug;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.zip.InflaterInputStream;
+
+import org.eclipse.jgit.errors.MissingObjectException;
+import org.eclipse.jgit.errors.StoredObjectRepresentationNotAvailableException;
+import org.eclipse.jgit.lib.NullProgressMonitor;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.ObjectReader;
+import org.eclipse.jgit.pgm.TextBuiltin;
+import org.eclipse.jgit.revwalk.RevObject;
+import org.eclipse.jgit.revwalk.RevWalk;
+import org.eclipse.jgit.storage.pack.BinaryDelta;
+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;
+import org.eclipse.jgit.storage.pack.StoredObjectRepresentation;
+import org.eclipse.jgit.util.TemporaryBuffer;
+import org.kohsuke.args4j.Argument;
+
+class ShowPackDelta extends TextBuiltin {
+       @Argument(index = 0)
+       private ObjectId objectId;
+
+       @Override
+       protected void run() throws Exception {
+               ObjectReader reader = db.newObjectReader();
+               RevObject obj = new RevWalk(reader).parseAny(objectId);
+               byte[] delta = getDelta(reader, obj);
+
+               // We're crossing our fingers that this will be a delta. Double
+               // check the size field in the header, it should match.
+               //
+               long size = reader.getObjectSize(obj, obj.getType());
+               try {
+                       if (BinaryDelta.getResultSize(delta) != size)
+                               throw die("Object " + obj.name() + " is not a delta");
+               } catch (ArrayIndexOutOfBoundsException bad) {
+                       throw die("Object " + obj.name() + " is not a delta");
+               }
+
+               out.println(BinaryDelta.format(delta));
+       }
+
+       private byte[] getDelta(ObjectReader reader, RevObject obj)
+                       throws IOException, MissingObjectException,
+                       StoredObjectRepresentationNotAvailableException {
+               ObjectReuseAsIs asis = (ObjectReuseAsIs) reader;
+               ObjectToPack target = asis.newObjectToPack(obj);
+
+               PackWriter pw = new PackWriter(reader) {
+                       @Override
+                       public void select(ObjectToPack otp, StoredObjectRepresentation next) {
+                               otp.select(next);
+                       }
+               };
+
+               ByteArrayOutputStream buf = new ByteArrayOutputStream();
+               asis.selectObjectRepresentation(pw, target);
+               asis.copyObjectAsIs(new PackOutputStream(NullProgressMonitor.INSTANCE,
+                               buf, pw), target);
+
+               // At this point the object header has no delta information,
+               // because it was output as though it were a whole object.
+               // Skip over the header and inflate.
+               //
+               byte[] bufArray = buf.toByteArray();
+               int ptr = 0;
+               while ((bufArray[ptr] & 0x80) != 0)
+                       ptr++;
+               ptr++;
+
+               TemporaryBuffer.Heap raw = new TemporaryBuffer.Heap(bufArray.length);
+               InflaterInputStream inf = new InflaterInputStream(
+                               new ByteArrayInputStream(bufArray, ptr, bufArray.length));
+               raw.copy(inf);
+               inf.close();
+               return raw.toByteArray();
+       }
+}
index a93ac0516a6158106b59e3d149e215438c50068f..92e1a197cdfbd234839dd2ef1ef603a7348ff96b 100644 (file)
@@ -71,11 +71,25 @@ public final class PackOutputStream extends OutputStream {
 
        private byte[] copyBuffer;
 
-       PackOutputStream(final ProgressMonitor writeMonitor,
-                       final OutputStream out, final boolean ofsDelta) {
+       /**
+        * Initialize a pack output stream.
+        * <p>
+        * This constructor is exposed to support debugging the JGit library only.
+        * Application or storage level code should not create a PackOutputStream,
+        * instead use {@link PackWriter}, and let the writer create the stream.
+        *
+        * @param writeMonitor
+        *            monitor to update on object output progress.
+        * @param out
+        *            target stream to receive all object contents.
+        * @param pw
+        *            packer that is going to perform the output.
+        */
+       public PackOutputStream(final ProgressMonitor writeMonitor,
+                       final OutputStream out, final PackWriter pw) {
                this.writeMonitor = writeMonitor;
                this.out = out;
-               this.ofsDelta = ofsDelta;
+               this.ofsDelta = pw.isDeltaBaseAsOffset();
        }
 
        @Override
index cae552831c99dd9dac9eab62a8ff31145b8ef71b..d96d5ddfd2410a61a5660b66c16bf8524b2c9395 100644 (file)
@@ -718,7 +718,7 @@ public class PackWriter {
                        searchForReuse();
 
                final PackOutputStream out = new PackOutputStream(writeMonitor,
-                               packStream, isDeltaBaseAsOffset());
+                               packStream, this);
 
                writeMonitor.beginTask(WRITING_OBJECTS_PROGRESS, getObjectsNumber());
                out.writeFileHeader(PACK_VERSION_GENERATED, getObjectsNumber());