This implements the DirCache portion of "git read-tree", where a tree can be recursively read into a DirCache instance without an impact on the working directory. Signed-off-by: Shawn O. Pearce <spearce@xxxxxxxxxxx> --- .../org/spearce/jgit/dircache/DirCacheBuilder.java | 58 ++++++++++++++++++++ 1 files changed, 58 insertions(+), 0 deletions(-) diff --git a/org.spearce.jgit/src/org/spearce/jgit/dircache/DirCacheBuilder.java b/org.spearce.jgit/src/org/spearce/jgit/dircache/DirCacheBuilder.java index 3a37054..88bda4d 100644 --- a/org.spearce.jgit/src/org/spearce/jgit/dircache/DirCacheBuilder.java +++ b/org.spearce.jgit/src/org/spearce/jgit/dircache/DirCacheBuilder.java @@ -37,8 +37,15 @@ package org.spearce.jgit.dircache; +import java.io.IOException; import java.util.Arrays; +import org.spearce.jgit.lib.AnyObjectId; +import org.spearce.jgit.lib.Repository; +import org.spearce.jgit.treewalk.AbstractTreeIterator; +import org.spearce.jgit.treewalk.CanonicalTreeParser; +import org.spearce.jgit.treewalk.TreeWalk; + /** * Updates a {@link DirCache} by adding individual {@link DirCacheEntry}s. * <p> @@ -112,6 +119,57 @@ public void keep(final int pos, int cnt) { fastKeep(pos, cnt); } + /** + * Recursively add an entire tree into this builder. + * <p> + * If pathPrefix is "a/b" and the tree contains file "c" then the resulting + * DirCacheEntry will have the path "a/b/c". + * <p> + * All entries are inserted at stage 0, therefore assuming that the + * application will not insert any other paths with the same pathPrefix. + * + * @param pathPrefix + * UTF-8 encoded prefix to mount the tree's entries at. If the + * path does not end with '/' one will be automatically inserted + * as necessary. + * @param db + * repository the tree(s) will be read from during recursive + * traversal. This must be the same repository that the resulting + * DirCache would be written out to (or used in) otherwise the + * caller is simply asking for deferred MissingObjectExceptions. + * @param tree + * the tree to recursively add. This tree's contents will appear + * under <code>pathPrefix</code>. The ObjectId must be that of a + * tree; the caller is responsible for dereferencing a tag or + * commit (if necessary). + * @throws IOException + * a tree cannot be read to iterate through its entries. + */ + public void addTree(final byte[] pathPrefix, final Repository db, + final AnyObjectId tree) throws IOException { + final TreeWalk tw = new TreeWalk(db); + tw.reset(); + tw.addTree(new CanonicalTreeParser(pathPrefix, db, tree.toObjectId())); + tw.setRecursive(true); + if (tw.next()) { + final DirCacheEntry newEntry = toEntry(tw); + beforeAdd(newEntry); + fastAdd(newEntry); + while (tw.next()) + fastAdd(toEntry(tw)); + } + } + + private DirCacheEntry toEntry(final TreeWalk tw) { + final DirCacheEntry e = new DirCacheEntry(tw.getRawPath()); + final AbstractTreeIterator i; + + i = tw.getTree(0, AbstractTreeIterator.class); + e.setFileMode(tw.getFileMode(0)); + e.setObjectIdFromRaw(i.idBuffer(), i.idOffset()); + return e; + } + public void finish() { if (!sorted) resort(); -- 1.6.0.2.706.g340fc -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html