aboutsummaryrefslogtreecommitdiffstats
path: root/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/AbstractTreeIterator.java
diff options
context:
space:
mode:
Diffstat (limited to 'org.eclipse.jgit/src/org/eclipse/jgit/treewalk/AbstractTreeIterator.java')
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/treewalk/AbstractTreeIterator.java236
1 files changed, 143 insertions, 93 deletions
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/AbstractTreeIterator.java b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/AbstractTreeIterator.java
index 41e593eaa2..65b18086b4 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/AbstractTreeIterator.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/AbstractTreeIterator.java
@@ -1,55 +1,25 @@
/*
* Copyright (C) 2008-2009, Google Inc.
* Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com>
- * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
- * and other copyright owners as documented in the project's IP log.
+ * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org> and others
*
- * This program and the accompanying materials are made available
- * under the terms of the Eclipse Distribution License v1.0 which
- * accompanies this distribution, is reproduced below, and is
- * available at http://www.eclipse.org/org/documents/edl-v10.php
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * https://www.eclipse.org/org/documents/edl-v10.php.
*
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- *
- * - Neither the name of the Eclipse Foundation, Inc. nor the
- * names of its contributors may be used to endorse or promote
- * products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * SPDX-License-Identifier: BSD-3-Clause
*/
package org.eclipse.jgit.treewalk;
+import static java.nio.charset.StandardCharsets.UTF_8;
+
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
-import org.eclipse.jgit.dircache.DirCacheCheckout;
+import org.eclipse.jgit.attributes.AttributesHandler;
+import org.eclipse.jgit.attributes.AttributesNode;
import org.eclipse.jgit.errors.CorruptObjectException;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.lib.Constants;
@@ -57,7 +27,7 @@ import org.eclipse.jgit.lib.FileMode;
import org.eclipse.jgit.lib.MutableObjectId;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectReader;
-import org.eclipse.jgit.treewalk.filter.TreeFilter;
+import org.eclipse.jgit.util.Paths;
/**
* Walks a Git tree (directory) in Git sort order.
@@ -86,13 +56,26 @@ public abstract class AbstractTreeIterator {
/** A dummy object id buffer that matches the zero ObjectId. */
protected static final byte[] zeroid = new byte[Constants.OBJECT_ID_LENGTH];
- /** Iterator for the parent tree; null if we are the root iterator. */
- final AbstractTreeIterator parent;
+ /**
+ * Iterator for the parent tree; null if we are the root iterator.
+ * <p>
+ * Used by {@link TreeWalk} and {@link AttributesHandler}
+ *
+ * @since 4.3
+ */
+ public final AbstractTreeIterator parent;
/** The iterator this current entry is path equal to. */
AbstractTreeIterator matches;
/**
+ * Parsed rules of .gitattributes file if it exists.
+ *
+ * @since 4.2
+ */
+ protected AttributesNode attributesNode;
+
+ /**
* Number of entries we moved forward to force a D/F conflict match.
*
* @see NameConflictTreeWalk
@@ -138,7 +121,9 @@ public abstract class AbstractTreeIterator {
*/
protected int pathLen;
- /** Create a new iterator with no parent. */
+ /**
+ * Create a new iterator with no parent.
+ */
protected AbstractTreeIterator() {
parent = null;
path = new byte[DEFAULT_PATH_SIZE];
@@ -160,13 +145,13 @@ public abstract class AbstractTreeIterator {
* root of the repository. A trailing slash ('/') is
* automatically appended if the prefix does not end in '/'.
*/
- protected AbstractTreeIterator(final String prefix) {
+ protected AbstractTreeIterator(String prefix) {
parent = null;
if (prefix != null && prefix.length() > 0) {
final ByteBuffer b;
- b = Constants.CHARSET.encode(CharBuffer.wrap(prefix));
+ b = UTF_8.encode(CharBuffer.wrap(prefix));
pathLen = b.limit();
path = new byte[Math.max(DEFAULT_PATH_SIZE, pathLen + 1)];
b.get(path, 0, pathLen);
@@ -194,7 +179,7 @@ public abstract class AbstractTreeIterator {
* root of the repository. A trailing slash ('/') is
* automatically appended if the prefix does not end in '/'.
*/
- protected AbstractTreeIterator(final byte[] prefix) {
+ protected AbstractTreeIterator(byte[] prefix) {
parent = null;
if (prefix != null && prefix.length > 0) {
@@ -216,17 +201,15 @@ public abstract class AbstractTreeIterator {
* @param p
* parent tree iterator.
*/
- protected AbstractTreeIterator(final AbstractTreeIterator p) {
+ protected AbstractTreeIterator(AbstractTreeIterator p) {
parent = p;
path = p.path;
pathOffset = p.pathLen + 1;
- try {
- path[pathOffset - 1] = '/';
- } catch (ArrayIndexOutOfBoundsException e) {
+ if (pathOffset > path.length) {
growPath(p.pathLen);
- path[pathOffset - 1] = '/';
}
+ path[pathOffset - 1] = '/';
}
/**
@@ -259,7 +242,7 @@ public abstract class AbstractTreeIterator {
* number of live bytes in the path buffer. This many bytes will
* be moved into the larger buffer.
*/
- protected void growPath(final int len) {
+ protected void growPath(int len) {
setPathCapacity(path.length << 1, len);
}
@@ -271,7 +254,7 @@ public abstract class AbstractTreeIterator {
* @param len
* the amount of live bytes in path buffer
*/
- protected void ensurePathCapacity(final int capacity, final int len) {
+ protected void ensurePathCapacity(int capacity, int len) {
if (path.length >= capacity)
return;
final byte[] o = path;
@@ -306,11 +289,11 @@ public abstract class AbstractTreeIterator {
* @return -1 if this entry sorts first; 0 if the entries are equal; 1 if
* p's entry sorts first.
*/
- public int pathCompare(final AbstractTreeIterator p) {
+ public int pathCompare(AbstractTreeIterator p) {
return pathCompare(p, p.mode);
}
- int pathCompare(final AbstractTreeIterator p, final int pMode) {
+ int pathCompare(AbstractTreeIterator p, int pMode) {
// Its common when we are a subtree for both parents to match;
// when this happens everything in path[0..cPos] is known to
// be equal and does not require evaluation again.
@@ -320,6 +303,42 @@ public abstract class AbstractTreeIterator {
}
/**
+ * Seek the iterator on a file, if present.
+ *
+ * @param name
+ * file name to find (will not find a directory).
+ * @return true if the file exists in this tree; false otherwise.
+ * @throws org.eclipse.jgit.errors.CorruptObjectException
+ * tree is invalid.
+ * @since 4.2
+ */
+ public boolean findFile(String name) throws CorruptObjectException {
+ return findFile(Constants.encode(name));
+ }
+
+ /**
+ * Seek the iterator on a file, if present.
+ *
+ * @param name
+ * file name to find (will not find a directory).
+ * @return true if the file exists in this tree; false otherwise.
+ * @throws org.eclipse.jgit.errors.CorruptObjectException
+ * tree is invalid.
+ * @since 4.2
+ */
+ public boolean findFile(byte[] name) throws CorruptObjectException {
+ for (; !eof(); next(1)) {
+ int cmp = pathCompare(name, 0, name.length, 0, pathOffset);
+ if (cmp == 0) {
+ return true;
+ } else if (cmp > 0) {
+ return false;
+ }
+ }
+ return false;
+ }
+
+ /**
* Compare the path of this current entry to a raw buffer.
*
* @param buf
@@ -338,20 +357,9 @@ public abstract class AbstractTreeIterator {
}
private int pathCompare(byte[] b, int bPos, int bEnd, int bMode, int aPos) {
- final byte[] a = path;
- final int aEnd = pathLen;
-
- for (; aPos < aEnd && bPos < bEnd; aPos++, bPos++) {
- final int cmp = (a[aPos] & 0xff) - (b[bPos] & 0xff);
- if (cmp != 0)
- return cmp;
- }
-
- if (aPos < aEnd)
- return (a[aPos] & 0xff) - lastPathChar(bMode);
- if (bPos < bEnd)
- return lastPathChar(mode) - (b[bPos] & 0xff);
- return lastPathChar(mode) - lastPathChar(bMode);
+ return Paths.compare(
+ path, aPos, pathLen, mode,
+ b, bPos, bEnd, bMode);
}
private static int alreadyMatch(AbstractTreeIterator a,
@@ -368,10 +376,6 @@ public abstract class AbstractTreeIterator {
}
}
- private static int lastPathChar(final int mode) {
- return FileMode.TREE.equals(mode) ? '/' : '\0';
- }
-
/**
* Check if the current entry of both iterators has the same id.
* <p>
@@ -383,12 +387,16 @@ public abstract class AbstractTreeIterator {
* the other iterator to test against.
* @return true if both iterators have the same object id; false otherwise.
*/
- public boolean idEqual(final AbstractTreeIterator otherIterator) {
+ public boolean idEqual(AbstractTreeIterator otherIterator) {
return ObjectId.equals(idBuffer(), idOffset(),
otherIterator.idBuffer(), otherIterator.idOffset());
}
- /** @return true if the entry has a valid ObjectId. */
+ /**
+ * Whether the entry has a valid ObjectId.
+ *
+ * @return {@code true} if the entry has a valid ObjectId.
+ */
public abstract boolean hasId();
/**
@@ -406,21 +414,33 @@ public abstract class AbstractTreeIterator {
* @param out
* buffer to copy the object id into.
*/
- public void getEntryObjectId(final MutableObjectId out) {
+ public void getEntryObjectId(MutableObjectId out) {
out.fromRaw(idBuffer(), idOffset());
}
- /** @return the file mode of the current entry. */
+ /**
+ * Get the file mode of the current entry.
+ *
+ * @return the file mode of the current entry.
+ */
public FileMode getEntryFileMode() {
return FileMode.fromBits(mode);
}
- /** @return the file mode of the current entry as bits */
+ /**
+ * Get the file mode of the current entry as bits.
+ *
+ * @return the file mode of the current entry as bits.
+ */
public int getEntryRawMode() {
return mode;
}
- /** @return path of the current entry, as a string. */
+ /**
+ * Get path of the current entry, as a string.
+ *
+ * @return path of the current entry, as a string.
+ */
public String getEntryPathString() {
return TreeWalk.pathOf(this);
}
@@ -437,7 +457,11 @@ public abstract class AbstractTreeIterator {
return path;
}
- /** @return length of the path in {@link #getEntryPathBuffer()}. */
+ /**
+ * Get length of the path in {@link #getEntryPathBuffer()}.
+ *
+ * @return length of the path in {@link #getEntryPathBuffer()}.
+ */
public int getEntryPathLength() {
return pathLen;
}
@@ -492,10 +516,10 @@ public abstract class AbstractTreeIterator {
* @param reader
* reader to load the tree data from.
* @return a new parser that walks over the current subtree.
- * @throws IncorrectObjectTypeException
+ * @throws org.eclipse.jgit.errors.IncorrectObjectTypeException
* the current entry is not actually a tree and cannot be parsed
* as though it were a tree.
- * @throws IOException
+ * @throws java.io.IOException
* a loose object or pack file could not be read.
*/
public abstract AbstractTreeIterator createSubtreeIterator(
@@ -523,10 +547,10 @@ public abstract class AbstractTreeIterator {
* @param idBuffer
* temporary ObjectId buffer for use by this method.
* @return a new parser that walks over the current subtree.
- * @throws IncorrectObjectTypeException
+ * @throws org.eclipse.jgit.errors.IncorrectObjectTypeException
* the current entry is not actually a tree and cannot be parsed
* as though it were a tree.
- * @throws IOException
+ * @throws java.io.IOException
* a loose object or pack file could not be read.
*/
public AbstractTreeIterator createSubtreeIterator(
@@ -543,7 +567,7 @@ public abstract class AbstractTreeIterator {
* method of repositioning the iterator to its first entry, so subclasses
* are strongly encouraged to override the method.
*
- * @throws CorruptObjectException
+ * @throws org.eclipse.jgit.errors.CorruptObjectException
* the tree is invalid.
*/
public void reset() throws CorruptObjectException {
@@ -592,7 +616,7 @@ public abstract class AbstractTreeIterator {
* @param delta
* number of entries to move the iterator by. Must be a positive,
* non-zero integer.
- * @throws CorruptObjectException
+ * @throws org.eclipse.jgit.errors.CorruptObjectException
* the tree is invalid.
*/
public abstract void next(int delta) throws CorruptObjectException;
@@ -616,7 +640,7 @@ public abstract class AbstractTreeIterator {
* @param delta
* number of entries to move the iterator by. Must be a positive,
* non-zero integer.
- * @throws CorruptObjectException
+ * @throws org.eclipse.jgit.errors.CorruptObjectException
* the tree is invalid.
*/
public abstract void back(int delta) throws CorruptObjectException;
@@ -625,11 +649,12 @@ public abstract class AbstractTreeIterator {
* Advance to the next tree entry, populating this iterator with its data.
* <p>
* This method behaves like <code>seek(1)</code> but is called by
- * {@link TreeWalk} only if a {@link TreeFilter} was used and ruled out the
- * current entry from the results. In such cases this tree iterator may
- * perform special behavior.
+ * {@link org.eclipse.jgit.treewalk.TreeWalk} only if a
+ * {@link org.eclipse.jgit.treewalk.filter.TreeFilter} was used and ruled
+ * out the current entry from the results. In such cases this tree iterator
+ * may perform special behavior.
*
- * @throws CorruptObjectException
+ * @throws org.eclipse.jgit.errors.CorruptObjectException
* the tree is invalid.
*/
public void skip() throws CorruptObjectException {
@@ -648,14 +673,28 @@ public abstract class AbstractTreeIterator {
}
/**
- * @return the length of the name component of the path for the current entry
+ * Whether the iterator implements {@link #stopWalk()}.
+ *
+ * @return {@code true} if the iterator implements {@link #stopWalk()}.
+ * @since 4.2
+ */
+ protected boolean needsStopWalk() {
+ return false;
+ }
+
+ /**
+ * Get the length of the name component of the path for the current entry.
+ *
+ * @return the length of the name component of the path for the current
+ * entry.
*/
public int getNameLength() {
return pathLen - pathOffset;
}
/**
- * JGit internal API for use by {@link DirCacheCheckout}
+ * JGit internal API for use by
+ * {@link org.eclipse.jgit.dircache.DirCacheCheckout}
*
* @return start of name component part within {@link #getEntryPathBuffer()}
* @since 2.0
@@ -684,4 +723,15 @@ public abstract class AbstractTreeIterator {
public String toString() {
return getClass().getSimpleName() + "[" + getEntryPathString() + "]"; //$NON-NLS-1$
}
+
+ /**
+ * Whether or not this Iterator is iterating through the working tree.
+ *
+ * @return whether or not this Iterator is iterating through the working
+ * tree
+ * @since 4.3
+ */
+ public boolean isWorkTree() {
+ return false;
+ }
}