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