diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/revwalk/AddToBitmapFilter.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/revwalk/AddToBitmapFilter.java new file mode 100644 index 000000000..3145de184 --- /dev/null +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/revwalk/AddToBitmapFilter.java @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2017, 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.internal.revwalk; + +import org.eclipse.jgit.lib.BitmapIndex.Bitmap; +import org.eclipse.jgit.lib.BitmapIndex.BitmapBuilder; +import org.eclipse.jgit.lib.Constants; +import org.eclipse.jgit.revwalk.filter.RevFilter; +import org.eclipse.jgit.revwalk.RevWalk; +import org.eclipse.jgit.revwalk.RevCommit; +import org.eclipse.jgit.revwalk.RevFlag; + +/** + * A RevFilter that adds the visited commits to {@code bitmap} as a side + * effect. + *
+ * When the walk hits a commit that is part of {@code bitmap}'s + * BitmapIndex, that entire bitmap is ORed into {@code bitmap} and the + * commit and its parents are marked as SEEN so that the walk does not + * have to visit its ancestors. This ensures the walk is very short if + * there is good bitmap coverage. + */ +public class AddToBitmapFilter extends RevFilter { + private final BitmapBuilder bitmap; + + /** + * Create a filter that adds visited commits to the given bitmap. + * + * @param bitmap bitmap to write visited commits to + */ + public AddToBitmapFilter(BitmapBuilder bitmap) { + this.bitmap = bitmap; + } + + @Override + public final boolean include(RevWalk walker, RevCommit cmit) { + Bitmap visitedBitmap; + + if (bitmap.contains(cmit)) { + // already included + } else if ((visitedBitmap = bitmap.getBitmapIndex() + .getBitmap(cmit)) != null) { + bitmap.or(visitedBitmap); + } else { + bitmap.addObject(cmit, Constants.OBJ_COMMIT); + return true; + } + + for (RevCommit p : cmit.getParents()) { + p.add(RevFlag.SEEN); + } + return false; + } + + @Override + public final RevFilter clone() { + throw new UnsupportedOperationException(); + } + + @Override + public final boolean requiresCommitBody() { + return false; + } +} diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/revwalk/AddUnseenToBitmapFilter.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/revwalk/AddUnseenToBitmapFilter.java new file mode 100644 index 000000000..6cb19ba00 --- /dev/null +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/revwalk/AddUnseenToBitmapFilter.java @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2017, 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.internal.revwalk; + +import org.eclipse.jgit.lib.BitmapIndex.Bitmap; +import org.eclipse.jgit.lib.BitmapIndex.BitmapBuilder; +import org.eclipse.jgit.lib.Constants; +import org.eclipse.jgit.revwalk.filter.RevFilter; +import org.eclipse.jgit.revwalk.RevWalk; +import org.eclipse.jgit.revwalk.RevCommit; +import org.eclipse.jgit.revwalk.RevFlag; + +/** + * A RevFilter that adds the visited commits to {@code bitmap} as a side + * effect. + *
+ * When the walk hits a commit that is part of {@code bitmap}'s + * BitmapIndex, that entire bitmap is ORed into {@code bitmap} and the + * commit and its parents are marked as SEEN so that the walk does not + * have to visit its ancestors. This ensures the walk is very short if + * there is good bitmap coverage. + *
+ * Commits named in {@code seen} are considered already seen. If one is + * encountered, that commit and its parents will be marked with the SEEN + * flag to prevent the walk from visiting its ancestors. + */ +public class AddUnseenToBitmapFilter extends RevFilter { + private final BitmapBuilder seen; + private final BitmapBuilder bitmap; + + /** + * Create a filter that adds visited commits to the given bitmap, but does not walk + * through the objects in {@code seen}. + * + * @param seen objects that are already seen + * @param bitmap bitmap to write visited commits to + */ + public AddUnseenToBitmapFilter(BitmapBuilder seen, BitmapBuilder bitmap) { + this.seen = seen; + this.bitmap = bitmap; + } + + @Override + public final boolean include(RevWalk walker, RevCommit cmit) { + Bitmap visitedBitmap; + + if (seen.contains(cmit) || bitmap.contains(cmit)) { + // already seen or included + } else if ((visitedBitmap = bitmap.getBitmapIndex() + .getBitmap(cmit)) != null) { + bitmap.or(visitedBitmap); + } else { + bitmap.addObject(cmit, Constants.OBJ_COMMIT); + return true; + } + + for (RevCommit p : cmit.getParents()) { + p.add(RevFlag.SEEN); + } + return false; + } + + @Override + public final RevFilter clone() { + throw new UnsupportedOperationException(); + } + + @Override + public final boolean requiresCommitBody() { + return false; + } +} diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriter.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriter.java index 7271560e3..2c1d475ae 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriter.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriter.java @@ -107,6 +107,7 @@ import org.eclipse.jgit.lib.ProgressMonitor; import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.lib.ThreadSafeProgressMonitor; import org.eclipse.jgit.revwalk.AsyncRevObjectQueue; +import org.eclipse.jgit.revwalk.BitmapWalker; import org.eclipse.jgit.revwalk.DepthWalk; import org.eclipse.jgit.revwalk.ObjectWalk; import org.eclipse.jgit.revwalk.RevCommit; @@ -1714,7 +1715,7 @@ public class PackWriter implements AutoCloseable { if (!shallowPack && useBitmaps) { BitmapIndex bitmapIndex = reader.getBitmapIndex(); if (bitmapIndex != null) { - PackWriterBitmapWalker bitmapWalker = new PackWriterBitmapWalker( + BitmapWalker bitmapWalker = new BitmapWalker( walker, bitmapIndex, countingMonitor); findObjectsToPackUsingBitmaps(bitmapWalker, want, have); endPhase(countingMonitor); @@ -1917,7 +1918,7 @@ public class PackWriter implements AutoCloseable { } private void findObjectsToPackUsingBitmaps( - PackWriterBitmapWalker bitmapWalker, Set extends ObjectId> want, + BitmapWalker bitmapWalker, Set extends ObjectId> want, Set extends ObjectId> have) throws MissingObjectException, IncorrectObjectTypeException, IOException { @@ -2123,7 +2124,7 @@ public class PackWriter implements AutoCloseable { beginPhase(PackingPhase.BUILDING_BITMAPS, pm, selectedCommits.size()); - PackWriterBitmapWalker walker = bitmapPreparer.newBitmapWalker(); + BitmapWalker walker = bitmapPreparer.newBitmapWalker(); AnyObjectId last = null; for (PackWriterBitmapPreparer.BitmapCommit cmit : selectedCommits) { if (!cmit.isReuseWalker()) { diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriterBitmapPreparer.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriterBitmapPreparer.java index 8bedddb93..38d3458cf 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriterBitmapPreparer.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriterBitmapPreparer.java @@ -59,18 +59,19 @@ import java.util.Set; import org.eclipse.jgit.errors.IncorrectObjectTypeException; import org.eclipse.jgit.errors.MissingObjectException; import org.eclipse.jgit.internal.JGitText; +import org.eclipse.jgit.internal.revwalk.AddUnseenToBitmapFilter; import org.eclipse.jgit.internal.storage.file.BitmapIndexImpl; import org.eclipse.jgit.internal.storage.file.BitmapIndexImpl.CompressedBitmap; import org.eclipse.jgit.internal.storage.file.PackBitmapIndex; import org.eclipse.jgit.internal.storage.file.PackBitmapIndexBuilder; import org.eclipse.jgit.internal.storage.file.PackBitmapIndexRemapper; -import org.eclipse.jgit.internal.storage.pack.PackWriterBitmapWalker.AddUnseenToBitmapFilter; import org.eclipse.jgit.lib.AnyObjectId; import org.eclipse.jgit.lib.BitmapIndex.BitmapBuilder; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectReader; import org.eclipse.jgit.lib.ProgressMonitor; +import org.eclipse.jgit.revwalk.BitmapWalker; import org.eclipse.jgit.revwalk.ObjectWalk; import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.revwalk.RevObject; @@ -508,8 +509,8 @@ class PackWriterBitmapPreparer { return Math.max(next, recentCommitSpan); } - PackWriterBitmapWalker newBitmapWalker() { - return new PackWriterBitmapWalker( + BitmapWalker newBitmapWalker() { + return new BitmapWalker( new ObjectWalk(reader), bitmapIndex, null); } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriterBitmapWalker.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/BitmapWalker.java similarity index 63% rename from org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriterBitmapWalker.java rename to org.eclipse.jgit/src/org/eclipse/jgit/revwalk/BitmapWalker.java index a5c3b71eb..787cf3588 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/pack/PackWriterBitmapWalker.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/BitmapWalker.java @@ -41,29 +41,28 @@ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package org.eclipse.jgit.internal.storage.pack; +package org.eclipse.jgit.revwalk; import java.io.IOException; import java.util.Arrays; import org.eclipse.jgit.errors.IncorrectObjectTypeException; import org.eclipse.jgit.errors.MissingObjectException; -import org.eclipse.jgit.lib.BitmapIndex; +import org.eclipse.jgit.internal.revwalk.AddToBitmapFilter; +import org.eclipse.jgit.internal.revwalk.AddUnseenToBitmapFilter; import org.eclipse.jgit.lib.BitmapIndex.Bitmap; import org.eclipse.jgit.lib.BitmapIndex.BitmapBuilder; -import org.eclipse.jgit.lib.Constants; +import org.eclipse.jgit.lib.BitmapIndex; import org.eclipse.jgit.lib.NullProgressMonitor; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ProgressMonitor; -import org.eclipse.jgit.revwalk.ObjectWalk; -import org.eclipse.jgit.revwalk.RevCommit; -import org.eclipse.jgit.revwalk.RevFlag; -import org.eclipse.jgit.revwalk.RevObject; -import org.eclipse.jgit.revwalk.RevWalk; -import org.eclipse.jgit.revwalk.filter.RevFilter; -/** Helper class for PackWriter to do ObjectWalks with pack index bitmaps. */ -final class PackWriterBitmapWalker { +/** + * Helper class to do ObjectWalks with pack index bitmaps. + * + * @since 4.10 + */ +public final class BitmapWalker { private final ObjectWalk walker; @@ -73,18 +72,52 @@ final class PackWriterBitmapWalker { private long countOfBitmapIndexMisses; - PackWriterBitmapWalker( + /** + * Create a BitmapWalker. + * + * @param walker walker to use when traversing the object graph. + * @param bitmapIndex index to obtain bitmaps from. + * @param pm progress monitor to report progress on. + */ + public BitmapWalker( ObjectWalk walker, BitmapIndex bitmapIndex, ProgressMonitor pm) { this.walker = walker; this.bitmapIndex = bitmapIndex; this.pm = (pm == null) ? NullProgressMonitor.INSTANCE : pm; } - long getCountOfBitmapIndexMisses() { + /** + * Return the number of objects that had to be walked because they were not covered by a + * bitmap. + * + * @return the number of objects that had to be walked because they were not covered by a + * bitmap. + */ + public long getCountOfBitmapIndexMisses() { return countOfBitmapIndexMisses; } - BitmapBuilder findObjects(Iterable extends ObjectId> start, BitmapBuilder seen, + /** + * Return, as a bitmap, the objects reachable from the objects in start. + * + * @param start the objects to start the object traversal from. + * @param seen the objects to skip if encountered during traversal. + * @param ignoreMissing true to ignore missing objects, false otherwise. + * @return as a bitmap, the objects reachable from the objects in start. + * @throws MissingObjectException + * the object supplied is not available from the object + * database. This usually indicates the supplied object is + * invalid, but the reference was constructed during an earlier + * invocation to {@link RevWalk#lookupAny(AnyObjectId, int)}. + * @throws IncorrectObjectTypeException + * the object was not parsed yet and it was discovered during + * parsing that it is not actually the type of the instance + * passed in. This usually indicates the caller used the wrong + * type in a {@link RevWalk#lookupAny(AnyObjectId, int)} call. + * @throws IOException + * a pack file or loose object could not be read. + */ + public BitmapBuilder findObjects(Iterable extends ObjectId> start, BitmapBuilder seen, boolean ignoreMissing) throws MissingObjectException, IncorrectObjectTypeException, IOException { @@ -191,106 +224,4 @@ final class PackWriterBitmapWalker { return bitmapResult; } - - /** - * A RevFilter that adds the visited commits to {@code bitmap} as a side - * effect. - *
- * When the walk hits a commit that is part of {@code bitmap}'s - * BitmapIndex, that entire bitmap is ORed into {@code bitmap} and the - * commit and its parents are marked as SEEN so that the walk does not - * have to visit its ancestors. This ensures the walk is very short if - * there is good bitmap coverage. - */ - static class AddToBitmapFilter extends RevFilter { - private final BitmapBuilder bitmap; - - AddToBitmapFilter(BitmapBuilder bitmap) { - this.bitmap = bitmap; - } - - @Override - public final boolean include(RevWalk walker, RevCommit cmit) { - Bitmap visitedBitmap; - - if (bitmap.contains(cmit)) { - // already included - } else if ((visitedBitmap = bitmap.getBitmapIndex() - .getBitmap(cmit)) != null) { - bitmap.or(visitedBitmap); - } else { - bitmap.addObject(cmit, Constants.OBJ_COMMIT); - return true; - } - - for (RevCommit p : cmit.getParents()) { - p.add(RevFlag.SEEN); - } - return false; - } - - @Override - public final RevFilter clone() { - throw new UnsupportedOperationException(); - } - - @Override - public final boolean requiresCommitBody() { - return false; - } - } - - /** - * A RevFilter that adds the visited commits to {@code bitmap} as a side - * effect. - *
- * When the walk hits a commit that is part of {@code bitmap}'s - * BitmapIndex, that entire bitmap is ORed into {@code bitmap} and the - * commit and its parents are marked as SEEN so that the walk does not - * have to visit its ancestors. This ensures the walk is very short if - * there is good bitmap coverage. - *
- * Commits named in {@code seen} are considered already seen. If one is - * encountered, that commit and its parents will be marked with the SEEN - * flag to prevent the walk from visiting its ancestors. - */ - static class AddUnseenToBitmapFilter extends RevFilter { - private final BitmapBuilder seen; - private final BitmapBuilder bitmap; - - AddUnseenToBitmapFilter(BitmapBuilder seen, BitmapBuilder bitmapResult) { - this.seen = seen; - this.bitmap = bitmapResult; - } - - @Override - public final boolean include(RevWalk walker, RevCommit cmit) { - Bitmap visitedBitmap; - - if (seen.contains(cmit) || bitmap.contains(cmit)) { - // already seen or included - } else if ((visitedBitmap = bitmap.getBitmapIndex() - .getBitmap(cmit)) != null) { - bitmap.or(visitedBitmap); - } else { - bitmap.addObject(cmit, Constants.OBJ_COMMIT); - return true; - } - - for (RevCommit p : cmit.getParents()) { - p.add(RevFlag.SEEN); - } - return false; - } - - @Override - public final RevFilter clone() { - throw new UnsupportedOperationException(); - } - - @Override - public final boolean requiresCommitBody() { - return false; - } - } }