diff options
author | Shawn O. Pearce <spearce@spearce.org> | 2010-06-18 23:02:57 -0700 |
---|---|---|
committer | Shawn O. Pearce <spearce@spearce.org> | 2010-06-25 17:58:01 -0700 |
commit | 5cfc29b491eece0ceb71e653763b6cc771e7bdfe (patch) | |
tree | 196b31592fbc21f5f677a4d0e34abd03ecdca831 | |
parent | 133c987f4db0788043b79e33582d0c0d4d6ce09a (diff) | |
download | jgit-5cfc29b491eece0ceb71e653763b6cc771e7bdfe.tar.gz jgit-5cfc29b491eece0ceb71e653763b6cc771e7bdfe.zip |
Replace WindowCache with ObjectReader
The WindowCache is an implementation detail of PackFile and how its
used by ObjectDirectory. Lets start to hide it and replace the public
API with a more generic concept, ObjectReader.
Because PackedObjectLoader is also considered a private detail of
PackFile, we have to make PackWriter temporarily dependent upon the
WindowCursor and thus FileRepository and ObjectDirectory in order to
just start the refactoring. In later changes we will clean up the
APIs more, exposing sufficient support to PackWriter without needing
the file specific implementation details.
Change-Id: I676be12b57f3534f1285854ee5de1aa483895398
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
20 files changed, 274 insertions, 157 deletions
diff --git a/org.eclipse.jgit.iplog/src/org/eclipse/jgit/iplog/IpLogGenerator.java b/org.eclipse.jgit.iplog/src/org/eclipse/jgit/iplog/IpLogGenerator.java index f64c329847..f40c3896a0 100644 --- a/org.eclipse.jgit.iplog/src/org/eclipse/jgit/iplog/IpLogGenerator.java +++ b/org.eclipse.jgit.iplog/src/org/eclipse/jgit/iplog/IpLogGenerator.java @@ -86,7 +86,7 @@ import org.eclipse.jgit.lib.MutableObjectId; import org.eclipse.jgit.lib.ObjectLoader; import org.eclipse.jgit.lib.PersonIdent; import org.eclipse.jgit.lib.Repository; -import org.eclipse.jgit.lib.WindowCursor; +import org.eclipse.jgit.lib.ObjectReader; import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.revwalk.RevTree; import org.eclipse.jgit.revwalk.RevWalk; @@ -144,7 +144,7 @@ public class IpLogGenerator { private NameConflictTreeWalk tw; - private final WindowCursor curs = new WindowCursor(); + private ObjectReader curs; private final MutableObjectId idbuf = new MutableObjectId(); @@ -184,6 +184,7 @@ public class IpLogGenerator { throws IOException, ConfigInvalidException { try { db = repo; + curs = db.newObjectReader(); rw = new RevWalk(db); tw = new NameConflictTreeWalk(db); @@ -194,7 +195,7 @@ public class IpLogGenerator { scanProjectCommits(meta.getProjects().get(0), c); commits.add(c); } finally { - WindowCursor.release(curs); + curs.release(); db = null; rw = null; tw = null; diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/AbstractTreeIteratorHandler.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/AbstractTreeIteratorHandler.java index 2043ac2090..d7b98c5098 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/AbstractTreeIteratorHandler.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/AbstractTreeIteratorHandler.java @@ -59,7 +59,7 @@ import org.eclipse.jgit.dircache.DirCacheIterator; import org.eclipse.jgit.errors.IncorrectObjectTypeException; import org.eclipse.jgit.errors.MissingObjectException; import org.eclipse.jgit.lib.ObjectId; -import org.eclipse.jgit.lib.WindowCursor; +import org.eclipse.jgit.lib.ObjectReader; import org.eclipse.jgit.pgm.CLIText; import org.eclipse.jgit.treewalk.AbstractTreeIterator; import org.eclipse.jgit.treewalk.CanonicalTreeParser; @@ -121,7 +121,7 @@ public class AbstractTreeIteratorHandler extends throw new CmdLineException(MessageFormat.format(CLIText.get().notATree, name)); final CanonicalTreeParser p = new CanonicalTreeParser(); - final WindowCursor curs = new WindowCursor(); + final ObjectReader curs = clp.getRepository().newObjectReader(); try { p.reset(clp.getRepository(), clp.getRevWalk().parseTree(id), curs); } catch (MissingObjectException e) { diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/T0004_PackReader.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/T0004_PackReader.java index 336bba22ce..54816f6f5e 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/T0004_PackReader.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/T0004_PackReader.java @@ -63,7 +63,7 @@ public class T0004_PackReader extends SampleDataRepositoryTestCase { id = ObjectId.fromString("902d5476fa249b7abc9d84c611577a81381f0327"); pr = new PackFile(TEST_IDX, TEST_PACK); - or = pr.get(new WindowCursor(), id); + or = pr.get(new WindowCursor(null), id); assertNotNull(or); assertEquals(Constants.OBJ_TREE, or.getType()); assertEquals(35, or.getSize()); diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ReceivePackRefFilterTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ReceivePackRefFilterTest.java index b87cc7a99c..03726cba09 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ReceivePackRefFilterTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/ReceivePackRefFilterTest.java @@ -176,7 +176,7 @@ public class ReceivePackRefFilterTest extends LocalDiskRepositoryTestCase { // Verify the only storage of b is our packed delta above. // ObjectDirectory od = (ObjectDirectory) src.getObjectDatabase(); - assertTrue("has b", od.hasObject(b)); + assertTrue("has b", src.hasObject(b)); assertFalse("b not loose", od.fileFor(b).exists()); // Now use b but in a different commit than what is hidden. diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheBuilder.java b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheBuilder.java index e6b6197819..adb8a8d77f 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheBuilder.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheBuilder.java @@ -51,7 +51,7 @@ import java.util.Arrays; import org.eclipse.jgit.JGitText; import org.eclipse.jgit.lib.AnyObjectId; import org.eclipse.jgit.lib.Repository; -import org.eclipse.jgit.lib.WindowCursor; +import org.eclipse.jgit.lib.ObjectReader; import org.eclipse.jgit.treewalk.AbstractTreeIterator; import org.eclipse.jgit.treewalk.CanonicalTreeParser; import org.eclipse.jgit.treewalk.TreeWalk; @@ -166,7 +166,7 @@ public class DirCacheBuilder extends BaseDirCacheEditor { final Repository db, final AnyObjectId tree) throws IOException { final TreeWalk tw = new TreeWalk(db); tw.reset(); - final WindowCursor curs = new WindowCursor(); + final ObjectReader curs = db.newObjectReader(); try { tw.addTree(new CanonicalTreeParser(pathPrefix, db, tree .toObjectId(), curs)); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/CachedObjectDirectory.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/CachedObjectDirectory.java index 37a96d74f2..351d6817fc 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/CachedObjectDirectory.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/CachedObjectDirectory.java @@ -46,7 +46,6 @@ package org.eclipse.jgit.lib; import java.io.File; import java.io.IOException; -import java.util.Collection; /** * The cached instance of an {@link ObjectDirectory}. @@ -117,12 +116,6 @@ class CachedObjectDirectory extends FileObjectDatabase { } @Override - void openObjectInAllPacks(Collection<PackedObjectLoader> out, - WindowCursor curs, AnyObjectId objectId) throws IOException { - wrapped.openObjectInAllPacks(out, curs, objectId); - } - - @Override File getDirectory() { return wrapped.getDirectory(); } @@ -157,7 +150,7 @@ class CachedObjectDirectory extends FileObjectDatabase { } @Override - public ObjectLoader openObject(final WindowCursor curs, + ObjectLoader openObject(final WindowCursor curs, final AnyObjectId objectId) throws IOException { return openObjectImpl1(curs, objectId); } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/FileObjectDatabase.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/FileObjectDatabase.java index a7bf60370c..36e808c23b 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/FileObjectDatabase.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/FileObjectDatabase.java @@ -45,8 +45,14 @@ package org.eclipse.jgit.lib; import java.io.File; import java.io.IOException; +import java.util.Collection; abstract class FileObjectDatabase extends ObjectDatabase { + @Override + public ObjectReader newReader() { + return new WindowCursor(this); + } + /** * Does the requested object exist in this database? * <p> @@ -98,8 +104,8 @@ abstract class FileObjectDatabase extends ObjectDatabase { * object, or null if the object does not exist. * @throws IOException */ - public ObjectLoader openObject(final WindowCursor curs, - final AnyObjectId objectId) throws IOException { + ObjectLoader openObject(final WindowCursor curs, final AnyObjectId objectId) + throws IOException { ObjectLoader ldr; ldr = openObjectImpl1(curs, objectId); @@ -154,6 +160,10 @@ abstract class FileObjectDatabase extends ObjectDatabase { return null; } + void openObjectInAllPacks(Collection<PackedObjectLoader> reuseLoaders, + WindowCursor windowCursor, AnyObjectId otp) throws IOException { + } + abstract File getDirectory(); abstract AlternateHandle[] myAlternates(); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/FileRepository.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/FileRepository.java index 12248fb425..32f516f7d9 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/FileRepository.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/FileRepository.java @@ -49,9 +49,7 @@ package org.eclipse.jgit.lib; import java.io.File; import java.io.IOException; import java.text.MessageFormat; -import java.util.Collection; import java.util.HashSet; -import java.util.LinkedList; import java.util.Set; import org.eclipse.jgit.JGitText; @@ -397,43 +395,6 @@ public class FileRepository extends Repository { } /** - * Open object in all packs containing specified object. - * - * @param objectId - * id of object to search for - * @param curs - * temporary working space associated with the calling thread. - * @return collection of loaders for this object, from all packs containing - * this object - * @throws IOException - */ - public Collection<PackedObjectLoader> openObjectInAllPacks( - final AnyObjectId objectId, final WindowCursor curs) - throws IOException { - Collection<PackedObjectLoader> result = new LinkedList<PackedObjectLoader>(); - openObjectInAllPacks(objectId, result, curs); - return result; - } - - /** - * Open object in all packs containing specified object. - * - * @param objectId - * id of object to search for - * @param resultLoaders - * result collection of loaders for this object, filled with - * loaders from all packs containing specified object - * @param curs - * temporary working space associated with the calling thread. - * @throws IOException - */ - void openObjectInAllPacks(final AnyObjectId objectId, - final Collection<PackedObjectLoader> resultLoaders, - final WindowCursor curs) throws IOException { - objectDatabase.openObjectInAllPacks(resultLoaders, curs, objectId); - } - - /** * Objects known to exist but not expressed by {@link #getAllRefs()}. * <p> * When a repository borrows objects from another repository, it can diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectDatabase.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectDatabase.java index c44a7ac6f2..c2d2beda9a 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectDatabase.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectDatabase.java @@ -44,7 +44,8 @@ package org.eclipse.jgit.lib; import java.io.IOException; -import java.util.Collection; + +import org.eclipse.jgit.errors.MissingObjectException; /** * Abstraction of arbitrary object storage. @@ -90,48 +91,65 @@ public abstract class ObjectDatabase { public abstract ObjectInserter newInserter(); /** + * Create a new {@code ObjectReader} to read existing objects. + * <p> + * The returned reader is not itself thread-safe, but multiple concurrent + * reader instances created from the same {@code ObjectDatabase} must be + * thread-safe. + * + * @return reader the caller can use to load objects from this database. + */ + public abstract ObjectReader newReader(); + + /** * Close any resources held by this database. */ public abstract void close(); /** * Does the requested object exist in this database? + * <p> + * This is a one-shot call interface which may be faster than allocating a + * {@link #newReader()} to perform the lookup. * * @param objectId * identity of the object to test for existence of. * @return true if the specified object is stored in this database. + * @throws IOException + * the object store cannot be accessed. */ - public abstract boolean hasObject(AnyObjectId objectId); + public boolean hasObject(final AnyObjectId objectId) throws IOException { + final ObjectReader or = newReader(); + try { + return or.hasObject(objectId); + } finally { + or.release(); + } + } /** * Open an object from this database. + * <p> + * This is a one-shot call interface which may be faster than allocating a + * {@link #newReader()} to perform the lookup. * - * @param curs - * temporary working space associated with the calling thread. * @param objectId * identity of the object to open. - * @return a {@link ObjectLoader} for accessing the data of the named - * object, or null if the object does not exist. + * @return a {@link ObjectLoader} for accessing the object. + * @throws MissingObjectException + * the object does not exist. * @throws IOException + * the object store cannot be accessed. */ - public abstract ObjectLoader openObject(WindowCursor curs, - AnyObjectId objectId) throws IOException; - - /** - * Open the object from all packs containing it. - * - * @param out - * result collection of loaders for this object, filled with - * loaders from all packs containing specified object - * @param curs - * temporary working space associated with the calling thread. - * @param objectId - * id of object to search for - * @throws IOException - */ - abstract void openObjectInAllPacks(final Collection<PackedObjectLoader> out, - final WindowCursor curs, final AnyObjectId objectId) - throws IOException; + public ObjectLoader openObject(final AnyObjectId objectId) + throws IOException { + final ObjectReader or = newReader(); + try { + return or.openObject(objectId); + } finally { + or.release(); + } + } /** * Create a new cached database instance over this database. This instance might diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectDirectory.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectDirectory.java index c605df9b8a..810e48890a 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectDirectory.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectDirectory.java @@ -283,7 +283,6 @@ public class ObjectDirectory extends FileObjectDatabase { } } - @Override void openObjectInAllPacks(final Collection<PackedObjectLoader> out, final WindowCursor curs, final AnyObjectId objectId) throws IOException { @@ -308,6 +307,9 @@ public class ObjectDirectory extends FileObjectDatabase { } break SEARCH; } + + for (AlternateHandle h : myAlternates()) + h.db.openObjectInAllPacks(out, curs, objectId); } boolean hasObject2(final String objectName) { diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectReader.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectReader.java new file mode 100644 index 0000000000..c95130ce29 --- /dev/null +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectReader.java @@ -0,0 +1,114 @@ +/* + * 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.lib; + +import java.io.IOException; + +import org.eclipse.jgit.errors.MissingObjectException; + +/** Reads an {@link ObjectDatabase} for a single thread. */ +public abstract class ObjectReader { + /** Type hint indicating the caller doesn't know the type. */ + protected static final int OBJ_ANY = -1; + + /** + * Does the requested object exist in this database? + * + * @param objectId + * identity of the object to test for existence of. + * @return true if the specified object is stored in this database. + * @throws IOException + * the object store cannot be accessed. + */ + public boolean hasObject(AnyObjectId objectId) throws IOException { + try { + openObject(objectId); + return true; + } catch (MissingObjectException notFound) { + return false; + } + } + + /** + * Open an object from this database. + * + * @param objectId + * identity of the object to open. + * @return a {@link ObjectLoader} for accessing the object. + * @throws MissingObjectException + * the object does not exist. + * @throws IOException + */ + public ObjectLoader openObject(AnyObjectId objectId) + throws MissingObjectException, IOException { + return openObject(objectId, OBJ_ANY); + } + + /** + * Open an object from this database. + * + * @param objectId + * identity of the object to open. + *@param typeHint + * hint about the type of object being requested; + * {@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 + * the object does not exist. + * @throws IOException + */ + public abstract ObjectLoader openObject(AnyObjectId objectId, int typeHint) + throws MissingObjectException, IOException; + + /** + * Release any resources used by this reader. + * <p> + * A reader that has been released can be used again, but may need to be + * released after the subsequent usage. + */ + public void release() { + // Do nothing. + } +} diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/PackWriter.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/PackWriter.java index e8e5fc21e6..15ac17425e 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/PackWriter.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/PackWriter.java @@ -179,7 +179,7 @@ public class PackWriter { private final byte[] buf = new byte[16384]; // 16 KB - private final WindowCursor windowCursor = new WindowCursor(); + private final WindowCursor windowCursor; private List<ObjectToPack> sortedByName; @@ -236,6 +236,9 @@ public class PackWriter { public PackWriter(final Repository repo, final ProgressMonitor imonitor, final ProgressMonitor wmonitor) { this.db = repo; + windowCursor = new WindowCursor((ObjectDirectory) repo + .getObjectDatabase()); + initMonitor = imonitor == null ? NullProgressMonitor.INSTANCE : imonitor; writeMonitor = wmonitor == null ? NullProgressMonitor.INSTANCE : wmonitor; @@ -621,7 +624,7 @@ public class PackWriter { private void searchForReuse( final Collection<PackedObjectLoader> reuseLoaders, final ObjectToPack otp) throws IOException { - db.openObjectInAllPacks(otp, reuseLoaders, windowCursor); + windowCursor.openObjectInAllPacks(otp, reuseLoaders); if (reuseDeltas) { selectDeltaReuseForObject(otp, reuseLoaders); } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java index 334581415a..400cae43d4 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Repository.java @@ -50,7 +50,6 @@ import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.util.ArrayList; -import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; @@ -64,6 +63,7 @@ import java.util.concurrent.atomic.AtomicInteger; import org.eclipse.jgit.JGitText; import org.eclipse.jgit.dircache.DirCache; import org.eclipse.jgit.errors.IncorrectObjectTypeException; +import org.eclipse.jgit.errors.MissingObjectException; import org.eclipse.jgit.errors.RevisionSyntaxException; import org.eclipse.jgit.revwalk.RevBlob; import org.eclipse.jgit.revwalk.RevCommit; @@ -153,6 +153,11 @@ public abstract class Repository { return getObjectDatabase().newInserter(); } + /** @return a new inserter to create objects in {@link #getObjectDatabase()} */ + public ObjectReader newObjectReader() { + return getObjectDatabase().newReader(); + } + /** @return the reference database which stores the reference namespace. */ public abstract RefDatabase getRefDatabase(); @@ -186,7 +191,12 @@ public abstract class Repository { * known shared repositories. */ public boolean hasObject(AnyObjectId objectId) { - return getObjectDatabase().hasObject(objectId); + try { + return getObjectDatabase().hasObject(objectId); + } catch (IOException e) { + // Legacy API, assume error means "no" + return false; + } } /** @@ -199,11 +209,11 @@ public abstract class Repository { */ public ObjectLoader openObject(final AnyObjectId id) throws IOException { - final WindowCursor wc = new WindowCursor(); try { - return openObject(wc, id); - } finally { - wc.release(); + return getObjectDatabase().openObject(id); + } catch (MissingObjectException notFound) { + // Legacy API, return null + return null; } } @@ -216,44 +226,19 @@ public abstract class Repository { * @return a {@link ObjectLoader} for accessing the data of the named * object, or null if the object does not exist. * @throws IOException + * @deprecated Use {code newObjectReader().open(id)}. */ - public ObjectLoader openObject(WindowCursor curs, AnyObjectId id) + @Deprecated + public ObjectLoader openObject(ObjectReader curs, AnyObjectId id) throws IOException { - return getObjectDatabase().openObject(curs, id); + try { + return curs.openObject(id); + } catch (MissingObjectException notFound) { + return null; + } } /** - * Open object in all packs containing specified object. - * - * @param objectId - * id of object to search for - * @param curs - * temporary working space associated with the calling thread. - * @return collection of loaders for this object, from all packs containing - * this object - * @throws IOException - */ - public abstract Collection<PackedObjectLoader> openObjectInAllPacks( - AnyObjectId objectId, WindowCursor curs) - throws IOException; - - /** - * Open object in all packs containing specified object. - * - * @param objectId - * id of object to search for - * @param resultLoaders - * result collection of loaders for this object, filled with - * loaders from all packs containing specified object - * @param curs - * temporary working space associated with the calling thread. - * @throws IOException - */ - abstract void openObjectInAllPacks(final AnyObjectId objectId, - final Collection<PackedObjectLoader> resultLoaders, - final WindowCursor curs) throws IOException; - - /** * @param id * SHA'1 of a blob * @return an {@link ObjectLoader} for accessing the data of a named blob diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/WindowCursor.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/WindowCursor.java index 968c92e5ce..afc7f7186a 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/WindowCursor.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/WindowCursor.java @@ -45,11 +45,14 @@ package org.eclipse.jgit.lib; import java.io.IOException; +import java.util.Collection; import java.util.zip.DataFormatException; import java.util.zip.Inflater; +import org.eclipse.jgit.errors.MissingObjectException; + /** Active handle to a ByteWindow. */ -public final class WindowCursor { +final class WindowCursor extends ObjectReader { /** Temporary buffer large enough for at least one raw object id. */ final byte[] tempId = new byte[Constants.OBJECT_ID_LENGTH]; @@ -57,6 +60,32 @@ public final class WindowCursor { private ByteWindow window; + private final FileObjectDatabase db; + + WindowCursor(FileObjectDatabase db) { + this.db = db; + } + + public boolean hasObject(AnyObjectId objectId) throws IOException { + return db.hasObject(objectId); + } + + public ObjectLoader openObject(AnyObjectId objectId, int typeHint) + throws MissingObjectException, IOException { + final ObjectLoader ldr = db.openObject(this, objectId); + if (ldr == null) { + if (typeHint == OBJ_ANY) + throw new MissingObjectException(objectId.copy(), "unknown"); + throw new MissingObjectException(objectId.copy(), typeHint); + } + return ldr; + } + + void openObjectInAllPacks(AnyObjectId otp, + Collection<PackedObjectLoader> reuseLoaders) throws IOException { + db.openObjectInAllPacks(reuseLoaders, this, otp); + } + /** * Copy bytes from the window to a caller supplied buffer. * @@ -168,14 +197,4 @@ public final class WindowCursor { inf = null; } } - - /** - * @param curs cursor to release; may be null. - * @return always null. - */ - public static WindowCursor release(final WindowCursor curs) { - if (curs != null) - curs.release(); - return null; - } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/merge/Merger.java b/org.eclipse.jgit/src/org/eclipse/jgit/merge/Merger.java index 59b826438e..38a8b8eae5 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/merge/Merger.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/merge/Merger.java @@ -53,7 +53,7 @@ import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectInserter; import org.eclipse.jgit.lib.Repository; -import org.eclipse.jgit.lib.WindowCursor; +import org.eclipse.jgit.lib.ObjectReader; import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.revwalk.RevObject; import org.eclipse.jgit.revwalk.RevTree; @@ -202,7 +202,7 @@ public abstract class Merger { */ protected AbstractTreeIterator openTree(final AnyObjectId treeId) throws IncorrectObjectTypeException, IOException { - final WindowCursor curs = new WindowCursor(); + final ObjectReader curs = db.newObjectReader(); try { return new CanonicalTreeParser(null, db, treeId, curs); } finally { diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevWalk.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevWalk.java index e42554811b..1224182960 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevWalk.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevWalk.java @@ -62,7 +62,7 @@ import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectIdSubclassMap; import org.eclipse.jgit.lib.ObjectLoader; import org.eclipse.jgit.lib.Repository; -import org.eclipse.jgit.lib.WindowCursor; +import org.eclipse.jgit.lib.ObjectReader; import org.eclipse.jgit.revwalk.filter.RevFilter; import org.eclipse.jgit.treewalk.filter.TreeFilter; @@ -159,7 +159,7 @@ public class RevWalk implements Iterable<RevCommit> { final Repository db; - final WindowCursor curs; + final ObjectReader curs; final MutableObjectId idBuffer; @@ -193,7 +193,7 @@ public class RevWalk implements Iterable<RevCommit> { */ public RevWalk(final Repository repo) { db = repo; - curs = new WindowCursor(); + curs = db.newObjectReader(); idBuffer = new MutableObjectId(); objects = new ObjectIdSubclassMap<RevObject>(); roots = new ArrayList<RevCommit>(); 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 f6e04107f6..0cd6733695 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/IndexPack.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/IndexPack.java @@ -79,7 +79,7 @@ import org.eclipse.jgit.lib.PackIndexWriter; import org.eclipse.jgit.lib.PackLock; import org.eclipse.jgit.lib.ProgressMonitor; import org.eclipse.jgit.lib.Repository; -import org.eclipse.jgit.lib.WindowCursor; +import org.eclipse.jgit.lib.ObjectReader; import org.eclipse.jgit.util.NB; /** Indexes Git pack files for local use. */ @@ -213,7 +213,7 @@ public class IndexPack { /** If {@link #fixThin} this is the last byte of the original checksum. */ private long originalEOF; - private WindowCursor readCurs; + private ObjectReader readCurs; /** * Create a new pack indexer utility. @@ -232,7 +232,7 @@ public class IndexPack { objectDatabase = db.getObjectDatabase().newCachedDatabase(); in = src; inflater = InflaterCache.get(); - readCurs = new WindowCursor(); + readCurs = objectDatabase.newReader(); buf = new byte[BUFFER_SIZE]; objectData = new byte[BUFFER_SIZE]; objectDigest = Constants.newMessageDigest(); @@ -430,7 +430,13 @@ public class IndexPack { inflater = null; objectDatabase.close(); } - readCurs = WindowCursor.release(readCurs); + + try { + if (readCurs != null) + readCurs.release(); + } finally { + readCurs = null; + } progress.endTask(); if (packOut != null) @@ -847,12 +853,16 @@ public class IndexPack { } } - final ObjectLoader ldr = objectDatabase.openObject(readCurs, id); - if (ldr != null) { + try { + final ObjectLoader ldr = readCurs.openObject(id, type); final byte[] existingData = ldr.getCachedBytes(); if (ldr.getType() != type || !Arrays.equals(data, existingData)) { throw new IOException(MessageFormat.format(JGitText.get().collisionOn, id.name())); } + } catch (MissingObjectException notLocal) { + // This is OK, we don't have a copy of the object locally + // but the API throws when we try to read it as usually its + // an error to read something that doesn't exist. } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/AbstractTreeIterator.java b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/AbstractTreeIterator.java index 90cea0f1be..73357a4dfe 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/AbstractTreeIterator.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/AbstractTreeIterator.java @@ -56,7 +56,7 @@ import org.eclipse.jgit.lib.FileMode; import org.eclipse.jgit.lib.MutableObjectId; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.Repository; -import org.eclipse.jgit.lib.WindowCursor; +import org.eclipse.jgit.lib.ObjectReader; import org.eclipse.jgit.treewalk.filter.TreeFilter; /** @@ -474,7 +474,7 @@ public abstract class AbstractTreeIterator { * a loose object or pack file could not be read. */ public AbstractTreeIterator createSubtreeIterator(final Repository repo, - final MutableObjectId idBuffer, final WindowCursor curs) + final MutableObjectId idBuffer, final ObjectReader curs) throws IncorrectObjectTypeException, IOException { return createSubtreeIterator(repo); } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/CanonicalTreeParser.java b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/CanonicalTreeParser.java index 0b9dc00446..b7f980ccaa 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/CanonicalTreeParser.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/CanonicalTreeParser.java @@ -56,7 +56,7 @@ import org.eclipse.jgit.lib.MutableObjectId; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectLoader; import org.eclipse.jgit.lib.Repository; -import org.eclipse.jgit.lib.WindowCursor; +import org.eclipse.jgit.lib.ObjectReader; /** Parses raw Git trees from the canonical semi-text/semi-binary format. */ public class CanonicalTreeParser extends AbstractTreeIterator { @@ -102,7 +102,7 @@ public class CanonicalTreeParser extends AbstractTreeIterator { * a loose object or pack file could not be read. */ public CanonicalTreeParser(final byte[] prefix, final Repository repo, - final AnyObjectId treeId, final WindowCursor curs) + final AnyObjectId treeId, final ObjectReader curs) throws IncorrectObjectTypeException, IOException { super(prefix); reset(repo, treeId, curs); @@ -148,7 +148,7 @@ public class CanonicalTreeParser extends AbstractTreeIterator { * a loose object or pack file could not be read. */ public CanonicalTreeParser resetRoot(final Repository repo, - final AnyObjectId id, final WindowCursor curs) + final AnyObjectId id, final ObjectReader curs) throws IncorrectObjectTypeException, IOException { CanonicalTreeParser p = this; while (p.parent != null) @@ -197,7 +197,7 @@ public class CanonicalTreeParser extends AbstractTreeIterator { * a loose object or pack file could not be read. */ public void reset(final Repository repo, final AnyObjectId id, - final WindowCursor curs) + final ObjectReader curs) throws IncorrectObjectTypeException, IOException { final ObjectLoader ldr = repo.openObject(curs, id); if (ldr == null) { @@ -214,7 +214,7 @@ public class CanonicalTreeParser extends AbstractTreeIterator { @Override public CanonicalTreeParser createSubtreeIterator(final Repository repo, - final MutableObjectId idBuffer, final WindowCursor curs) + final MutableObjectId idBuffer, final ObjectReader curs) throws IncorrectObjectTypeException, IOException { idBuffer.fromRaw(idBuffer(), idOffset()); if (!FileMode.TREE.equals(mode)) { @@ -242,7 +242,7 @@ public class CanonicalTreeParser extends AbstractTreeIterator { * a loose object or pack file could not be read. */ public final CanonicalTreeParser createSubtreeIterator0( - final Repository repo, final AnyObjectId id, final WindowCursor curs) + final Repository repo, final AnyObjectId id, final ObjectReader curs) throws IOException { final CanonicalTreeParser p = new CanonicalTreeParser(this); p.reset(repo, id, curs); @@ -251,7 +251,7 @@ public class CanonicalTreeParser extends AbstractTreeIterator { public CanonicalTreeParser createSubtreeIterator(final Repository repo) throws IncorrectObjectTypeException, IOException { - final WindowCursor curs = new WindowCursor(); + final ObjectReader curs = repo.newObjectReader(); try { return createSubtreeIterator(repo, new MutableObjectId(), curs); } finally { diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/TreeWalk.java b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/TreeWalk.java index 25ab78ef04..aefa79c3a8 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/TreeWalk.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/TreeWalk.java @@ -57,7 +57,7 @@ import org.eclipse.jgit.lib.FileMode; import org.eclipse.jgit.lib.MutableObjectId; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.Repository; -import org.eclipse.jgit.lib.WindowCursor; +import org.eclipse.jgit.lib.ObjectReader; import org.eclipse.jgit.revwalk.RevTree; import org.eclipse.jgit.treewalk.filter.PathFilterGroup; import org.eclipse.jgit.treewalk.filter.TreeFilter; @@ -155,7 +155,7 @@ public class TreeWalk { private final MutableObjectId idBuffer = new MutableObjectId(); - private final WindowCursor curs = new WindowCursor(); + private final ObjectReader curs; private TreeFilter filter; @@ -181,6 +181,7 @@ public class TreeWalk { */ public TreeWalk(final Repository repo) { db = repo; + curs = repo.newObjectReader(); filter = TreeFilter.ALL; trees = new AbstractTreeIterator[] { new EmptyTreeIterator() }; } |