diff options
Diffstat (limited to 'org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectReader.java')
-rw-r--r-- | org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectReader.java | 405 |
1 files changed, 329 insertions, 76 deletions
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectReader.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectReader.java index 4c9af85fa8..b916d1e8e9 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectReader.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectReader.java @@ -1,70 +1,58 @@ /* - * Copyright (C) 2010, Google Inc. - * and other copyright owners as documented in the project's IP log. + * Copyright (C) 2010, Google Inc. and others * - * 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 + * This program and the accompanying materials are made available under the + * terms of the Eclipse Distribution License v. 1.0 which is available at + * https://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. + * SPDX-License-Identifier: BSD-3-Clause */ package org.eclipse.jgit.lib; +import static org.eclipse.jgit.lib.Constants.OBJECT_ID_ABBREV_STRING_LENGTH; + import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; +import java.util.Optional; import java.util.Set; +import org.eclipse.jgit.annotations.NonNull; +import org.eclipse.jgit.annotations.Nullable; import org.eclipse.jgit.errors.IncorrectObjectTypeException; import org.eclipse.jgit.errors.MissingObjectException; -import org.eclipse.jgit.internal.storage.pack.ObjectReuseAsIs; +import org.eclipse.jgit.internal.revwalk.BitmappedObjectReachabilityChecker; +import org.eclipse.jgit.internal.revwalk.BitmappedReachabilityChecker; +import org.eclipse.jgit.internal.revwalk.PedestrianObjectReachabilityChecker; +import org.eclipse.jgit.internal.revwalk.PedestrianReachabilityChecker; +import org.eclipse.jgit.internal.storage.commitgraph.CommitGraph; +import org.eclipse.jgit.revwalk.ObjectReachabilityChecker; +import org.eclipse.jgit.revwalk.ObjectWalk; +import org.eclipse.jgit.revwalk.ReachabilityChecker; +import org.eclipse.jgit.revwalk.RevWalk; /** - * Reads an {@link ObjectDatabase} for a single thread. + * Reads an {@link org.eclipse.jgit.lib.ObjectDatabase} for a single thread. * <p> * Readers that can support efficient reuse of pack encoded objects should also - * implement the companion interface {@link ObjectReuseAsIs}. + * implement the companion interface + * {@link org.eclipse.jgit.internal.storage.pack.ObjectReuseAsIs}. */ public abstract class ObjectReader implements AutoCloseable { /** Type hint indicating the caller doesn't know the type. */ public static final int OBJ_ANY = -1; /** + * The threshold at which a file will be streamed rather than loaded + * entirely into memory. + * @since 4.6 + */ + protected int streamFileThreshold; + + /** * Construct a new reader from the same data. * <p> * Applications can use this method to build a new reader from the same data @@ -87,12 +75,12 @@ public abstract class ObjectReader implements AutoCloseable { * @param objectId * object identity that needs to be abbreviated. * @return SHA-1 abbreviation. - * @throws IOException + * @throws java.io.IOException * the object store cannot be read. */ public AbbreviatedObjectId abbreviate(AnyObjectId objectId) throws IOException { - return abbreviate(objectId, 7); + return abbreviate(objectId, OBJECT_ID_ABBREV_STRING_LENGTH); } /** @@ -114,7 +102,7 @@ public abstract class ObjectReader implements AutoCloseable { * [2, {@value Constants#OBJECT_ID_STRING_LENGTH}]. * @return SHA-1 abbreviation. If no matching objects exist in the * repository, the abbreviation will match the minimum length. - * @throws IOException + * @throws java.io.IOException * the object store cannot be read. */ public AbbreviatedObjectId abbreviate(AnyObjectId objectId, int len) @@ -126,7 +114,7 @@ public abstract class ObjectReader implements AutoCloseable { Collection<ObjectId> matches = resolve(abbrev); while (1 < matches.size() && len < Constants.OBJECT_ID_STRING_LENGTH) { abbrev = objectId.abbreviate(++len); - List<ObjectId> n = new ArrayList<ObjectId>(8); + List<ObjectId> n = new ArrayList<>(8); for (ObjectId candidate : matches) { if (abbrev.prefixCompare(candidate) == 0) n.add(candidate); @@ -166,7 +154,7 @@ public abstract class ObjectReader implements AutoCloseable { * abbreviated id to resolve to a complete identity. The * abbreviation must have a length of at least 2. * @return candidates that begin with the abbreviated identity. - * @throws IOException + * @throws java.io.IOException * the object store cannot be read. */ public abstract Collection<ObjectId> resolve(AbbreviatedObjectId id) @@ -178,7 +166,7 @@ public abstract class ObjectReader implements AutoCloseable { * @param objectId * identity of the object to test for existence of. * @return true if the specified object is stored in this database. - * @throws IOException + * @throws java.io.IOException * the object store cannot be accessed. */ public boolean has(AnyObjectId objectId) throws IOException { @@ -192,13 +180,14 @@ public abstract class ObjectReader implements AutoCloseable { * identity of the object to test for existence of. * @param typeHint * hint about the type of object being requested, e.g. - * {@link Constants#OBJ_BLOB}; {@link #OBJ_ANY} if the object - * type is not known, or does not matter to the caller. + * {@link org.eclipse.jgit.lib.Constants#OBJ_BLOB}; + * {@link #OBJ_ANY} if the object type is not known, or does not + * matter to the caller. * @return true if the specified object is stored in this database. * @throws IncorrectObjectTypeException * typeHint was not OBJ_ANY, and the object's actual type does * not match typeHint. - * @throws IOException + * @throws java.io.IOException * the object store cannot be accessed. */ public boolean has(AnyObjectId objectId, int typeHint) throws IOException { @@ -215,10 +204,11 @@ public abstract class ObjectReader implements AutoCloseable { * * @param objectId * identity of the object to open. - * @return a {@link ObjectLoader} for accessing the object. - * @throws MissingObjectException + * @return a {@link org.eclipse.jgit.lib.ObjectLoader} for accessing the + * object. + * @throws org.eclipse.jgit.errors.MissingObjectException * the object does not exist. - * @throws IOException + * @throws java.io.IOException * the object store cannot be accessed. */ public ObjectLoader open(AnyObjectId objectId) @@ -233,15 +223,17 @@ public abstract class ObjectReader implements AutoCloseable { * identity of the object to open. * @param typeHint * hint about the type of object being requested, e.g. - * {@link Constants#OBJ_BLOB}; {@link #OBJ_ANY} if the object - * type is not known, or does not matter to the caller. - * @return a {@link ObjectLoader} for accessing the object. - * @throws MissingObjectException + * {@link org.eclipse.jgit.lib.Constants#OBJ_BLOB}; + * {@link #OBJ_ANY} if the object type is not known, or does not + * matter to the caller. + * @return a {@link org.eclipse.jgit.lib.ObjectLoader} for accessing the + * object. + * @throws org.eclipse.jgit.errors.MissingObjectException * the object does not exist. - * @throws IncorrectObjectTypeException + * @throws org.eclipse.jgit.errors.IncorrectObjectTypeException * typeHint was not OBJ_ANY, and the object's actual type does * not match typeHint. - * @throws IOException + * @throws java.io.IOException * the object store cannot be accessed. */ public abstract ObjectLoader open(AnyObjectId objectId, int typeHint) @@ -252,7 +244,8 @@ public abstract class ObjectReader implements AutoCloseable { * Returns IDs for those commits which should be considered as shallow. * * @return IDs of shallow commits - * @throws IOException + * @throws java.io.IOException + * if an error occurred */ public abstract Set<ObjectId> getShallowCommits() throws IOException; @@ -260,7 +253,7 @@ public abstract class ObjectReader implements AutoCloseable { * Asynchronous object opening. * * @param <T> - * type of identifier being supplied. + * type of {@code ObjectId} * @param objectIds * objects to open from the object store. The supplied collection * must not be modified until the queue has finished. @@ -275,34 +268,39 @@ public abstract class ObjectReader implements AutoCloseable { public <T extends ObjectId> AsyncObjectLoaderQueue<T> open( Iterable<T> objectIds, final boolean reportMissing) { final Iterator<T> idItr = objectIds.iterator(); - return new AsyncObjectLoaderQueue<T>() { + return new AsyncObjectLoaderQueue<>() { private T cur; + @Override public boolean next() throws MissingObjectException, IOException { if (idItr.hasNext()) { cur = idItr.next(); return true; - } else { - return false; } + return false; } + @Override public T getCurrent() { return cur; } + @Override public ObjectId getObjectId() { return cur; } + @Override public ObjectLoader open() throws IOException { return ObjectReader.this.open(cur, OBJ_ANY); } + @Override public boolean cancel(boolean mayInterruptIfRunning) { return true; } + @Override public void release() { // Since we are sequential by default, we don't // have any state to clean up if we terminate early. @@ -321,15 +319,16 @@ public abstract class ObjectReader implements AutoCloseable { * identity of the object to open. * @param typeHint * hint about the type of object being requested, e.g. - * {@link Constants#OBJ_BLOB}; {@link #OBJ_ANY} if the object - * type is not known, or does not matter to the caller. + * {@link org.eclipse.jgit.lib.Constants#OBJ_BLOB}; + * {@link #OBJ_ANY} if the object type is not known, or does not + * matter to the caller. * @return size of object in bytes. - * @throws MissingObjectException + * @throws org.eclipse.jgit.errors.MissingObjectException * the object does not exist. - * @throws IncorrectObjectTypeException + * @throws org.eclipse.jgit.errors.IncorrectObjectTypeException * typeHint was not OBJ_ANY, and the object's actual type does * not match typeHint. - * @throws IOException + * @throws java.io.IOException * the object store cannot be accessed. */ public long getObjectSize(AnyObjectId objectId, int typeHint) @@ -339,10 +338,43 @@ public abstract class ObjectReader implements AutoCloseable { } /** + * Check if the object size is less or equal than certain value + * + * By default, it reads the object from storage to get the size. Subclasses + * can implement more efficient lookups. + * + * @param objectId + * identity of the object to open. + * @param typeHint + * hint about the type of object being requested, e.g. + * {@link org.eclipse.jgit.lib.Constants#OBJ_BLOB}; + * {@link #OBJ_ANY} if the object type is not known, or does not + * matter to the caller. + * @param size + * threshold value for the size of the object in bytes. + * @return true if the object size is equal or smaller than the threshold + * value + * @throws org.eclipse.jgit.errors.MissingObjectException + * the object does not exist. + * @throws org.eclipse.jgit.errors.IncorrectObjectTypeException + * typeHint was not OBJ_ANY, and the object's actual type does + * not match typeHint. + * @throws java.io.IOException + * the object store cannot be accessed. + * + * @since 6.4 + */ + public boolean isNotLargerThan(AnyObjectId objectId, int typeHint, long size) + throws MissingObjectException, IncorrectObjectTypeException, + IOException { + return open(objectId, typeHint).getSize() <= size; + } + + /** * Asynchronous object size lookup. * * @param <T> - * type of identifier being supplied. + * type of {@code ObjectId} * @param objectIds * objects to get the size of from the object store. The supplied * collection must not be modified until the queue has finished. @@ -357,37 +389,42 @@ public abstract class ObjectReader implements AutoCloseable { public <T extends ObjectId> AsyncObjectSizeQueue<T> getObjectSize( Iterable<T> objectIds, final boolean reportMissing) { final Iterator<T> idItr = objectIds.iterator(); - return new AsyncObjectSizeQueue<T>() { + return new AsyncObjectSizeQueue<>() { private T cur; private long sz; + @Override public boolean next() throws MissingObjectException, IOException { if (idItr.hasNext()) { cur = idItr.next(); sz = getObjectSize(cur, OBJ_ANY); return true; - } else { - return false; } + return false; } + @Override public T getCurrent() { return cur; } + @Override public ObjectId getObjectId() { return cur; } + @Override public long getSize() { return sz; } + @Override public boolean cancel(boolean mayInterruptIfRunning) { return true; } + @Override public void release() { // Since we are sequential by default, we don't // have any state to clean up if we terminate early. @@ -413,7 +450,7 @@ public abstract class ObjectReader implements AutoCloseable { * An index that can be used to speed up ObjectWalks. * * @return the index or null if one does not exist. - * @throws IOException + * @throws java.io.IOException * when the index fails to load * @since 3.0 */ @@ -422,6 +459,90 @@ public abstract class ObjectReader implements AutoCloseable { } /** + * Create a reachability checker that will use bitmaps if possible. + * + * @param rw + * revwalk for use by the reachability checker + * @return the most efficient reachability checker for this repository. + * @throws IOException + * if it cannot open any of the underlying indices. + * + * @since 5.11 + */ + @NonNull + public ReachabilityChecker createReachabilityChecker(RevWalk rw) + throws IOException { + if (getBitmapIndex() != null) { + return new BitmappedReachabilityChecker(rw); + } + + return new PedestrianReachabilityChecker(true, rw); + } + + /** + * Create an object reachability checker that will use bitmaps if possible. + * + * This reachability checker accepts any object as target. For checks + * exclusively between commits, use + * {@link #createReachabilityChecker(RevWalk)}. + * + * @param ow + * objectwalk for use by the reachability checker + * @return the most efficient object reachability checker for this + * repository. + * + * @throws IOException + * if it cannot open any of the underlying indices. + * + * @since 5.11 + */ + @NonNull + public ObjectReachabilityChecker createObjectReachabilityChecker( + ObjectWalk ow) throws IOException { + if (getBitmapIndex() != null) { + return new BitmappedObjectReachabilityChecker(ow); + } + + return new PedestrianObjectReachabilityChecker(ow); + } + + /** + * Get the commit-graph for this repository if available. + * <p> + * The commit graph can be created/modified/deleted while the repository is + * open and specific implementations decide when to refresh it. + * + * @return the commit-graph or empty if the commit-graph does not exist or + * is invalid; always returns empty when core.commitGraph is false + * (default is + * {@value org.eclipse.jgit.lib.CoreConfig#DEFAULT_COMMIT_GRAPH_ENABLE}). + * + * @throws IOException + * if it cannot open any of the underlying commit graph. + * + * @since 6.5 + */ + public Optional<CommitGraph> getCommitGraph() throws IOException { + return Optional.empty(); + } + + /** + * Get the {@link org.eclipse.jgit.lib.ObjectInserter} from which this + * reader was created using {@code inserter.newReader()} + * + * @return the {@link org.eclipse.jgit.lib.ObjectInserter} from which this + * reader was created using {@code inserter.newReader()}, or null if + * this reader was not created from an inserter. + * @since 4.4 + */ + @Nullable + public ObjectInserter getCreatedFromInserter() { + return null; + } + + /** + * {@inheritDoc} + * <p> * Release any resources used by this reader. * <p> * A reader that has been released can be used again, but may need to be @@ -430,7 +551,139 @@ public abstract class ObjectReader implements AutoCloseable { * @since 4.0 */ @Override - public void close() { - // Do nothing. + public abstract void close(); + + /** + * Sets the threshold at which a file will be streamed rather than loaded + * entirely into memory + * + * @param threshold + * the new threshold + * @since 4.6 + */ + public void setStreamFileThreshold(int threshold) { + streamFileThreshold = threshold; + } + + /** + * Returns the threshold at which a file will be streamed rather than loaded + * entirely into memory + * + * @return the threshold in bytes + * @since 4.6 + */ + public int getStreamFileThreshold() { + return streamFileThreshold; + } + + /** + * Wraps a delegate ObjectReader. + * + * @since 4.4 + */ + public abstract static class Filter extends ObjectReader { + /** + * Get delegate ObjectReader to handle all processing + * + * @return delegate ObjectReader to handle all processing. + * @since 4.4 + */ + protected abstract ObjectReader delegate(); + + @Override + public ObjectReader newReader() { + return delegate().newReader(); + } + + @Override + public AbbreviatedObjectId abbreviate(AnyObjectId objectId) + throws IOException { + return delegate().abbreviate(objectId); + } + + @Override + public AbbreviatedObjectId abbreviate(AnyObjectId objectId, int len) + throws IOException { + return delegate().abbreviate(objectId, len); + } + + @Override + public Collection<ObjectId> resolve(AbbreviatedObjectId id) + throws IOException { + return delegate().resolve(id); + } + + @Override + public boolean has(AnyObjectId objectId) throws IOException { + return delegate().has(objectId); + } + + @Override + public boolean has(AnyObjectId objectId, int typeHint) throws IOException { + return delegate().has(objectId, typeHint); + } + + @Override + public ObjectLoader open(AnyObjectId objectId) + throws MissingObjectException, IOException { + return delegate().open(objectId); + } + + @Override + public ObjectLoader open(AnyObjectId objectId, int typeHint) + throws MissingObjectException, IncorrectObjectTypeException, + IOException { + return delegate().open(objectId, typeHint); + } + + @Override + public Set<ObjectId> getShallowCommits() throws IOException { + return delegate().getShallowCommits(); + } + + @Override + public <T extends ObjectId> AsyncObjectLoaderQueue<T> open( + Iterable<T> objectIds, boolean reportMissing) { + return delegate().open(objectIds, reportMissing); + } + + @Override + public long getObjectSize(AnyObjectId objectId, int typeHint) + throws MissingObjectException, IncorrectObjectTypeException, + IOException { + return delegate().getObjectSize(objectId, typeHint); + } + + @Override + public <T extends ObjectId> AsyncObjectSizeQueue<T> getObjectSize( + Iterable<T> objectIds, boolean reportMissing) { + return delegate().getObjectSize(objectIds, reportMissing); + } + + @Override + public void setAvoidUnreachableObjects(boolean avoid) { + delegate().setAvoidUnreachableObjects(avoid); + } + + @Override + public BitmapIndex getBitmapIndex() throws IOException { + return delegate().getBitmapIndex(); + } + + @Override + public Optional<CommitGraph> getCommitGraph() throws IOException{ + return delegate().getCommitGraph(); + } + + @Override + @Nullable + public ObjectInserter getCreatedFromInserter() { + return delegate().getCreatedFromInserter(); + } + + @Override + public void close() { + delegate().close(); + } } } |