]> source.dussan.org Git - jgit.git/commitdiff
Try really hard to load a commit or tag 62/1362/1
authorShawn O. Pearce <spearce@spearce.org>
Fri, 20 Aug 2010 16:25:47 +0000 (09:25 -0700)
committerShawn O. Pearce <spearce@spearce.org>
Sat, 21 Aug 2010 00:38:52 +0000 (17:38 -0700)
When we need the canonical form of a commit or a tag in order to
parse it into our RevCommit or RevTag fields, we really need it as a
single contiguous byte array.  However the ObjectDatabase may choose
to give us a large loader.  In general commits or tags are always
under the several MiB limit, so even if the loader calls it "large"
we should still be able to afford the JVM heap memory required to
get a single byte array.  Coerce even large loaders into a single
byte array anyway.

Change-Id: I04efbaa7b31c5f4b0a68fc074821930b1132cfcf
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevObject.java

index 85191224df062aecfebb8397b136ec11b32c8812..b31bc37687856a84b3409d146238ed8cdac2420e 100644 (file)
@@ -47,15 +47,39 @@ import java.io.IOException;
 
 import org.eclipse.jgit.errors.CorruptObjectException;
 import org.eclipse.jgit.errors.IncorrectObjectTypeException;
+import org.eclipse.jgit.errors.LargeObjectException;
 import org.eclipse.jgit.errors.MissingObjectException;
 import org.eclipse.jgit.lib.AnyObjectId;
 import org.eclipse.jgit.lib.Constants;
 import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.ObjectLoader;
+import org.eclipse.jgit.lib.ObjectStream;
+import org.eclipse.jgit.util.IO;
 
 /** Base object type accessed during revision walking. */
 public abstract class RevObject extends ObjectId {
        static final int PARSED = 1;
 
+       static byte[] asByteArray(RevObject obj, ObjectLoader loader) throws IOException {
+               if (loader.isLarge()) {
+                       ObjectStream in = loader.openStream();
+                       try {
+                               long sz = in.getSize();
+                               if (Integer.MAX_VALUE <= sz){
+                                       if (obj != null)
+                                               throw new LargeObjectException(obj.copy());
+                                       throw new LargeObjectException();
+                               }
+                               byte[] buf = new byte[(int) sz];
+                               IO.readFully(in, buf, 0, buf.length);
+                               return buf;
+                       } finally {
+                               in.close();
+                       }
+               }
+               return loader.getCachedBytes();
+       }
+
        int flags;
 
        RevObject(final AnyObjectId name) {
@@ -77,7 +101,7 @@ public abstract class RevObject extends ObjectId {
        final byte[] loadCanonical(final RevWalk walk) throws IOException,
                        MissingObjectException, IncorrectObjectTypeException,
                        CorruptObjectException {
-               return walk.reader.open(this, getType()).getCachedBytes();
+               return asByteArray(this, walk.reader.open(this, getType()));
        }
 
        /**