diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/IndexPack.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/IndexPack.java index 7c94767b4..23faa42a2 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/IndexPack.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/IndexPack.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2009, Google Inc. + * Copyright (C) 2008-2010, Google Inc. * Copyright (C) 2007-2008, Robin Rosenberg * Copyright (C) 2008, Shawn O. Pearce * and other copyright owners as documented in the project's IP log. @@ -54,7 +54,10 @@ import java.security.MessageDigest; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.zip.CRC32; import java.util.zip.DataFormatException; import java.util.zip.Deflater; @@ -158,6 +161,8 @@ public static IndexPack create(final Repository db, final InputStream is) private boolean keepEmpty; + private boolean needBaseObjectIds; + private int outputVersion; private final File dstPack; @@ -168,6 +173,8 @@ public static IndexPack create(final Repository db, final InputStream is) private PackedObjectInfo[] entries; + private Set newObjectIds; + private int deltaCount; private int entryCount; @@ -176,6 +183,8 @@ public static IndexPack create(final Repository db, final InputStream is) private ObjectIdSubclassMap baseById; + private Set baseIds; + private LongMap baseByPos; private byte[] objectData; @@ -267,6 +276,54 @@ public void setKeepEmpty(final boolean empty) { keepEmpty = empty; } + /** + * Configure this index pack instance to keep track of new objects. + *

+ * By default an index pack doesn't save the new objects that were created + * when it was instantiated. Setting this flag to {@code true} allows the + * caller to use {@link #getNewObjectIds()} to retrieve that list. + * + * @param b {@code true} to enable keeping track of new objects. + */ + public void setNeedNewObjectIds(boolean b) { + if (b) + newObjectIds = new HashSet(); + else + newObjectIds = null; + } + + private boolean needNewObjectIds() { + return newObjectIds != null; + } + + /** + * Configure this index pack instance to keep track of the objects assumed + * for delta bases. + *

+ * By default an index pack doesn't save the objects that were used as delta + * bases. Setting this flag to {@code true} will allow the caller to + * use {@link #getBaseObjectIds()} to retrieve that list. + * + * @param b {@code true} to enable keeping track of delta bases. + */ + public void setNeedBaseObjectIds(boolean b) { + this.needBaseObjectIds = b; + } + + /** @return the new objects that were sent by the user */ + public Set getNewObjectIds() { + return newObjectIds == null ? + Collections.emptySet() : newObjectIds; + } + + /** + * @return the set of objects the incoming pack assumed for delta purposes + */ + public Set getBaseObjectIds() { + return baseIds == null ? + Collections.emptySet() : baseIds; + } + /** * Configure the checker used to validate received objects. *

@@ -333,6 +390,12 @@ public void index(final ProgressMonitor progress) throws IOException { if (packOut == null) throw new IOException("need packOut"); resolveDeltas(progress); + if (needBaseObjectIds) { + baseIds = new HashSet(); + for (DeltaChain c : baseById) { + baseIds.add(c); + } + } if (entryCount < objectCount) { if (!fixThin) { throw new IOException("pack has " @@ -453,7 +516,7 @@ private void resolveDeltas(final long pos, final int oldCRC, int type, verifySafeObject(tempObjectId, type, data); oe = new PackedObjectInfo(pos, crc32, tempObjectId); - entries[entryCount++] = oe; + addObjectAndTrack(oe); } resolveChildDeltas(pos, type, data, oe); @@ -749,7 +812,7 @@ private void whole(final int type, final long pos, final long sz) verifySafeObject(tempObjectId, type, data); final int crc32 = (int) crc.getValue(); - entries[entryCount++] = new PackedObjectInfo(pos, crc32, tempObjectId); + addObjectAndTrack(new PackedObjectInfo(pos, crc32, tempObjectId)); } private void verifySafeObject(final AnyObjectId id, final int type, @@ -1112,4 +1175,10 @@ private void cleanupTemporaryFiles() { if (!dstPack.delete()) dstPack.deleteOnExit(); } -} + + private void addObjectAndTrack(PackedObjectInfo oe) { + entries[entryCount++] = oe; + if (needNewObjectIds()) + newObjectIds.add(oe); + } +} \ No newline at end of file diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java index 4d63ee68e..8d75f3cb9 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java @@ -153,6 +153,8 @@ public class ReceivePack { private PrintWriter msgs; + private IndexPack ip; + /** The refs we advertised as existing at the start of the connection. */ private Map refs; @@ -171,6 +173,10 @@ public class ReceivePack { /** Lock around the received pack file, while updating refs. */ private PackLock packLock; + private boolean needNewObjectIds; + + private boolean needBaseObjectIds; + /** * Create a new pack receive for an open repository. * @@ -236,6 +242,45 @@ public final Map getAdvertisedRefs() { return refs; } + /** + * Configure this receive pack instance to keep track of the objects assumed + * for delta bases. + *

+ * By default a receive pack doesn't save the objects that were used as + * delta bases. Setting this flag to {@code true} will allow the caller to + * use {@link #getBaseObjectIds()} to retrieve that list. + * + * @param b {@code true} to enable keeping track of delta bases. + */ + public void setNeedBaseObjectIds(boolean b) { + this.needBaseObjectIds = b; + } + + /** + * @return the set of objects the incoming pack assumed for delta purposes + */ + public final Set getBaseObjectIds() { + return ip.getBaseObjectIds(); + } + + /** + * Configure this receive pack instance to keep track of new objects. + *

+ * By default a receive pack doesn't save the new objects that were created + * when it was instantiated. Setting this flag to {@code true} allows the + * caller to use {@link #getNewObjectIds()} to retrieve that list. + * + * @param b {@code true} to enable keeping track of new objects. + */ + public void setNeedNewObjectIds(boolean b) { + this.needNewObjectIds = b; + } + + /** @return the new objects that were sent by the user */ + public final Set getNewObjectIds() { + return ip.getNewObjectIds(); + } + /** * @return true if this class expects a bi-directional pipe opened between * the client and itself. The default is true. @@ -685,8 +730,10 @@ private void receivePack() throws IOException { if (timeoutIn != null) timeoutIn.setTimeout(10 * timeout * 1000); - final IndexPack ip = IndexPack.create(db, rawIn); + ip = IndexPack.create(db, rawIn); ip.setFixThin(true); + ip.setNeedNewObjectIds(needNewObjectIds); + ip.setNeedBaseObjectIds(needBaseObjectIds); ip.setObjectChecking(isCheckReceivedObjects()); ip.index(NullProgressMonitor.INSTANCE);