From 121d009b9b7159ca0bd73a7c25b925516852a026 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Mon, 28 Jun 2010 18:25:22 -0700 Subject: [PATCH] Use ObjectReader in RevWalk, TreeWalk We don't actually need a Repository object here, just an ObjectReader that can load content for us. So change the API to depend on that. However, this breaks the asCommit and asTag legacy translation methods on RevCommit and RevTag, so we still have to keep the Repository inside of RevWalk for those two types. Hopefully we can drop those in the future, and then drop the Repository off the RevWalk. Change-Id: Iba983e48b663790061c43ae9ffbb77dfe6f4818e Signed-off-by: Shawn O. Pearce --- .../eclipse/jgit/junit/TestRepository.java | 2 +- .../pgm/opt/AbstractTreeIteratorHandler.java | 2 +- .../treewalk/AbstractTreeIteratorTest.java | 4 +- .../jgit/treewalk/EmptyTreeIteratorTest.java | 7 +- .../jgit/treewalk/FileTreeIteratorTest.java | 4 +- .../jgit/dircache/DirCacheBuildIterator.java | 4 +- .../jgit/dircache/DirCacheBuilder.java | 28 ++++---- .../jgit/dircache/DirCacheIterator.java | 4 +- .../org/eclipse/jgit/lib/ObjectReader.java | 22 ++++++- .../src/org/eclipse/jgit/merge/Merger.java | 14 ++-- .../merge/StrategySimpleTwoWayInCore.java | 2 +- .../jgit/revwalk/MergeBaseGenerator.java | 2 +- .../org/eclipse/jgit/revwalk/ObjectWalk.java | 25 +++++-- .../jgit/revwalk/PendingGenerator.java | 4 +- .../org/eclipse/jgit/revwalk/RevCommit.java | 3 +- .../org/eclipse/jgit/revwalk/RevObject.java | 2 +- .../src/org/eclipse/jgit/revwalk/RevTag.java | 2 +- .../src/org/eclipse/jgit/revwalk/RevWalk.java | 52 +++++++++++---- .../jgit/revwalk/RewriteTreeFilter.java | 2 +- .../eclipse/jgit/storage/pack/PackWriter.java | 2 +- .../eclipse/jgit/transport/ReceivePack.java | 2 +- .../eclipse/jgit/transport/RefAdvertiser.java | 11 ++-- .../jgit/treewalk/AbstractTreeIterator.java | 22 +++---- .../jgit/treewalk/CanonicalTreeParser.java | 65 +++++++------------ .../jgit/treewalk/EmptyTreeIterator.java | 4 +- .../jgit/treewalk/FileTreeIterator.java | 4 +- .../jgit/treewalk/NameConflictTreeWalk.java | 13 +++- .../org/eclipse/jgit/treewalk/TreeWalk.java | 55 ++++++++++------ 28 files changed, 221 insertions(+), 142 deletions(-) diff --git a/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/TestRepository.java b/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/TestRepository.java index a179773d15..96b616889c 100644 --- a/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/TestRepository.java +++ b/org.eclipse.jgit.junit/src/org/eclipse/jgit/junit/TestRepository.java @@ -272,7 +272,7 @@ public class TestRepository { */ public RevObject get(final RevTree tree, final String path) throws AssertionFailedError, Exception { - final TreeWalk tw = new TreeWalk(db); + final TreeWalk tw = new TreeWalk(pool.getObjectReader()); tw.setFilter(PathFilterGroup.createFromStrings(Collections .singleton(path))); tw.reset(tree); 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 d7b98c5098..01981600dd 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 @@ -123,7 +123,7 @@ public class AbstractTreeIteratorHandler extends final CanonicalTreeParser p = new CanonicalTreeParser(); final ObjectReader curs = clp.getRepository().newObjectReader(); try { - p.reset(clp.getRepository(), clp.getRevWalk().parseTree(id), curs); + p.reset(curs, clp.getRevWalk().parseTree(id)); } catch (MissingObjectException e) { throw new CmdLineException(MessageFormat.format(CLIText.get().notATree, name)); } catch (IncorrectObjectTypeException e) { diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/AbstractTreeIteratorTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/AbstractTreeIteratorTest.java index e96445a30a..12c11482ae 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/AbstractTreeIteratorTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/AbstractTreeIteratorTest.java @@ -51,7 +51,7 @@ import junit.framework.TestCase; import org.eclipse.jgit.errors.IncorrectObjectTypeException; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.FileMode; -import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.lib.ObjectReader; public class AbstractTreeIteratorTest extends TestCase { @@ -73,7 +73,7 @@ public class AbstractTreeIteratorTest extends TestCase { } @Override - public AbstractTreeIterator createSubtreeIterator(Repository repo) + public AbstractTreeIterator createSubtreeIterator(ObjectReader reader) throws IncorrectObjectTypeException, IOException { return null; } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/EmptyTreeIteratorTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/EmptyTreeIteratorTest.java index 111264b1c9..1ea2dc6250 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/EmptyTreeIteratorTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/EmptyTreeIteratorTest.java @@ -44,6 +44,7 @@ package org.eclipse.jgit.treewalk; import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.lib.ObjectReader; import org.eclipse.jgit.lib.RepositoryTestCase; public class EmptyTreeIteratorTest extends RepositoryTestCase { @@ -55,7 +56,8 @@ public class EmptyTreeIteratorTest extends RepositoryTestCase { public void testCreateSubtreeIterator() throws Exception { final EmptyTreeIterator etp = new EmptyTreeIterator(); - final AbstractTreeIterator sub = etp.createSubtreeIterator(db); + final ObjectReader reader = db.newObjectReader(); + final AbstractTreeIterator sub = etp.createSubtreeIterator(reader); assertNotNull(sub); assertTrue(sub.first()); assertTrue(sub.eof()); @@ -106,7 +108,8 @@ public class EmptyTreeIteratorTest extends RepositoryTestCase { called[0] = true; } }; - parent.createSubtreeIterator(db).stopWalk(); + final ObjectReader reader = db.newObjectReader(); + parent.createSubtreeIterator(reader).stopWalk(); assertTrue(called[0]); } } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/FileTreeIteratorTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/FileTreeIteratorTest.java index eb08e495b9..f939c90d81 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/FileTreeIteratorTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/FileTreeIteratorTest.java @@ -49,6 +49,7 @@ import java.security.MessageDigest; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.FileMode; import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.lib.ObjectReader; import org.eclipse.jgit.lib.RepositoryTestCase; import org.eclipse.jgit.util.RawParseUtils; @@ -124,7 +125,8 @@ public class FileTreeIteratorTest extends RepositoryTestCase { assertFalse(top.eof()); assertEquals(FileMode.TREE.getBits(), top.mode); - final AbstractTreeIterator sub = top.createSubtreeIterator(db); + final ObjectReader reader = db.newObjectReader(); + final AbstractTreeIterator sub = top.createSubtreeIterator(reader); assertTrue(sub instanceof FileTreeIterator); final FileTreeIterator subfti = (FileTreeIterator) sub; assertTrue(sub.first()); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheBuildIterator.java b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheBuildIterator.java index 181192d141..1eb95c4be0 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheBuildIterator.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheBuildIterator.java @@ -50,7 +50,7 @@ import java.io.IOException; import org.eclipse.jgit.errors.CorruptObjectException; import org.eclipse.jgit.errors.IncorrectObjectTypeException; import org.eclipse.jgit.lib.Constants; -import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.lib.ObjectReader; import org.eclipse.jgit.treewalk.AbstractTreeIterator; /** @@ -106,7 +106,7 @@ public class DirCacheBuildIterator extends DirCacheIterator { } @Override - public AbstractTreeIterator createSubtreeIterator(final Repository repo) + public AbstractTreeIterator createSubtreeIterator(final ObjectReader reader) throws IncorrectObjectTypeException, IOException { if (currentSubtree == null) throw new IncorrectObjectTypeException(getEntryObjectId(), 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 adb8a8d77f..ab75138434 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheBuilder.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheBuilder.java @@ -164,22 +164,22 @@ public class DirCacheBuilder extends BaseDirCacheEditor { */ public void addTree(final byte[] pathPrefix, final int stage, final Repository db, final AnyObjectId tree) throws IOException { - final TreeWalk tw = new TreeWalk(db); - tw.reset(); - final ObjectReader curs = db.newObjectReader(); + final ObjectReader reader = db.newObjectReader(); try { - tw.addTree(new CanonicalTreeParser(pathPrefix, db, tree - .toObjectId(), curs)); + final TreeWalk tw = new TreeWalk(reader); + tw.reset(); + tw.addTree(new CanonicalTreeParser(pathPrefix, reader, tree + .toObjectId())); + tw.setRecursive(true); + if (tw.next()) { + final DirCacheEntry newEntry = toEntry(stage, tw); + beforeAdd(newEntry); + fastAdd(newEntry); + while (tw.next()) + fastAdd(toEntry(stage, tw)); + } } finally { - curs.release(); - } - tw.setRecursive(true); - if (tw.next()) { - final DirCacheEntry newEntry = toEntry(stage, tw); - beforeAdd(newEntry); - fastAdd(newEntry); - while (tw.next()) - fastAdd(toEntry(stage, tw)); + reader.release(); } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheIterator.java b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheIterator.java index 9c47187821..b4e2d2c2dd 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheIterator.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheIterator.java @@ -50,7 +50,7 @@ import java.util.Arrays; import org.eclipse.jgit.errors.IncorrectObjectTypeException; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.FileMode; -import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.lib.ObjectReader; import org.eclipse.jgit.treewalk.AbstractTreeIterator; import org.eclipse.jgit.treewalk.EmptyTreeIterator; @@ -125,7 +125,7 @@ public class DirCacheIterator extends AbstractTreeIterator { } @Override - public AbstractTreeIterator createSubtreeIterator(final Repository repo) + public AbstractTreeIterator createSubtreeIterator(final ObjectReader reader) throws IncorrectObjectTypeException, IOException { if (currentSubtree == null) throw new IncorrectObjectTypeException(getEntryObjectId(), 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 e9afc5043e..1af3cb2dea 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectReader.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/ObjectReader.java @@ -69,8 +69,28 @@ public abstract class ObjectReader { * the object store cannot be accessed. */ public boolean has(AnyObjectId objectId) throws IOException { + return has(objectId, OBJ_ANY); + } + + /** + * Does the requested object exist in this database? + * + * @param objectId + * identity of the object to test for existence of. + * @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 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 + * the object store cannot be accessed. + */ + public boolean has(AnyObjectId objectId, int typeHint) throws IOException { try { - open(objectId); + open(objectId, typeHint); return true; } catch (MissingObjectException notFound) { return false; 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 d95b11159c..68d60c0077 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/merge/Merger.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/merge/Merger.java @@ -70,6 +70,9 @@ public abstract class Merger { /** The repository this merger operates on. */ protected final Repository db; + /** Reader to support {@link #walk} and other object loading. */ + protected final ObjectReader reader; + /** A RevWalk for computing merge bases, or listing incoming commits. */ protected final RevWalk walk; @@ -92,7 +95,8 @@ public abstract class Merger { */ protected Merger(final Repository local) { db = local; - walk = new RevWalk(db); + reader = db.newObjectReader(); + walk = new RevWalk(reader); } /** @@ -153,6 +157,7 @@ public abstract class Merger { } finally { if (inserter != null) inserter.release(); + reader.release(); } } @@ -207,12 +212,7 @@ public abstract class Merger { */ protected AbstractTreeIterator openTree(final AnyObjectId treeId) throws IncorrectObjectTypeException, IOException { - final ObjectReader curs = db.newObjectReader(); - try { - return new CanonicalTreeParser(null, db, treeId, curs); - } finally { - curs.release(); - } + return new CanonicalTreeParser(null, reader, treeId); } /** diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/merge/StrategySimpleTwoWayInCore.java b/org.eclipse.jgit/src/org/eclipse/jgit/merge/StrategySimpleTwoWayInCore.java index 891abe0580..86ba724746 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/merge/StrategySimpleTwoWayInCore.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/merge/StrategySimpleTwoWayInCore.java @@ -100,7 +100,7 @@ public class StrategySimpleTwoWayInCore extends ThreeWayMergeStrategy { InCoreMerger(final Repository local) { super(local); - tw = new NameConflictTreeWalk(db); + tw = new NameConflictTreeWalk(reader); cache = DirCache.newInCore(); } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/MergeBaseGenerator.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/MergeBaseGenerator.java index edb883714b..76510ce387 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/MergeBaseGenerator.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/MergeBaseGenerator.java @@ -137,7 +137,7 @@ class MergeBaseGenerator extends Generator { for (;;) { final RevCommit c = pending.next(); if (c == null) { - walker.curs.release(); + walker.reader.release(); return null; } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/ObjectWalk.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/ObjectWalk.java index 11d40012c5..9393e2d17e 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/ObjectWalk.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/ObjectWalk.java @@ -53,6 +53,7 @@ import org.eclipse.jgit.errors.MissingObjectException; import org.eclipse.jgit.lib.AnyObjectId; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.FileMode; +import org.eclipse.jgit.lib.ObjectReader; import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.treewalk.CanonicalTreeParser; @@ -97,7 +98,19 @@ public class ObjectWalk extends RevWalk { * the repository the walker will obtain data from. */ public ObjectWalk(final Repository repo) { - super(repo); + this(repo.newObjectReader()); + } + + /** + * Create a new revision and object walker for a given repository. + * + * @param or + * the reader the walker will obtain data from. The reader should + * be released by the caller when the walker is no longer + * required. + */ + public ObjectWalk(ObjectReader or) { + super(or); pendingObjects = new BlockObjQueue(); treeWalk = new CanonicalTreeParser(); } @@ -294,14 +307,14 @@ public class ObjectWalk extends RevWalk { continue; if (o instanceof RevTree) { currentTree = (RevTree) o; - treeWalk = treeWalk.resetRoot(db, currentTree, curs); + treeWalk = treeWalk.resetRoot(reader, currentTree); } return o; } } private CanonicalTreeParser enter(RevObject tree) throws IOException { - CanonicalTreeParser p = treeWalk.createSubtreeIterator0(db, tree, curs); + CanonicalTreeParser p = treeWalk.createSubtreeIterator0(reader, tree); if (p.eof()) { // We can't tolerate the subtree being an empty tree, as // that will break us out early before we visit all names. @@ -349,7 +362,7 @@ public class ObjectWalk extends RevWalk { final RevObject o = nextObject(); if (o == null) break; - if (o instanceof RevBlob && !db.hasObject(o)) + if (o instanceof RevBlob && !reader.has(o)) throw new MissingObjectException(o, Constants.TYPE_BLOB); } } @@ -403,7 +416,7 @@ public class ObjectWalk extends RevWalk { return; tree.flags |= UNINTERESTING; - treeWalk = treeWalk.resetRoot(db, tree, curs); + treeWalk = treeWalk.resetRoot(reader, tree); while (!treeWalk.eof()) { final FileMode mode = treeWalk.getEntryFileMode(); final int sType = mode.getObjectType(); @@ -419,7 +432,7 @@ public class ObjectWalk extends RevWalk { final RevTree t = lookupTree(idBuffer); if ((t.flags & UNINTERESTING) == 0) { t.flags |= UNINTERESTING; - treeWalk = treeWalk.createSubtreeIterator0(db, t, curs); + treeWalk = treeWalk.createSubtreeIterator0(reader, t); continue; } break; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/PendingGenerator.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/PendingGenerator.java index e723bce51b..0e2bb98320 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/PendingGenerator.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/PendingGenerator.java @@ -128,7 +128,7 @@ class PendingGenerator extends Generator { for (;;) { final RevCommit c = pending.next(); if (c == null) { - walker.curs.release(); + walker.reader.release(); return null; } @@ -174,7 +174,7 @@ class PendingGenerator extends Generator { c.disposeBody(); } } catch (StopWalkException swe) { - walker.curs.release(); + walker.reader.release(); pending.clear(); return null; } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevCommit.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevCommit.java index 2d96bbf676..84cc704c34 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevCommit.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevCommit.java @@ -214,7 +214,8 @@ public class RevCommit extends RevObject { * @return parsed commit. */ public final Commit asCommit(final RevWalk walk) { - return new Commit(walk.db, this, buffer); + // TODO(spearce) Remove repository when this method dies. + return new Commit(walk.repository, this, buffer); } /** diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevObject.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevObject.java index 14f4836d7a..a19f4d83ea 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevObject.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevObject.java @@ -77,7 +77,7 @@ public abstract class RevObject extends ObjectId { final byte[] loadCanonical(final RevWalk walk) throws IOException, MissingObjectException, IncorrectObjectTypeException, CorruptObjectException { - return walk.curs.open(this, getType()).getCachedBytes(); + return walk.reader.open(this, getType()).getCachedBytes(); } /** diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevTag.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevTag.java index d2a665e078..a04ea7154e 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevTag.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevTag.java @@ -194,7 +194,7 @@ public class RevTag extends RevObject { * @return parsed tag. */ public Tag asTag(final RevWalk walk) { - return new Tag(walk.db, this, tagName, buffer); + return new Tag(walk.repository, this, tagName, buffer); } /** 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 60c8024b3c..51de7c4a51 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevWalk.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RevWalk.java @@ -157,9 +157,10 @@ public class RevWalk implements Iterable { private static final int APP_FLAGS = -1 & ~((1 << RESERVED_FLAGS) - 1); - final Repository db; + /** Exists ONLY to support legacy Tag and Commit objects. */ + final Repository repository; - final ObjectReader curs; + final ObjectReader reader; final MutableObjectId idBuffer; @@ -189,11 +190,29 @@ public class RevWalk implements Iterable { * Create a new revision walker for a given repository. * * @param repo - * the repository the walker will obtain data from. + * the repository the walker will obtain data from. An + * ObjectReader will be created by the walker, and must be + * released by the caller. */ public RevWalk(final Repository repo) { - db = repo; - curs = db.newObjectReader(); + this(repo, repo.newObjectReader()); + } + + /** + * Create a new revision walker for a given repository. + * + * @param or + * the reader the walker will obtain data from. The reader should + * be released by the caller when the walker is no longer + * required. + */ + public RevWalk(ObjectReader or) { + this(null, or); + } + + private RevWalk(final Repository repo, final ObjectReader or) { + repository = repo; + reader = or; idBuffer = new MutableObjectId(); objects = new ObjectIdSubclassMap(); roots = new ArrayList(); @@ -205,13 +224,19 @@ public class RevWalk implements Iterable { retainBody = true; } + /** @return the reader this walker is using to load objects. */ + public ObjectReader getObjectReader() { + return reader; + } + /** - * Get the repository this walker loads objects from. - * - * @return the repository this walker was created to read. + * Release any resources used by this walker's reader. + *

+ * A walker that has been released can be used again, but may need to be + * released after the subsequent usage. */ - public Repository getRepository() { - return db; + public void release() { + reader.release(); } /** @@ -720,7 +745,7 @@ public class RevWalk implements Iterable { throws MissingObjectException, IOException { RevObject r = objects.get(id); if (r == null) { - final ObjectLoader ldr = curs.open(id); + final ObjectLoader ldr = reader.open(id); final byte[] data = ldr.getCachedBytes(); final int type = ldr.getType(); switch (type) { @@ -991,7 +1016,7 @@ public class RevWalk implements Iterable { } } - curs.release(); + reader.release(); roots.clear(); queue = new DateRevQueue(); pending = new StartGenerator(this); @@ -1006,11 +1031,12 @@ public class RevWalk implements Iterable { * All RevFlag instances are also invalidated, and must not be reused. */ public void dispose() { + reader.release(); freeFlags = APP_FLAGS; delayFreeFlags = 0; carryFlags = UNINTERESTING; objects.clear(); - curs.release(); + reader.release(); roots.clear(); queue = new DateRevQueue(); pending = new StartGenerator(this); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RewriteTreeFilter.java b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RewriteTreeFilter.java index d7e5c8028f..023ed45fd2 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RewriteTreeFilter.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/revwalk/RewriteTreeFilter.java @@ -77,7 +77,7 @@ class RewriteTreeFilter extends RevFilter { private final TreeWalk pathFilter; RewriteTreeFilter(final RevWalk walker, final TreeFilter t) { - pathFilter = new TreeWalk(walker.db); + pathFilter = new TreeWalk(walker.reader); pathFilter.setFilter(t); pathFilter.setRecursive(t.shouldBeRecursive()); } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/PackWriter.java b/org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/PackWriter.java index c7e3c0c9b0..3fab3f7470 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/PackWriter.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/PackWriter.java @@ -739,7 +739,7 @@ public class PackWriter { final Collection uninterestingObjects) throws MissingObjectException, IOException, IncorrectObjectTypeException { - final ObjectWalk walker = new ObjectWalk(db); + final ObjectWalk walker = new ObjectWalk(reader); walker.setRetainBody(false); walker.sort(RevSort.COMMIT_TIME_DESC); if (thin) 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 1597a35fe9..2475b9acfe 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivePack.java @@ -696,7 +696,7 @@ public class ReceivePack { adv.send(refs); if (head != null && !head.isSymbolic()) adv.advertiseHave(head.getObjectId()); - adv.includeAdditionalHaves(); + adv.includeAdditionalHaves(db); if (adv.isEmpty()) adv.advertiseId(ObjectId.zeroId(), "capabilities^{}"); adv.end(); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/RefAdvertiser.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/RefAdvertiser.java index 532cc11a7f..df0afe73fa 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/RefAdvertiser.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/RefAdvertiser.java @@ -54,6 +54,7 @@ import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.lib.RefComparator; +import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.revwalk.RevFlag; import org.eclipse.jgit.revwalk.RevObject; import org.eclipse.jgit.revwalk.RevTag; @@ -124,7 +125,7 @@ public abstract class RefAdvertiser { *

    *
  • {@link #send(Map)} *
  • {@link #advertiseHave(AnyObjectId)} - *
  • {@link #includeAdditionalHaves()} + *
  • {@link #includeAdditionalHaves(Repository)} *
* * @param deref @@ -142,7 +143,7 @@ public abstract class RefAdvertiser { *
    *
  • {@link #send(Map)} *
  • {@link #advertiseHave(AnyObjectId)} - *
  • {@link #includeAdditionalHaves()} + *
  • {@link #includeAdditionalHaves(Repository)} *
* * @param name @@ -210,12 +211,14 @@ public abstract class RefAdvertiser { /** * Include references of alternate repositories as {@code .have} lines. * + * @param src + * repository to get the additional reachable objects from. * @throws IOException * the underlying output stream failed to write out an * advertisement record. */ - public void includeAdditionalHaves() throws IOException { - for (ObjectId id : walk.getRepository().getAdditionalHaves()) + public void includeAdditionalHaves(Repository src) throws IOException { + for (ObjectId id : src.getAdditionalHaves()) advertiseHave(id); } 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 73357a4dfe..e74f13e851 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/AbstractTreeIterator.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/AbstractTreeIterator.java @@ -55,7 +55,6 @@ import org.eclipse.jgit.lib.Constants; 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.ObjectReader; import org.eclipse.jgit.treewalk.filter.TreeFilter; @@ -432,8 +431,8 @@ public abstract class AbstractTreeIterator { * otherwise the caller would not be able to exit out of the subtree * iterator correctly and return to continue walking this. * - * @param repo - * repository to load the tree data from. + * @param reader + * reader to load the tree data from. * @return a new parser that walks over the current subtree. * @throws IncorrectObjectTypeException * the current entry is not actually a tree and cannot be parsed @@ -441,8 +440,9 @@ public abstract class AbstractTreeIterator { * @throws IOException * a loose object or pack file could not be read. */ - public abstract AbstractTreeIterator createSubtreeIterator(Repository repo) - throws IncorrectObjectTypeException, IOException; + public abstract AbstractTreeIterator createSubtreeIterator( + ObjectReader reader) throws IncorrectObjectTypeException, + IOException; /** * Create a new iterator as though the current entry were a subtree. @@ -460,12 +460,10 @@ public abstract class AbstractTreeIterator { * the caller would not be able to exit out of the subtree iterator * correctly and return to continue walking this. * - * @param repo - * repository to load the tree data from. + * @param reader + * reader to load the tree data from. * @param idBuffer * temporary ObjectId buffer for use by this method. - * @param curs - * window cursor to use during repository access. * @return a new parser that walks over the current subtree. * @throws IncorrectObjectTypeException * the current entry is not actually a tree and cannot be parsed @@ -473,10 +471,10 @@ public abstract class AbstractTreeIterator { * @throws IOException * a loose object or pack file could not be read. */ - public AbstractTreeIterator createSubtreeIterator(final Repository repo, - final MutableObjectId idBuffer, final ObjectReader curs) + public AbstractTreeIterator createSubtreeIterator( + final ObjectReader reader, final MutableObjectId idBuffer) throws IncorrectObjectTypeException, IOException { - return createSubtreeIterator(repo); + return createSubtreeIterator(reader); } /** 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 fc088d7760..8e4094a055 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/CanonicalTreeParser.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/CanonicalTreeParser.java @@ -55,7 +55,6 @@ import org.eclipse.jgit.lib.FileMode; import org.eclipse.jgit.lib.MutableObjectId; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectReader; -import org.eclipse.jgit.lib.Repository; /** Parses raw Git trees from the canonical semi-text/semi-binary format. */ public class CanonicalTreeParser extends AbstractTreeIterator { @@ -85,13 +84,11 @@ public class CanonicalTreeParser extends AbstractTreeIterator { * may be null or the empty array to indicate the prefix is the * root of the repository. A trailing slash ('/') is * automatically appended if the prefix does not end in '/'. - * @param repo - * repository to load the tree data from. + * @param reader + * reader to load the tree data from. * @param treeId * identity of the tree being parsed; used only in exception * messages if data corruption is found. - * @param curs - * a window cursor to use during data access from the repository. * @throws MissingObjectException * the object supplied is not available from the repository. * @throws IncorrectObjectTypeException @@ -100,11 +97,11 @@ public class CanonicalTreeParser extends AbstractTreeIterator { * @throws IOException * a loose object or pack file could not be read. */ - public CanonicalTreeParser(final byte[] prefix, final Repository repo, - final AnyObjectId treeId, final ObjectReader curs) - throws IncorrectObjectTypeException, IOException { + public CanonicalTreeParser(final byte[] prefix, final ObjectReader reader, + final AnyObjectId treeId) throws IncorrectObjectTypeException, + IOException { super(prefix); - reset(repo, treeId, curs); + reset(reader, treeId); } private CanonicalTreeParser(final CanonicalTreeParser p) { @@ -130,13 +127,11 @@ public class CanonicalTreeParser extends AbstractTreeIterator { /** * Reset this parser to walk through the given tree. * - * @param repo - * repository to load the tree data from. + * @param reader + * reader to use during repository access. * @param id * identity of the tree being parsed; used only in exception * messages if data corruption is found. - * @param curs - * window cursor to use during repository access. * @return the root level parser. * @throws MissingObjectException * the object supplied is not available from the repository. @@ -146,13 +141,13 @@ public class CanonicalTreeParser extends AbstractTreeIterator { * @throws IOException * a loose object or pack file could not be read. */ - public CanonicalTreeParser resetRoot(final Repository repo, - final AnyObjectId id, final ObjectReader curs) - throws IncorrectObjectTypeException, IOException { + public CanonicalTreeParser resetRoot(final ObjectReader reader, + final AnyObjectId id) throws IncorrectObjectTypeException, + IOException { CanonicalTreeParser p = this; while (p.parent != null) p = (CanonicalTreeParser) p.parent; - p.reset(repo, id, curs); + p.reset(reader, id); return p; } @@ -180,13 +175,11 @@ public class CanonicalTreeParser extends AbstractTreeIterator { /** * Reset this parser to walk through the given tree. * - * @param repo - * repository to load the tree data from. + * @param reader + * reader to use during repository access. * @param id * identity of the tree being parsed; used only in exception * messages if data corruption is found. - * @param curs - * window cursor to use during repository access. * @throws MissingObjectException * the object supplied is not available from the repository. * @throws IncorrectObjectTypeException @@ -195,22 +188,21 @@ public class CanonicalTreeParser extends AbstractTreeIterator { * @throws IOException * a loose object or pack file could not be read. */ - public void reset(final Repository repo, final AnyObjectId id, - final ObjectReader curs) + public void reset(final ObjectReader reader, final AnyObjectId id) throws IncorrectObjectTypeException, IOException { - reset(curs.open(id, Constants.OBJ_TREE).getCachedBytes()); + reset(reader.open(id, Constants.OBJ_TREE).getCachedBytes()); } @Override - public CanonicalTreeParser createSubtreeIterator(final Repository repo, - final MutableObjectId idBuffer, final ObjectReader curs) + public CanonicalTreeParser createSubtreeIterator(final ObjectReader reader, + final MutableObjectId idBuffer) throws IncorrectObjectTypeException, IOException { idBuffer.fromRaw(idBuffer(), idOffset()); if (!FileMode.TREE.equals(mode)) { final ObjectId me = idBuffer.toObjectId(); throw new IncorrectObjectTypeException(me, Constants.TYPE_TREE); } - return createSubtreeIterator0(repo, idBuffer, curs); + return createSubtreeIterator0(reader, idBuffer); } /** @@ -220,32 +212,25 @@ public class CanonicalTreeParser extends AbstractTreeIterator { * called only once the current entry has been identified as a tree and its * identity has been converted into an ObjectId. * - * @param repo - * repository to load the tree data from. + * @param reader + * reader to load the tree data from. * @param id * ObjectId of the tree to open. - * @param curs - * window cursor to use during repository access. * @return a new parser that walks over the current subtree. * @throws IOException * a loose object or pack file could not be read. */ public final CanonicalTreeParser createSubtreeIterator0( - final Repository repo, final AnyObjectId id, final ObjectReader curs) + final ObjectReader reader, final AnyObjectId id) throws IOException { final CanonicalTreeParser p = new CanonicalTreeParser(this); - p.reset(repo, id, curs); + p.reset(reader, id); return p; } - public CanonicalTreeParser createSubtreeIterator(final Repository repo) + public CanonicalTreeParser createSubtreeIterator(final ObjectReader reader) throws IncorrectObjectTypeException, IOException { - final ObjectReader curs = repo.newObjectReader(); - try { - return createSubtreeIterator(repo, new MutableObjectId(), curs); - } finally { - curs.release(); - } + return createSubtreeIterator(reader, new MutableObjectId()); } @Override diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/EmptyTreeIterator.java b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/EmptyTreeIterator.java index 1776b50887..7d4ee6d2bd 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/EmptyTreeIterator.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/EmptyTreeIterator.java @@ -50,7 +50,7 @@ import java.io.IOException; import org.eclipse.jgit.errors.CorruptObjectException; import org.eclipse.jgit.errors.IncorrectObjectTypeException; import org.eclipse.jgit.lib.ObjectId; -import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.lib.ObjectReader; /** Iterator over an empty tree (a directory with no files). */ public class EmptyTreeIterator extends AbstractTreeIterator { @@ -87,7 +87,7 @@ public class EmptyTreeIterator extends AbstractTreeIterator { } @Override - public AbstractTreeIterator createSubtreeIterator(final Repository repo) + public AbstractTreeIterator createSubtreeIterator(final ObjectReader reader) throws IncorrectObjectTypeException, IOException { return new EmptyTreeIterator(this); } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/FileTreeIterator.java b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/FileTreeIterator.java index 8dfab8aa57..7f63646b5b 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/FileTreeIterator.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/FileTreeIterator.java @@ -54,7 +54,7 @@ import java.io.InputStream; import org.eclipse.jgit.errors.IncorrectObjectTypeException; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.FileMode; -import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.lib.ObjectReader; import org.eclipse.jgit.util.FS; /** @@ -103,7 +103,7 @@ public class FileTreeIterator extends WorkingTreeIterator { } @Override - public AbstractTreeIterator createSubtreeIterator(final Repository repo) + public AbstractTreeIterator createSubtreeIterator(final ObjectReader reader) throws IncorrectObjectTypeException, IOException { return new FileTreeIterator(this, ((FileEntry) current()).file, fs); } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/NameConflictTreeWalk.java b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/NameConflictTreeWalk.java index b569174bdb..99126e8615 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/NameConflictTreeWalk.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/NameConflictTreeWalk.java @@ -46,6 +46,7 @@ package org.eclipse.jgit.treewalk; import org.eclipse.jgit.dircache.DirCacheBuilder; import org.eclipse.jgit.errors.CorruptObjectException; import org.eclipse.jgit.lib.FileMode; +import org.eclipse.jgit.lib.ObjectReader; import org.eclipse.jgit.lib.Repository; /** @@ -93,7 +94,17 @@ public class NameConflictTreeWalk extends TreeWalk { * the repository the walker will obtain data from. */ public NameConflictTreeWalk(final Repository repo) { - super(repo); + this(repo.newObjectReader()); + } + + /** + * Create a new tree walker for a given repository. + * + * @param or + * the reader the walker will obtain tree data from. + */ + public NameConflictTreeWalk(final ObjectReader or) { + super(or); } @Override 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 aefa79c3a8..2ebabcb94d 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/TreeWalk.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/TreeWalk.java @@ -113,11 +113,15 @@ public class TreeWalk { final AnyObjectId... trees) throws MissingObjectException, IncorrectObjectTypeException, CorruptObjectException, IOException { final TreeWalk r = new TreeWalk(db); - r.setFilter(PathFilterGroup.createFromStrings(Collections - .singleton(path))); - r.setRecursive(r.getFilter().shouldBeRecursive()); - r.reset(trees); - return r.next() ? r : null; + try { + r.setFilter(PathFilterGroup.createFromStrings(Collections + .singleton(path))); + r.setRecursive(r.getFilter().shouldBeRecursive()); + r.reset(trees); + return r.next() ? r : null; + } finally { + r.release(); + } } /** @@ -151,12 +155,10 @@ public class TreeWalk { return forPath(db, path, new ObjectId[] { tree }); } - private final Repository db; + private final ObjectReader reader; private final MutableObjectId idBuffer = new MutableObjectId(); - private final ObjectReader curs; - private TreeFilter filter; AbstractTreeIterator[] trees; @@ -180,19 +182,34 @@ public class TreeWalk { * the repository the walker will obtain data from. */ public TreeWalk(final Repository repo) { - db = repo; - curs = repo.newObjectReader(); + this(repo.newObjectReader()); + } + + /** + * Create a new tree walker for a given repository. + * + * @param or + * the reader the walker will obtain tree data from. + */ + public TreeWalk(final ObjectReader or) { + reader = or; filter = TreeFilter.ALL; trees = new AbstractTreeIterator[] { new EmptyTreeIterator() }; } + /** @return the reader this walker is using to load objects. */ + public ObjectReader getObjectReader() { + return reader; + } + /** - * Get the repository this tree walker is reading from. - * - * @return the repository configured when the walker was created. + * Release any resources used by this walker's reader. + *

+ * A walker that has been released can be used again, but may need to be + * released after the subsequent usage. */ - public Repository getRepository() { - return db; + public void release() { + reader.release(); } /** @@ -320,7 +337,7 @@ public class TreeWalk { if (o instanceof CanonicalTreeParser) { o.matches = null; o.matchShift = 0; - ((CanonicalTreeParser) o).reset(db, id, curs); + ((CanonicalTreeParser) o).reset(reader, id); trees[0] = o; } else { trees[0] = parserFor(id); @@ -367,7 +384,7 @@ public class TreeWalk { if (o instanceof CanonicalTreeParser && o.pathOffset == 0) { o.matches = null; o.matchShift = 0; - ((CanonicalTreeParser) o).reset(db, ids[i], curs); + ((CanonicalTreeParser) o).reset(reader, ids[i]); r[i] = o; continue; } @@ -837,7 +854,7 @@ public class TreeWalk { final AbstractTreeIterator t = trees[i]; final AbstractTreeIterator n; if (t.matches == ch && !t.eof() && FileMode.TREE.equals(t.mode)) - n = t.createSubtreeIterator(db, idBuffer, curs); + n = t.createSubtreeIterator(reader, idBuffer); else n = t.createEmptyTreeIterator(); tmp[i] = n; @@ -912,7 +929,7 @@ public class TreeWalk { private CanonicalTreeParser parserFor(final AnyObjectId id) throws IncorrectObjectTypeException, IOException { final CanonicalTreeParser p = new CanonicalTreeParser(); - p.reset(db, id, curs); + p.reset(reader, id); return p; } -- 2.39.5