You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

AbstractTreeIterator.java 24KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773
  1. /*
  2. * Copyright (C) 2008-2009, Google Inc.
  3. * Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com>
  4. * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
  5. * and other copyright owners as documented in the project's IP log.
  6. *
  7. * This program and the accompanying materials are made available
  8. * under the terms of the Eclipse Distribution License v1.0 which
  9. * accompanies this distribution, is reproduced below, and is
  10. * available at http://www.eclipse.org/org/documents/edl-v10.php
  11. *
  12. * All rights reserved.
  13. *
  14. * Redistribution and use in source and binary forms, with or
  15. * without modification, are permitted provided that the following
  16. * conditions are met:
  17. *
  18. * - Redistributions of source code must retain the above copyright
  19. * notice, this list of conditions and the following disclaimer.
  20. *
  21. * - Redistributions in binary form must reproduce the above
  22. * copyright notice, this list of conditions and the following
  23. * disclaimer in the documentation and/or other materials provided
  24. * with the distribution.
  25. *
  26. * - Neither the name of the Eclipse Foundation, Inc. nor the
  27. * names of its contributors may be used to endorse or promote
  28. * products derived from this software without specific prior
  29. * written permission.
  30. *
  31. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
  32. * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  33. * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  34. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  35. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  36. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  37. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  38. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  39. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  40. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  41. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  42. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  43. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  44. */
  45. package org.eclipse.jgit.treewalk;
  46. import static java.nio.charset.StandardCharsets.UTF_8;
  47. import java.io.IOException;
  48. import java.nio.ByteBuffer;
  49. import java.nio.CharBuffer;
  50. import org.eclipse.jgit.attributes.AttributesHandler;
  51. import org.eclipse.jgit.attributes.AttributesNode;
  52. import org.eclipse.jgit.errors.CorruptObjectException;
  53. import org.eclipse.jgit.errors.IncorrectObjectTypeException;
  54. import org.eclipse.jgit.lib.Constants;
  55. import org.eclipse.jgit.lib.FileMode;
  56. import org.eclipse.jgit.lib.MutableObjectId;
  57. import org.eclipse.jgit.lib.ObjectId;
  58. import org.eclipse.jgit.lib.ObjectReader;
  59. import org.eclipse.jgit.util.Paths;
  60. /**
  61. * Walks a Git tree (directory) in Git sort order.
  62. * <p>
  63. * A new iterator instance should be positioned on the first entry, or at eof.
  64. * Data for the first entry (if not at eof) should be available immediately.
  65. * <p>
  66. * Implementors must walk a tree in the Git sort order, which has the following
  67. * odd sorting:
  68. * <ol>
  69. * <li>A.c</li>
  70. * <li>A/c</li>
  71. * <li>A0c</li>
  72. * </ol>
  73. * <p>
  74. * In the second item, <code>A</code> is the name of a subtree and
  75. * <code>c</code> is a file within that subtree. The other two items are files
  76. * in the root level tree.
  77. *
  78. * @see CanonicalTreeParser
  79. */
  80. public abstract class AbstractTreeIterator {
  81. /** Default size for the {@link #path} buffer. */
  82. protected static final int DEFAULT_PATH_SIZE = 128;
  83. /** A dummy object id buffer that matches the zero ObjectId. */
  84. protected static final byte[] zeroid = new byte[Constants.OBJECT_ID_LENGTH];
  85. /**
  86. * Iterator for the parent tree; null if we are the root iterator.
  87. * <p>
  88. * Used by {@link TreeWalk} and {@link AttributesHandler}
  89. *
  90. * @since 4.3
  91. */
  92. public final AbstractTreeIterator parent;
  93. /** The iterator this current entry is path equal to. */
  94. AbstractTreeIterator matches;
  95. /**
  96. * Parsed rules of .gitattributes file if it exists.
  97. *
  98. * @since 4.2
  99. */
  100. protected AttributesNode attributesNode;
  101. /**
  102. * Number of entries we moved forward to force a D/F conflict match.
  103. *
  104. * @see NameConflictTreeWalk
  105. */
  106. int matchShift;
  107. /**
  108. * Mode bits for the current entry.
  109. * <p>
  110. * A numerical value from FileMode is usually faster for an iterator to
  111. * obtain from its data source so this is the preferred representation.
  112. *
  113. * @see org.eclipse.jgit.lib.FileMode
  114. */
  115. protected int mode;
  116. /**
  117. * Path buffer for the current entry.
  118. * <p>
  119. * This buffer is pre-allocated at the start of walking and is shared from
  120. * parent iterators down into their subtree iterators. The sharing allows
  121. * the current entry to always be a full path from the root, while each
  122. * subtree only needs to populate the part that is under their control.
  123. */
  124. protected byte[] path;
  125. /**
  126. * Position within {@link #path} this iterator starts writing at.
  127. * <p>
  128. * This is the first offset in {@link #path} that this iterator must
  129. * populate during {@link #next}. At the root level (when {@link #parent}
  130. * is null) this is 0. For a subtree iterator the index before this position
  131. * should have the value '/'.
  132. */
  133. protected final int pathOffset;
  134. /**
  135. * Total length of the current entry's complete path from the root.
  136. * <p>
  137. * This is the number of bytes within {@link #path} that pertain to the
  138. * current entry. Values at this index through the end of the array are
  139. * garbage and may be randomly populated from prior entries.
  140. */
  141. protected int pathLen;
  142. /**
  143. * Create a new iterator with no parent.
  144. */
  145. protected AbstractTreeIterator() {
  146. parent = null;
  147. path = new byte[DEFAULT_PATH_SIZE];
  148. pathOffset = 0;
  149. }
  150. /**
  151. * Create a new iterator with no parent and a prefix.
  152. * <p>
  153. * The prefix path supplied is inserted in front of all paths generated by
  154. * this iterator. It is intended to be used when an iterator is being
  155. * created for a subsection of an overall repository and needs to be
  156. * combined with other iterators that are created to run over the entire
  157. * repository namespace.
  158. *
  159. * @param prefix
  160. * position of this iterator in the repository tree. The value
  161. * may be null or the empty string to indicate the prefix is the
  162. * root of the repository. A trailing slash ('/') is
  163. * automatically appended if the prefix does not end in '/'.
  164. */
  165. protected AbstractTreeIterator(String prefix) {
  166. parent = null;
  167. if (prefix != null && prefix.length() > 0) {
  168. final ByteBuffer b;
  169. b = UTF_8.encode(CharBuffer.wrap(prefix));
  170. pathLen = b.limit();
  171. path = new byte[Math.max(DEFAULT_PATH_SIZE, pathLen + 1)];
  172. b.get(path, 0, pathLen);
  173. if (path[pathLen - 1] != '/')
  174. path[pathLen++] = '/';
  175. pathOffset = pathLen;
  176. } else {
  177. path = new byte[DEFAULT_PATH_SIZE];
  178. pathOffset = 0;
  179. }
  180. }
  181. /**
  182. * Create a new iterator with no parent and a prefix.
  183. * <p>
  184. * The prefix path supplied is inserted in front of all paths generated by
  185. * this iterator. It is intended to be used when an iterator is being
  186. * created for a subsection of an overall repository and needs to be
  187. * combined with other iterators that are created to run over the entire
  188. * repository namespace.
  189. *
  190. * @param prefix
  191. * position of this iterator in the repository tree. The value
  192. * may be null or the empty array to indicate the prefix is the
  193. * root of the repository. A trailing slash ('/') is
  194. * automatically appended if the prefix does not end in '/'.
  195. */
  196. protected AbstractTreeIterator(byte[] prefix) {
  197. parent = null;
  198. if (prefix != null && prefix.length > 0) {
  199. pathLen = prefix.length;
  200. path = new byte[Math.max(DEFAULT_PATH_SIZE, pathLen + 1)];
  201. System.arraycopy(prefix, 0, path, 0, pathLen);
  202. if (path[pathLen - 1] != '/')
  203. path[pathLen++] = '/';
  204. pathOffset = pathLen;
  205. } else {
  206. path = new byte[DEFAULT_PATH_SIZE];
  207. pathOffset = 0;
  208. }
  209. }
  210. /**
  211. * Create an iterator for a subtree of an existing iterator.
  212. *
  213. * @param p
  214. * parent tree iterator.
  215. */
  216. protected AbstractTreeIterator(AbstractTreeIterator p) {
  217. parent = p;
  218. path = p.path;
  219. pathOffset = p.pathLen + 1;
  220. try {
  221. path[pathOffset - 1] = '/';
  222. } catch (ArrayIndexOutOfBoundsException e) {
  223. growPath(p.pathLen);
  224. path[pathOffset - 1] = '/';
  225. }
  226. }
  227. /**
  228. * Create an iterator for a subtree of an existing iterator.
  229. * <p>
  230. * The caller is responsible for setting up the path of the child iterator.
  231. *
  232. * @param p
  233. * parent tree iterator.
  234. * @param childPath
  235. * path array to be used by the child iterator. This path must
  236. * contain the path from the top of the walk to the first child
  237. * and must end with a '/'.
  238. * @param childPathOffset
  239. * position within <code>childPath</code> where the child can
  240. * insert its data. The value at
  241. * <code>childPath[childPathOffset-1]</code> must be '/'.
  242. */
  243. protected AbstractTreeIterator(final AbstractTreeIterator p,
  244. final byte[] childPath, final int childPathOffset) {
  245. parent = p;
  246. path = childPath;
  247. pathOffset = childPathOffset;
  248. }
  249. /**
  250. * Grow the path buffer larger.
  251. *
  252. * @param len
  253. * number of live bytes in the path buffer. This many bytes will
  254. * be moved into the larger buffer.
  255. */
  256. protected void growPath(int len) {
  257. setPathCapacity(path.length << 1, len);
  258. }
  259. /**
  260. * Ensure that path is capable to hold at least {@code capacity} bytes
  261. *
  262. * @param capacity
  263. * the amount of bytes to hold
  264. * @param len
  265. * the amount of live bytes in path buffer
  266. */
  267. protected void ensurePathCapacity(int capacity, int len) {
  268. if (path.length >= capacity)
  269. return;
  270. final byte[] o = path;
  271. int current = o.length;
  272. int newCapacity = current;
  273. while (newCapacity < capacity && newCapacity > 0)
  274. newCapacity <<= 1;
  275. setPathCapacity(newCapacity, len);
  276. }
  277. /**
  278. * Set path buffer capacity to the specified size
  279. *
  280. * @param capacity
  281. * the new size
  282. * @param len
  283. * the amount of bytes to copy
  284. */
  285. private void setPathCapacity(int capacity, int len) {
  286. final byte[] o = path;
  287. final byte[] n = new byte[capacity];
  288. System.arraycopy(o, 0, n, 0, len);
  289. for (AbstractTreeIterator p = this; p != null && p.path == o; p = p.parent)
  290. p.path = n;
  291. }
  292. /**
  293. * Compare the path of this current entry to another iterator's entry.
  294. *
  295. * @param p
  296. * the other iterator to compare the path against.
  297. * @return -1 if this entry sorts first; 0 if the entries are equal; 1 if
  298. * p's entry sorts first.
  299. */
  300. public int pathCompare(AbstractTreeIterator p) {
  301. return pathCompare(p, p.mode);
  302. }
  303. int pathCompare(AbstractTreeIterator p, int pMode) {
  304. // Its common when we are a subtree for both parents to match;
  305. // when this happens everything in path[0..cPos] is known to
  306. // be equal and does not require evaluation again.
  307. //
  308. int cPos = alreadyMatch(this, p);
  309. return pathCompare(p.path, cPos, p.pathLen, pMode, cPos);
  310. }
  311. /**
  312. * Seek the iterator on a file, if present.
  313. *
  314. * @param name
  315. * file name to find (will not find a directory).
  316. * @return true if the file exists in this tree; false otherwise.
  317. * @throws org.eclipse.jgit.errors.CorruptObjectException
  318. * tree is invalid.
  319. * @since 4.2
  320. */
  321. public boolean findFile(String name) throws CorruptObjectException {
  322. return findFile(Constants.encode(name));
  323. }
  324. /**
  325. * Seek the iterator on a file, if present.
  326. *
  327. * @param name
  328. * file name to find (will not find a directory).
  329. * @return true if the file exists in this tree; false otherwise.
  330. * @throws org.eclipse.jgit.errors.CorruptObjectException
  331. * tree is invalid.
  332. * @since 4.2
  333. */
  334. public boolean findFile(byte[] name) throws CorruptObjectException {
  335. for (; !eof(); next(1)) {
  336. int cmp = pathCompare(name, 0, name.length, 0, pathOffset);
  337. if (cmp == 0) {
  338. return true;
  339. } else if (cmp > 0) {
  340. return false;
  341. }
  342. }
  343. return false;
  344. }
  345. /**
  346. * Compare the path of this current entry to a raw buffer.
  347. *
  348. * @param buf
  349. * the raw path buffer.
  350. * @param pos
  351. * position to start reading the raw buffer.
  352. * @param end
  353. * one past the end of the raw buffer (length is end - pos).
  354. * @param pathMode
  355. * the mode of the path.
  356. * @return -1 if this entry sorts first; 0 if the entries are equal; 1 if
  357. * p's entry sorts first.
  358. */
  359. public int pathCompare(byte[] buf, int pos, int end, int pathMode) {
  360. return pathCompare(buf, pos, end, pathMode, 0);
  361. }
  362. private int pathCompare(byte[] b, int bPos, int bEnd, int bMode, int aPos) {
  363. return Paths.compare(
  364. path, aPos, pathLen, mode,
  365. b, bPos, bEnd, bMode);
  366. }
  367. private static int alreadyMatch(AbstractTreeIterator a,
  368. AbstractTreeIterator b) {
  369. for (;;) {
  370. final AbstractTreeIterator ap = a.parent;
  371. final AbstractTreeIterator bp = b.parent;
  372. if (ap == null || bp == null)
  373. return 0;
  374. if (ap.matches == bp.matches)
  375. return a.pathOffset;
  376. a = ap;
  377. b = bp;
  378. }
  379. }
  380. /**
  381. * Check if the current entry of both iterators has the same id.
  382. * <p>
  383. * This method is faster than {@link #getEntryObjectId()} as it does not
  384. * require copying the bytes out of the buffers. A direct {@link #idBuffer}
  385. * compare operation is performed.
  386. *
  387. * @param otherIterator
  388. * the other iterator to test against.
  389. * @return true if both iterators have the same object id; false otherwise.
  390. */
  391. public boolean idEqual(AbstractTreeIterator otherIterator) {
  392. return ObjectId.equals(idBuffer(), idOffset(),
  393. otherIterator.idBuffer(), otherIterator.idOffset());
  394. }
  395. /**
  396. * Whether the entry has a valid ObjectId.
  397. *
  398. * @return {@code true} if the entry has a valid ObjectId.
  399. */
  400. public abstract boolean hasId();
  401. /**
  402. * Get the object id of the current entry.
  403. *
  404. * @return an object id for the current entry.
  405. */
  406. public ObjectId getEntryObjectId() {
  407. return ObjectId.fromRaw(idBuffer(), idOffset());
  408. }
  409. /**
  410. * Obtain the ObjectId for the current entry.
  411. *
  412. * @param out
  413. * buffer to copy the object id into.
  414. */
  415. public void getEntryObjectId(MutableObjectId out) {
  416. out.fromRaw(idBuffer(), idOffset());
  417. }
  418. /**
  419. * Get the file mode of the current entry.
  420. *
  421. * @return the file mode of the current entry.
  422. */
  423. public FileMode getEntryFileMode() {
  424. return FileMode.fromBits(mode);
  425. }
  426. /**
  427. * Get the file mode of the current entry as bits.
  428. *
  429. * @return the file mode of the current entry as bits.
  430. */
  431. public int getEntryRawMode() {
  432. return mode;
  433. }
  434. /**
  435. * Get path of the current entry, as a string.
  436. *
  437. * @return path of the current entry, as a string.
  438. */
  439. public String getEntryPathString() {
  440. return TreeWalk.pathOf(this);
  441. }
  442. /**
  443. * Get the current entry path buffer.
  444. * <p>
  445. * Note that the returned byte[] has to be used together with
  446. * {@link #getEntryPathLength()} (only use bytes up to this length).
  447. *
  448. * @return the internal buffer holding the current path.
  449. */
  450. public byte[] getEntryPathBuffer() {
  451. return path;
  452. }
  453. /**
  454. * Get length of the path in {@link #getEntryPathBuffer()}.
  455. *
  456. * @return length of the path in {@link #getEntryPathBuffer()}.
  457. */
  458. public int getEntryPathLength() {
  459. return pathLen;
  460. }
  461. /**
  462. * Get the current entry's path hash code.
  463. * <p>
  464. * This method computes a hash code on the fly for this path, the hash is
  465. * suitable to cluster objects that may have similar paths together.
  466. *
  467. * @return path hash code; any integer may be returned.
  468. */
  469. public int getEntryPathHashCode() {
  470. int hash = 0;
  471. for (int i = Math.max(0, pathLen - 16); i < pathLen; i++) {
  472. byte c = path[i];
  473. if (c != ' ')
  474. hash = (hash >>> 2) + (c << 24);
  475. }
  476. return hash;
  477. }
  478. /**
  479. * Get the byte array buffer object IDs must be copied out of.
  480. * <p>
  481. * The id buffer contains the bytes necessary to construct an ObjectId for
  482. * the current entry of this iterator. The buffer can be the same buffer for
  483. * all entries, or it can be a unique buffer per-entry. Implementations are
  484. * encouraged to expose their private buffer whenever possible to reduce
  485. * garbage generation and copying costs.
  486. *
  487. * @return byte array the implementation stores object IDs within.
  488. * @see #getEntryObjectId()
  489. */
  490. public abstract byte[] idBuffer();
  491. /**
  492. * Get the position within {@link #idBuffer()} of this entry's ObjectId.
  493. *
  494. * @return offset into the array returned by {@link #idBuffer()} where the
  495. * ObjectId must be copied out of.
  496. */
  497. public abstract int idOffset();
  498. /**
  499. * Create a new iterator for the current entry's subtree.
  500. * <p>
  501. * The parent reference of the iterator must be <code>this</code>,
  502. * otherwise the caller would not be able to exit out of the subtree
  503. * iterator correctly and return to continue walking <code>this</code>.
  504. *
  505. * @param reader
  506. * reader to load the tree data from.
  507. * @return a new parser that walks over the current subtree.
  508. * @throws org.eclipse.jgit.errors.IncorrectObjectTypeException
  509. * the current entry is not actually a tree and cannot be parsed
  510. * as though it were a tree.
  511. * @throws java.io.IOException
  512. * a loose object or pack file could not be read.
  513. */
  514. public abstract AbstractTreeIterator createSubtreeIterator(
  515. ObjectReader reader) throws IncorrectObjectTypeException,
  516. IOException;
  517. /**
  518. * Create a new iterator as though the current entry were a subtree.
  519. *
  520. * @return a new empty tree iterator.
  521. */
  522. public EmptyTreeIterator createEmptyTreeIterator() {
  523. return new EmptyTreeIterator(this);
  524. }
  525. /**
  526. * Create a new iterator for the current entry's subtree.
  527. * <p>
  528. * The parent reference of the iterator must be <code>this</code>, otherwise
  529. * the caller would not be able to exit out of the subtree iterator
  530. * correctly and return to continue walking <code>this</code>.
  531. *
  532. * @param reader
  533. * reader to load the tree data from.
  534. * @param idBuffer
  535. * temporary ObjectId buffer for use by this method.
  536. * @return a new parser that walks over the current subtree.
  537. * @throws org.eclipse.jgit.errors.IncorrectObjectTypeException
  538. * the current entry is not actually a tree and cannot be parsed
  539. * as though it were a tree.
  540. * @throws java.io.IOException
  541. * a loose object or pack file could not be read.
  542. */
  543. public AbstractTreeIterator createSubtreeIterator(
  544. final ObjectReader reader, final MutableObjectId idBuffer)
  545. throws IncorrectObjectTypeException, IOException {
  546. return createSubtreeIterator(reader);
  547. }
  548. /**
  549. * Position this iterator on the first entry.
  550. *
  551. * The default implementation of this method uses {@code back(1)} until
  552. * {@code first()} is true. This is most likely not the most efficient
  553. * method of repositioning the iterator to its first entry, so subclasses
  554. * are strongly encouraged to override the method.
  555. *
  556. * @throws org.eclipse.jgit.errors.CorruptObjectException
  557. * the tree is invalid.
  558. */
  559. public void reset() throws CorruptObjectException {
  560. while (!first())
  561. back(1);
  562. }
  563. /**
  564. * Is this tree iterator positioned on its first entry?
  565. * <p>
  566. * An iterator is positioned on the first entry if <code>back(1)</code>
  567. * would be an invalid request as there is no entry before the current one.
  568. * <p>
  569. * An empty iterator (one with no entries) will be
  570. * <code>first() &amp;&amp; eof()</code>.
  571. *
  572. * @return true if the iterator is positioned on the first entry.
  573. */
  574. public abstract boolean first();
  575. /**
  576. * Is this tree iterator at its EOF point (no more entries)?
  577. * <p>
  578. * An iterator is at EOF if there is no current entry.
  579. *
  580. * @return true if we have walked all entries and have none left.
  581. */
  582. public abstract boolean eof();
  583. /**
  584. * Move to next entry, populating this iterator with the entry data.
  585. * <p>
  586. * The delta indicates how many moves forward should occur. The most common
  587. * delta is 1 to move to the next entry.
  588. * <p>
  589. * Implementations must populate the following members:
  590. * <ul>
  591. * <li>{@link #mode}</li>
  592. * <li>{@link #path} (from {@link #pathOffset} to {@link #pathLen})</li>
  593. * <li>{@link #pathLen}</li>
  594. * </ul>
  595. * as well as any implementation dependent information necessary to
  596. * accurately return data from {@link #idBuffer()} and {@link #idOffset()}
  597. * when demanded.
  598. *
  599. * @param delta
  600. * number of entries to move the iterator by. Must be a positive,
  601. * non-zero integer.
  602. * @throws org.eclipse.jgit.errors.CorruptObjectException
  603. * the tree is invalid.
  604. */
  605. public abstract void next(int delta) throws CorruptObjectException;
  606. /**
  607. * Move to prior entry, populating this iterator with the entry data.
  608. * <p>
  609. * The delta indicates how many moves backward should occur.The most common
  610. * delta is 1 to move to the prior entry.
  611. * <p>
  612. * Implementations must populate the following members:
  613. * <ul>
  614. * <li>{@link #mode}</li>
  615. * <li>{@link #path} (from {@link #pathOffset} to {@link #pathLen})</li>
  616. * <li>{@link #pathLen}</li>
  617. * </ul>
  618. * as well as any implementation dependent information necessary to
  619. * accurately return data from {@link #idBuffer()} and {@link #idOffset()}
  620. * when demanded.
  621. *
  622. * @param delta
  623. * number of entries to move the iterator by. Must be a positive,
  624. * non-zero integer.
  625. * @throws org.eclipse.jgit.errors.CorruptObjectException
  626. * the tree is invalid.
  627. */
  628. public abstract void back(int delta) throws CorruptObjectException;
  629. /**
  630. * Advance to the next tree entry, populating this iterator with its data.
  631. * <p>
  632. * This method behaves like <code>seek(1)</code> but is called by
  633. * {@link org.eclipse.jgit.treewalk.TreeWalk} only if a
  634. * {@link org.eclipse.jgit.treewalk.filter.TreeFilter} was used and ruled
  635. * out the current entry from the results. In such cases this tree iterator
  636. * may perform special behavior.
  637. *
  638. * @throws org.eclipse.jgit.errors.CorruptObjectException
  639. * the tree is invalid.
  640. */
  641. public void skip() throws CorruptObjectException {
  642. next(1);
  643. }
  644. /**
  645. * Indicates to the iterator that no more entries will be read.
  646. * <p>
  647. * This is only invoked by TreeWalk when the iteration is aborted early due
  648. * to a {@link org.eclipse.jgit.errors.StopWalkException} being thrown from
  649. * within a TreeFilter.
  650. */
  651. public void stopWalk() {
  652. // Do nothing by default. Most iterators do not care.
  653. }
  654. /**
  655. * Whether the iterator implements {@link #stopWalk()}.
  656. *
  657. * @return {@code true} if the iterator implements {@link #stopWalk()}.
  658. * @since 4.2
  659. */
  660. protected boolean needsStopWalk() {
  661. return false;
  662. }
  663. /**
  664. * Get the length of the name component of the path for the current entry.
  665. *
  666. * @return the length of the name component of the path for the current
  667. * entry.
  668. */
  669. public int getNameLength() {
  670. return pathLen - pathOffset;
  671. }
  672. /**
  673. * JGit internal API for use by
  674. * {@link org.eclipse.jgit.dircache.DirCacheCheckout}
  675. *
  676. * @return start of name component part within {@link #getEntryPathBuffer()}
  677. * @since 2.0
  678. */
  679. public int getNameOffset() {
  680. return pathOffset;
  681. }
  682. /**
  683. * Get the name component of the current entry path into the provided
  684. * buffer.
  685. *
  686. * @param buffer
  687. * the buffer to get the name into, it is assumed that buffer can
  688. * hold the name
  689. * @param offset
  690. * the offset of the name in the buffer
  691. * @see #getNameLength()
  692. */
  693. public void getName(byte[] buffer, int offset) {
  694. System.arraycopy(path, pathOffset, buffer, offset, pathLen - pathOffset);
  695. }
  696. /** {@inheritDoc} */
  697. @SuppressWarnings("nls")
  698. @Override
  699. public String toString() {
  700. return getClass().getSimpleName() + "[" + getEntryPathString() + "]"; //$NON-NLS-1$
  701. }
  702. /**
  703. * Whether or not this Iterator is iterating through the working tree.
  704. *
  705. * @return whether or not this Iterator is iterating through the working
  706. * tree
  707. * @since 4.3
  708. */
  709. public boolean isWorkTree() {
  710. return false;
  711. }
  712. }