/** * Reset this walker to run over a set of existing trees. * * @param ids the trees we need to parse. The walker will execute over this many parallel trees if * the reset is successful. * @throws MissingObjectException the given tree object does not exist in this repository. * @throws IncorrectObjectTypeException the given object id does not denote a tree, but instead * names some other non-tree type of object. Note that commits are not trees, even if they are * sometimes called a "tree-ish". * @throws CorruptObjectException the object claimed to be a tree, but its contents did not appear * to be a tree. The repository may have data corruption. * @throws IOException a loose object or pack file could not be read. */ public void reset(final AnyObjectId[] ids) throws MissingObjectException, IncorrectObjectTypeException, CorruptObjectException, IOException { final int oldLen = trees.length; final int newLen = ids.length; final AbstractTreeIterator[] r = newLen == oldLen ? trees : new AbstractTreeIterator[newLen]; for (int i = 0; i < newLen; i++) { AbstractTreeIterator o; if (i < oldLen) { o = trees[i]; while (o.parent != null) o = o.parent; if (o instanceof CanonicalTreeParser && o.pathOffset == 0) { o.matches = null; o.matchShift = 0; ((CanonicalTreeParser) o).reset(db, ids[i], curs); r[i] = o; continue; } } o = parserFor(ids[i]); r[i] = o; } trees = r; advance = false; depth = 0; }
void skipEntriesEqual() throws CorruptObjectException { final AbstractTreeIterator ch = currentHead; for (int i = 0; i < trees.length; i++) { final AbstractTreeIterator t = trees[i]; if (t.matches == ch) { t.skip(); t.matches = null; } } }
private void exitSubtree() { depth--; for (int i = 0; i < trees.length; i++) trees[i] = trees[i].parent; AbstractTreeIterator minRef = null; for (final AbstractTreeIterator t : trees) { if (t.matches != t) continue; if (minRef == null || t.pathCompare(minRef) < 0) minRef = t; } currentHead = minRef; }
/** * Add an already created tree iterator for walking. * * <p>The position of this tree is returned to the caller, in case the caller has lost track of * the order they added the trees into the walker. * * <p>The tree which the iterator operates on must have the same root as existing trees in the * walk. * * @param p an iterator to walk over. The iterator should be new, with no parent, and should still * be positioned before the first entry. The tree which the iterator operates on must have the * same root as other trees in the walk. * @return position of this tree within the walker. * @throws CorruptObjectException the iterator was unable to obtain its first entry, due to * possible data corruption within the backing data store. */ public int addTree(final AbstractTreeIterator p) throws CorruptObjectException { final int n = trees.length; final AbstractTreeIterator[] newTrees = new AbstractTreeIterator[n + 1]; System.arraycopy(trees, 0, newTrees, 0, n); newTrees[n] = p; p.matches = null; p.matchShift = 0; trees = newTrees; return n; }
/** * Compare two tree's current ObjectId values for equality. * * @param nthA first tree to compare the object id from. * @param nthB second tree to compare the object id from. * @return result of <code>getObjectId(nthA).equals(getObjectId(nthB))</code>. * @see #getObjectId(int) */ public boolean idEqual(final int nthA, final int nthB) { final AbstractTreeIterator ch = currentHead; final AbstractTreeIterator a = trees[nthA]; final AbstractTreeIterator b = trees[nthB]; if (a.matches == ch && b.matches == ch) return a.idEqual(b); if (a.matches != ch && b.matches != ch) { // If neither tree matches the current path node then neither // tree has this entry. In such case the ObjectId is zero(), // and zero() is always equal to zero(). // return true; } return false; }
/** * Enter into the current subtree. * * <p>If the current entry is a subtree this method arranges for its children to be returned * before the next sibling following the subtree is returned. * * @throws MissingObjectException a subtree was found, but the subtree object does not exist in * this repository. The repository may be missing objects. * @throws IncorrectObjectTypeException a subtree was found, and the subtree id does not denote a * tree, but instead names some other non-tree type of object. The repository may have data * corruption. * @throws CorruptObjectException the contents of a tree did not appear to be a tree. The * repository may have data corruption. * @throws IOException a loose object or pack file could not be read. */ public void enterSubtree() throws MissingObjectException, IncorrectObjectTypeException, CorruptObjectException, IOException { final AbstractTreeIterator ch = currentHead; final AbstractTreeIterator[] tmp = new AbstractTreeIterator[trees.length]; for (int i = 0; i < trees.length; i++) { 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); else n = t.createEmptyTreeIterator(); tmp[i] = n; } depth++; advance = false; System.arraycopy(tmp, 0, trees, 0, trees.length); }
/** * Advance this walker to the next relevant entry. * * @return true if there is an entry available; false if all entries have been walked and the walk * of this set of tree iterators is over. * @throws MissingObjectException {@link #isRecursive()} was enabled, a subtree was found, but the * subtree object does not exist in this repository. The repository may be missing objects. * @throws IncorrectObjectTypeException {@link #isRecursive()} was enabled, a subtree was found, * and the subtree id does not denote a tree, but instead names some other non-tree type of * object. The repository may have data corruption. * @throws CorruptObjectException the contents of a tree did not appear to be a tree. The * repository may have data corruption. * @throws IOException a loose object or pack file could not be read. */ public boolean next() throws MissingObjectException, IncorrectObjectTypeException, CorruptObjectException, IOException { try { if (advance) { advance = false; postChildren = false; popEntriesEqual(); } for (; ; ) { final AbstractTreeIterator t = min(); if (t.eof()) { if (depth > 0) { exitSubtree(); if (postOrderTraversal) { advance = true; postChildren = true; return true; } popEntriesEqual(); continue; } return false; } currentHead = t; if (!filter.include(this)) { skipEntriesEqual(); continue; } if (recursive && FileMode.TREE.equals(t.mode)) { enterSubtree(); continue; } advance = true; return true; } } catch (StopWalkException stop) { for (final AbstractTreeIterator t : trees) t.stopWalk(); return false; } }
/** * Reset this walker to run over a single existing tree. * * @param id the tree we need to parse. The walker will execute over this single tree if the reset * is successful. * @throws MissingObjectException the given tree object does not exist in this repository. * @throws IncorrectObjectTypeException the given object id does not denote a tree, but instead * names some other non-tree type of object. Note that commits are not trees, even if they are * sometimes called a "tree-ish". * @throws CorruptObjectException the object claimed to be a tree, but its contents did not appear * to be a tree. The repository may have data corruption. * @throws IOException a loose object or pack file could not be read. */ public void reset(final AnyObjectId id) throws MissingObjectException, IncorrectObjectTypeException, CorruptObjectException, IOException { if (trees.length == 1) { AbstractTreeIterator o = trees[0]; while (o.parent != null) o = o.parent; if (o instanceof CanonicalTreeParser) { o.matches = null; o.matchShift = 0; ((CanonicalTreeParser) o).reset(db, id, curs); trees[0] = o; } else { trees[0] = parserFor(id); } } else { trees = new AbstractTreeIterator[] {parserFor(id)}; } advance = false; depth = 0; }
AbstractTreeIterator min() throws CorruptObjectException { int i = 0; AbstractTreeIterator minRef = trees[i]; while (minRef.eof() && ++i < trees.length) minRef = trees[i]; if (minRef.eof()) return minRef; minRef.matches = minRef; while (++i < trees.length) { final AbstractTreeIterator t = trees[i]; if (t.eof()) continue; final int cmp = t.pathCompare(minRef); if (cmp < 0) { t.matches = t; minRef = t; } else if (cmp == 0) { t.matches = minRef; } } return minRef; }
/** * Obtain the ObjectId for the current entry. * * <p>Every tree supplies an object id, even if the tree does not contain the current entry. In * the latter case {@link ObjectId#zeroId()} is supplied. * * <p>Applications should try to use {@link #idEqual(int, int)} when possible as it avoids * conversion overheads. * * @param out buffer to copy the object id into. * @param nth tree to obtain the object identifier from. * @see #idEqual(int, int) */ public void getObjectId(final MutableObjectId out, final int nth) { final AbstractTreeIterator t = trees[nth]; if (t.matches == currentHead) t.getEntryObjectId(out); else out.clear(); }
/** * Obtain the ObjectId for the current entry. * * <p>Using this method to compare ObjectId values between trees of this walker is very * inefficient. Applications should try to use {@link #idEqual(int, int)} or {@link * #getObjectId(MutableObjectId, int)} whenever possible. * * <p>Every tree supplies an object id, even if the tree does not contain the current entry. In * the latter case {@link ObjectId#zeroId()} is returned. * * @param nth tree to obtain the object identifier from. * @return object identifier for the current tree entry. * @see #getObjectId(MutableObjectId, int) * @see #idEqual(int, int) */ public ObjectId getObjectId(final int nth) { final AbstractTreeIterator t = trees[nth]; return t.matches == currentHead ? t.getEntryObjectId() : ObjectId.zeroId(); }