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