/*
 * Copyright (C) 2008, Google Inc. and others
 *
 * 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.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

package org.eclipse.jgit.treewalk;

import java.io.IOException;

import org.eclipse.jgit.annotations.Nullable;
import org.eclipse.jgit.errors.CorruptObjectException;
import org.eclipse.jgit.lib.FileMode;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.Repository;

/**
 * Specialized TreeWalk to detect directory-file (D/F) name conflicts.
 * <p>
 * Due to the way a Git tree is organized the standard
 * {@link org.eclipse.jgit.treewalk.TreeWalk} won't easily find a D/F conflict
 * when merging two or more trees together. In the standard TreeWalk the file
 * will be returned first, and then much later the directory will be returned.
 * This makes it impossible for the application to efficiently detect and handle
 * the conflict.
 * <p>
 * Using this walk implementation causes the directory to report earlier than
 * usual, at the same time as the non-directory entry. This permits the
 * application to handle the D/F conflict in a single step. The directory is
 * returned only once, so it does not get returned later in the iteration.
 * <p>
 * When a D/F conflict is detected
 * {@link org.eclipse.jgit.treewalk.TreeWalk#isSubtree()} will return true and
 * {@link org.eclipse.jgit.treewalk.TreeWalk#enterSubtree()} will recurse into
 * the subtree, no matter which iterator originally supplied the subtree.
 * <p>
 * Because conflicted directories report early, using this walk implementation
 * to populate a {@link org.eclipse.jgit.dircache.DirCacheBuilder} may cause the
 * automatic resorting to run and fix the entry ordering.
 * <p>
 * This walk implementation requires more CPU to implement a look-ahead and a
 * look-behind to merge a D/F pair together, or to skip a previously reported
 * directory. In typical Git repositories the look-ahead cost is 0 and the
 * look-behind doesn't trigger, as users tend not to create trees which contain
 * both "foo" as a directory and "foo.c" as a file.
 * <p>
 * In the worst-case however several thousand look-ahead steps per walk step may
 * be necessary, making the overhead quite significant. Since this worst-case
 * should never happen this walk implementation has made the time/space tradeoff
 * in favor of more-time/less-space, as that better suits the typical case.
 */
public class NameConflictTreeWalk extends TreeWalk {
	private static final int TREE_MODE = FileMode.TREE.getBits();

	/**
	 * True if all {@link #trees} point to entries with equal names.
	 *
	 * If at least one tree iterator point to a different name or
	 * reached end of the tree, the value is false.
	 * Note: if all iterators reached end of trees, the value is true.
	 */
	private boolean allTreesNamesMatchFastMinRef;

	private AbstractTreeIterator dfConflict;

	/**
	 * Create a new tree walker for a given repository.
	 *
	 * @param repo
	 *            the repository the walker will obtain data from.
	 */
	public NameConflictTreeWalk(Repository repo) {
		super(repo);
	}

	/**
	 * Create a new tree walker for a given repository.
	 *
	 * @param repo
	 *            the repository the walker will obtain data from.
	 * @param or
	 *            the reader the walker will obtain tree data from.
	 * @since 4.3
	 */
	public NameConflictTreeWalk(@Nullable Repository repo, ObjectReader or) {
		super(repo, or);
	}

	/**
	 * Create a new tree walker for a given repository.
	 *
	 * @param or
	 *            the reader the walker will obtain tree data from.
	 */
	public NameConflictTreeWalk(ObjectReader or) {
		super(or);
	}

	@Override
	AbstractTreeIterator min() throws CorruptObjectException {
		for (;;) {
			final AbstractTreeIterator minRef = fastMin();
			if (allTreesNamesMatchFastMinRef)
				return minRef;

			if (isTree(minRef)) {
				if (skipEntry(minRef)) {
					for (AbstractTreeIterator t : trees) {
						if (t.matches == minRef) {
							t.next(1);
							t.matches = null;
						}
					}
					continue;
				}
				return minRef;
			}

			return combineDF(minRef);
		}
	}

	private AbstractTreeIterator fastMin() {
		int i = getFirstNonEofTreeIndex();
		if (i == -1) {
			// All trees reached the end.
			allTreesNamesMatchFastMinRef = true;
			return trees[trees.length - 1];
		}
		AbstractTreeIterator minRef = trees[i];
		// if i > 0 then we already know that only some trees reached the end
		// (but not all), so it is impossible that ALL trees points to the
		// minRef entry.
		// Only if i == 0 it is still possible that all trees points to the same
		// minRef entry.
		allTreesNamesMatchFastMinRef = i == 0;
		boolean hasConflict = false;
		minRef.matches = minRef;
		while (++i < trees.length) {
			final AbstractTreeIterator t = trees[i];
			if (t.eof()) {
				allTreesNamesMatchFastMinRef = false;
				continue;
			}

			final int cmp = t.pathCompare(minRef);
			if (cmp < 0) {
				if (allTreesNamesMatchFastMinRef && isTree(minRef) && !isTree(t)
						&& nameEqual(minRef, t)) {
					// We used to be at a tree, but now we are at a file
					// with the same name. Allow the file to match the
					// tree anyway.
					//
					t.matches = minRef;
					hasConflict = true;
				} else {
					allTreesNamesMatchFastMinRef = false;
					t.matches = t;
					minRef = t;
				}
			} else if (cmp == 0) {
				// Exact name/mode match is best.
				//
				t.matches = minRef;
			} else if (allTreesNamesMatchFastMinRef && isTree(t)
					&& !isTree(minRef) && !isGitlink(minRef)
					&& nameEqual(t, minRef)) {
				// The minimum is a file (non-tree) but the next entry
				// of this iterator is a tree whose name matches our file.
				// This is a classic D/F conflict and commonly occurs like
				// this, with no gaps in between the file and directory.
				//
				// Use the tree as the minimum instead (see combineDF).
				//

				for (int k = 0; k < i; k++) {
					final AbstractTreeIterator p = trees[k];
					if (p.matches == minRef)
						p.matches = t;
				}
				t.matches = t;
				minRef = t;
				hasConflict = true;
			} else
				allTreesNamesMatchFastMinRef = false;
		}

		if (hasConflict && allTreesNamesMatchFastMinRef && dfConflict == null)
			dfConflict = minRef;
		return minRef;
	}

	private int getFirstNonEofTreeIndex() {
		for (int i = 0; i < trees.length; i++) {
			if (!trees[i].eof()) {
				return i;
			}
		}
		return -1;
	}

	private static boolean nameEqual(final AbstractTreeIterator a,
			final AbstractTreeIterator b) {
		return a.pathCompare(b, TREE_MODE) == 0;
	}

	private boolean isGitlink(AbstractTreeIterator p) {
		return FileMode.GITLINK.equals(p.mode);
	}

	private static boolean isTree(AbstractTreeIterator p) {
		return FileMode.TREE.equals(p.mode);
	}

	private boolean skipEntry(AbstractTreeIterator minRef)
			throws CorruptObjectException {
		// A tree D/F may have been handled earlier. We need to
		// not report this path if it has already been reported.
		//
		for (AbstractTreeIterator t : trees) {
			if (t.matches == minRef || t.first())
				continue;

			int stepsBack = 0;
			for (;;) {
				stepsBack++;
				t.back(1);

				final int cmp = t.pathCompare(minRef, 0);
				if (cmp == 0) {
					// We have already seen this "$path" before. Skip it.
					//
					t.next(stepsBack);
					return true;
				} else if (cmp < 0 || t.first()) {
					// We cannot find "$path" in t; it will never appear.
					//
					t.next(stepsBack);
					break;
				}
			}
		}

		// We have never seen the current path before.
		//
		return false;
	}

	private AbstractTreeIterator combineDF(AbstractTreeIterator minRef)
			throws CorruptObjectException {
		// Look for a possible D/F conflict forward in the tree(s)
		// as there may be a "$path/" which matches "$path". Make
		// such entries match this entry.
		//
		AbstractTreeIterator treeMatch = null;
		for (AbstractTreeIterator t : trees) {
			if (t.matches == minRef || t.eof())
				continue;

			for (;;) {
				final int cmp = t.pathCompare(minRef, TREE_MODE);
				if (cmp < 0) {
					// The "$path/" may still appear later.
					//
					t.matchShift++;
					t.next(1);
					if (t.eof()) {
						t.back(t.matchShift);
						t.matchShift = 0;
						break;
					}
				} else if (cmp == 0) {
					// We have a conflict match here.
					//
					t.matches = minRef;
					treeMatch = t;
					break;
				} else {
					// A conflict match is not possible.
					//
					if (t.matchShift != 0) {
						t.back(t.matchShift);
						t.matchShift = 0;
					}
					break;
				}
			}
		}

		// When the combineDF is called, the t.matches field stores other
		// entry (i.e. tree iterator) with an equal path. However, the
		// previous loop moves each iterator independently. As a result,
		// iterators which have had equals path at the start of the
		// method can have different paths at this point.
		// Reevaluate existing matches.
		// The NameConflictTreeWalkTest.testDF_specialFileNames test
		// cover this situation.
		for (AbstractTreeIterator t : trees) {
			// The previous loop doesn't touch tree iterator if it matches
			// minRef. Skip it here
			if (t.eof() || t.matches == null || t.matches == minRef)
				continue;
			// The t.pathCompare takes into account the entry type (file
			// or directory) and returns non-zero value if names match
			// but entry type don't match.
			// We want to keep such matches (file/directory conflict),
			// so reset matches only if names are not equal.
			if (!nameEqual(t, t.matches))
				t.matches = null;
		}

		if (treeMatch != null) {
			// If we do have a conflict use one of the directory
			// matching iterators instead of the file iterator.
			// This way isSubtree is true and isRecursive works.
			//
			for (AbstractTreeIterator t : trees)
				if (t.matches == minRef)
					t.matches = treeMatch;

			if (dfConflict == null && !isGitlink(minRef)) {
				dfConflict = treeMatch;
			}

			return treeMatch;
		}

		return minRef;
	}

	@Override
	void popEntriesEqual() throws CorruptObjectException {
		final AbstractTreeIterator ch = currentHead;
		for (AbstractTreeIterator t : trees) {
			if (t.matches == ch) {
				if (t.matchShift == 0)
					t.next(1);
				else {
					t.back(t.matchShift);
					t.matchShift = 0;
				}
				t.matches = null;
			}
		}

		if (ch == dfConflict)
			dfConflict = null;
	}

	@Override
	void skipEntriesEqual() throws CorruptObjectException {
		final AbstractTreeIterator ch = currentHead;
		for (AbstractTreeIterator t : trees) {
			if (t.matches == ch) {
				if (t.matchShift == 0)
					t.skip();
				else {
					t.back(t.matchShift);
					t.matchShift = 0;
				}
				t.matches = null;
			}
		}

		if (ch == dfConflict)
			dfConflict = null;
	}

	@Override
	void stopWalk() throws IOException {
		if (!needsStopWalk()) {
			return;
		}

		// Name conflicts make aborting early difficult. Multiple paths may
		// exist between the file and directory versions of a name. To ensure
		// the directory version is skipped over (as it was previously visited
		// during the file version step) requires popping up the stack and
		// finishing out each subtree that the walker dove into. Siblings in
		// parents do not need to be recursed into, bounding the cost.
		for (;;) {
			AbstractTreeIterator t = min();
			if (t.eof()) {
				if (depth > 0) {
					exitSubtree();
					popEntriesEqual();
					continue;
				}
				return;
			}
			currentHead = t;
			skipEntriesEqual();
		}
	}

	private boolean needsStopWalk() {
		for (AbstractTreeIterator t : trees) {
			if (t.needsStopWalk()) {
				return true;
			}
		}
		return false;
	}

	/**
	 * True if the current entry is covered by a directory/file conflict.
	 *
	 * This means that for some prefix of the current entry's path, this walk
	 * has detected a directory/file conflict. Also true if the current entry
	 * itself is a directory/file conflict.
	 *
	 * Example: If this TreeWalk points to foo/bar/a.txt and this method returns
	 * true then you know that either for path foo or for path foo/bar files and
	 * folders were detected.
	 *
	 * @return <code>true</code> if the current entry is covered by a
	 *         directory/file conflict, <code>false</code> otherwise
	 */
	public boolean isDirectoryFileConflict() {
		return dfConflict != null;
	}
}
