/*
 * Copyright (C) 2011, 2019 Google Inc.
 * and other copyright owners as documented in the project's IP log.
 *
 * 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
 *
 * 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.
 */

package org.eclipse.jgit.blame;

import static org.eclipse.jgit.lib.Constants.OBJ_BLOB;
import static org.eclipse.jgit.lib.FileMode.TYPE_FILE;
import static org.eclipse.jgit.lib.FileMode.TYPE_MASK;

import java.io.IOException;
import java.io.InputStream;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

import org.eclipse.jgit.annotations.Nullable;
import org.eclipse.jgit.api.errors.NoHeadException;
import org.eclipse.jgit.blame.Candidate.BlobCandidate;
import org.eclipse.jgit.blame.Candidate.HeadCandidate;
import org.eclipse.jgit.blame.Candidate.ReverseCandidate;
import org.eclipse.jgit.blame.ReverseWalk.ReverseCommit;
import org.eclipse.jgit.diff.DiffAlgorithm;
import org.eclipse.jgit.diff.DiffEntry;
import org.eclipse.jgit.diff.DiffEntry.ChangeType;
import org.eclipse.jgit.diff.EditList;
import org.eclipse.jgit.diff.HistogramDiff;
import org.eclipse.jgit.diff.RawText;
import org.eclipse.jgit.diff.RawTextComparator;
import org.eclipse.jgit.diff.RenameDetector;
import org.eclipse.jgit.dircache.DirCache;
import org.eclipse.jgit.dircache.DirCacheEntry;
import org.eclipse.jgit.dircache.DirCacheIterator;
import org.eclipse.jgit.errors.NoWorkTreeException;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.AnyObjectId;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.MutableObjectId;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectLoader;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevFlag;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.treewalk.FileTreeIterator;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.jgit.treewalk.TreeWalk.OperationType;
import org.eclipse.jgit.treewalk.filter.PathFilter;
import org.eclipse.jgit.treewalk.filter.TreeFilter;
import org.eclipse.jgit.util.IO;

/**
 * Generate author information for lines based on a provided file.
 * <p>
 * Applications that want a simple one-shot computation of blame for a file
 * should use {@link #computeBlameResult()} to prepare the entire result in one
 * method call. This may block for significant time as the history of the
 * repository must be traversed until information is gathered for every line.
 * <p>
 * Applications that want more incremental update behavior may use either the
 * raw {@link #next()} streaming approach supported by this class, or construct
 * a {@link org.eclipse.jgit.blame.BlameResult} using
 * {@link org.eclipse.jgit.blame.BlameResult#create(BlameGenerator)} and
 * incrementally construct the result with
 * {@link org.eclipse.jgit.blame.BlameResult#computeNext()}.
 * <p>
 * This class is not thread-safe.
 * <p>
 * An instance of BlameGenerator can only be used once. To blame multiple files
 * the application must create a new BlameGenerator.
 * <p>
 * During blame processing there are two files involved:
 * <ul>
 * <li>result - The file whose lines are being examined. This is the revision
 * the user is trying to view blame/annotation information alongside of.</li>
 * <li>source - The file that was blamed with supplying one or more lines of
 * data into result. The source may be a different file path (due to copy or
 * rename). Source line numbers may differ from result line numbers due to lines
 * being added/removed in intermediate revisions.</li>
 * </ul>
 * <p>
 * The blame algorithm is implemented by initially assigning responsibility for
 * all lines of the result to the starting commit. A difference against the
 * commit's ancestor is computed, and responsibility is passed to the ancestor
 * commit for any lines that are common. The starting commit is blamed only for
 * the lines that do not appear in the ancestor, if any. The loop repeats using
 * the ancestor, until there are no more lines to acquire information on, or the
 * file's creation point is discovered in history.
 */
public class BlameGenerator implements AutoCloseable {
	private final Repository repository;

	private final PathFilter resultPath;

	private final MutableObjectId idBuf;

	/** Revision pool used to acquire commits from. */
	private RevWalk revPool;

	/** Indicates the commit was put into the queue at least once. */
	private RevFlag SEEN;

	private ObjectReader reader;

	private TreeWalk treeWalk;

	private DiffAlgorithm diffAlgorithm = new HistogramDiff();

	private RawTextComparator textComparator = RawTextComparator.DEFAULT;

	private RenameDetector renameDetector;

	/** Potential candidates, sorted by commit time descending. */
	private Candidate queue;

	/** Number of lines that still need to be discovered. */
	private int remaining;

	/** Blame is currently assigned to this source. */
	private Candidate outCandidate;
	private Region outRegion;

	/**
	 * Create a blame generator for the repository and path (relative to
	 * repository)
	 *
	 * @param repository
	 *            repository to access revision data from.
	 * @param path
	 *            initial path of the file to start scanning (relative to the
	 *            repository).
	 */
	public BlameGenerator(Repository repository, String path) {
		this.repository = repository;
		this.resultPath = PathFilter.create(path);

		idBuf = new MutableObjectId();
		setFollowFileRenames(true);
		initRevPool(false);

		remaining = -1;
	}

	private void initRevPool(boolean reverse) {
		if (queue != null)
			throw new IllegalStateException();

		if (revPool != null)
			revPool.close();

		if (reverse)
			revPool = new ReverseWalk(getRepository());
		else
			revPool = new RevWalk(getRepository());

		SEEN = revPool.newFlag("SEEN"); //$NON-NLS-1$
		reader = revPool.getObjectReader();
		treeWalk = new TreeWalk(reader);
		treeWalk.setRecursive(true);
	}

	/**
	 * Get repository
	 *
	 * @return repository being scanned for revision history
	 */
	public Repository getRepository() {
		return repository;
	}

	/**
	 * Get result path
	 *
	 * @return path file path being processed
	 */
	public String getResultPath() {
		return resultPath.getPath();
	}

	/**
	 * Difference algorithm to use when comparing revisions.
	 *
	 * @param algorithm
	 *            a {@link org.eclipse.jgit.diff.DiffAlgorithm}
	 * @return {@code this}
	 */
	public BlameGenerator setDiffAlgorithm(DiffAlgorithm algorithm) {
		diffAlgorithm = algorithm;
		return this;
	}

	/**
	 * Text comparator to use when comparing revisions.
	 *
	 * @param comparator
	 *            a {@link org.eclipse.jgit.diff.RawTextComparator}
	 * @return {@code this}
	 */
	public BlameGenerator setTextComparator(RawTextComparator comparator) {
		textComparator = comparator;
		return this;
	}

	/**
	 * Enable (or disable) following file renames, on by default.
	 * <p>
	 * If true renames are followed using the standard FollowFilter behavior
	 * used by RevWalk (which matches {@code git log --follow} in the C
	 * implementation). This is not the same as copy/move detection as
	 * implemented by the C implementation's of {@code git blame -M -C}.
	 *
	 * @param follow
	 *            enable following.
	 * @return {@code this}
	 */
	public BlameGenerator setFollowFileRenames(boolean follow) {
		if (follow)
			renameDetector = new RenameDetector(getRepository());
		else
			renameDetector = null;
		return this;
	}

	/**
	 * Obtain the RenameDetector, allowing the application to configure its
	 * settings for rename score and breaking behavior.
	 *
	 * @return the rename detector, or {@code null} if
	 *         {@code setFollowFileRenames(false)}.
	 */
	@Nullable
	public RenameDetector getRenameDetector() {
		return renameDetector;
	}

	/**
	 * Push a candidate blob onto the generator's traversal stack.
	 * <p>
	 * Candidates should be pushed in history order from oldest-to-newest.
	 * Applications should push the starting commit first, then the index
	 * revision (if the index is interesting), and finally the working tree copy
	 * (if the working tree is interesting).
	 *
	 * @param description
	 *            description of the blob revision, such as "Working Tree".
	 * @param contents
	 *            contents of the file.
	 * @return {@code this}
	 * @throws java.io.IOException
	 *             the repository cannot be read.
	 */
	public BlameGenerator push(String description, byte[] contents)
			throws IOException {
		return push(description, new RawText(contents));
	}

	/**
	 * Push a candidate blob onto the generator's traversal stack.
	 * <p>
	 * Candidates should be pushed in history order from oldest-to-newest.
	 * Applications should push the starting commit first, then the index
	 * revision (if the index is interesting), and finally the working tree copy
	 * (if the working tree is interesting).
	 *
	 * @param description
	 *            description of the blob revision, such as "Working Tree".
	 * @param contents
	 *            contents of the file.
	 * @return {@code this}
	 * @throws java.io.IOException
	 *             the repository cannot be read.
	 */
	public BlameGenerator push(String description, RawText contents)
			throws IOException {
		if (description == null)
			description = JGitText.get().blameNotCommittedYet;
		BlobCandidate c = new BlobCandidate(getRepository(), description,
				resultPath);
		c.sourceText = contents;
		c.regionList = new Region(0, 0, contents.size());
		remaining = contents.size();
		push(c);
		return this;
	}

	/**
	 * Pushes HEAD, index, and working tree as appropriate for blaming the file
	 * given in the constructor {@link #BlameGenerator(Repository, String)}
	 * against HEAD. Includes special handling in case the file is in conflict
	 * state from an unresolved merge conflict.
	 *
	 * @return {@code this}
	 * @throws NoHeadException
	 *             if the repository has no HEAD
	 * @throws IOException
	 *             if an error occurs
	 * @since 5.6
	 */
	public BlameGenerator prepareHead() throws NoHeadException, IOException {
		Repository repo = getRepository();
		ObjectId head = repo.resolve(Constants.HEAD);
		if (head == null) {
			throw new NoHeadException(MessageFormat
					.format(JGitText.get().noSuchRefKnown, Constants.HEAD));
		}
		if (repo.isBare()) {
			return push(null, head);
		}
		DirCache dc = repo.readDirCache();
		try (TreeWalk walk = new TreeWalk(repo)) {
			walk.setOperationType(OperationType.CHECKIN_OP);
			FileTreeIterator iter = new FileTreeIterator(repo);
			int fileTree = walk.addTree(iter);
			int indexTree = walk.addTree(new DirCacheIterator(dc));
			iter.setDirCacheIterator(walk, indexTree);
			walk.setFilter(resultPath);
			walk.setRecursive(true);
			if (!walk.next()) {
				return this;
			}
			DirCacheIterator dcIter = walk.getTree(indexTree,
					DirCacheIterator.class);
			if (dcIter == null) {
				// Not found in index
				return this;
			}
			iter = walk.getTree(fileTree, FileTreeIterator.class);
			if (iter == null || !isFile(iter.getEntryRawMode())) {
				return this;
			}
			RawText inTree;
			long filteredLength = iter.getEntryContentLength();
			try (InputStream stream = iter.openEntryStream()) {
				inTree = new RawText(getBytes(iter.getEntryFile().getPath(),
						stream, filteredLength));
			}
			DirCacheEntry indexEntry = dcIter.getDirCacheEntry();
			if (indexEntry.getStage() == DirCacheEntry.STAGE_0) {
				push(null, head);
				push(null, indexEntry.getObjectId());
				push(null, inTree);
			} else {
				// Create a special candidate using the working tree file as
				// blob and HEAD and the MERGE_HEADs as parents.
				HeadCandidate c = new HeadCandidate(getRepository(), resultPath,
						getHeads(repo, head));
				c.sourceText = inTree;
				c.regionList = new Region(0, 0, inTree.size());
				remaining = inTree.size();
				push(c);
			}
		}
		return this;
	}

	private List<RevCommit> getHeads(Repository repo, ObjectId head)
			throws NoWorkTreeException, IOException {
		List<ObjectId> mergeIds = repo.readMergeHeads();
		if (mergeIds == null || mergeIds.isEmpty()) {
			return Collections.singletonList(revPool.parseCommit(head));
		}
		List<RevCommit> heads = new ArrayList<>(mergeIds.size() + 1);
		heads.add(revPool.parseCommit(head));
		for (ObjectId id : mergeIds) {
			heads.add(revPool.parseCommit(id));
		}
		return heads;
	}

	private static byte[] getBytes(String path, InputStream in, long maxLength)
			throws IOException {
		if (maxLength > Integer.MAX_VALUE) {
			throw new IOException(
					MessageFormat.format(JGitText.get().fileIsTooLarge, path));
		}
		int max = (int) maxLength;
		byte[] buffer = new byte[max];
		int read = IO.readFully(in, buffer, 0);
		if (read == max) {
			return buffer;
		}
		byte[] copy = new byte[read];
		System.arraycopy(buffer, 0, copy, 0, read);
		return copy;
	}

	/**
	 * Push a candidate object onto the generator's traversal stack.
	 * <p>
	 * Candidates should be pushed in history order from oldest-to-newest.
	 * Applications should push the starting commit first, then the index
	 * revision (if the index is interesting), and finally the working tree copy
	 * (if the working tree is interesting).
	 *
	 * @param description
	 *            description of the blob revision, such as "Working Tree".
	 * @param id
	 *            may be a commit or a blob.
	 * @return {@code this}
	 * @throws java.io.IOException
	 *             the repository cannot be read.
	 */
	public BlameGenerator push(String description, AnyObjectId id)
			throws IOException {
		ObjectLoader ldr = reader.open(id);
		if (ldr.getType() == OBJ_BLOB) {
			if (description == null)
				description = JGitText.get().blameNotCommittedYet;
			BlobCandidate c = new BlobCandidate(getRepository(), description,
					resultPath);
			c.sourceBlob = id.toObjectId();
			c.sourceText = new RawText(ldr.getCachedBytes(Integer.MAX_VALUE));
			c.regionList = new Region(0, 0, c.sourceText.size());
			remaining = c.sourceText.size();
			push(c);
			return this;
		}

		RevCommit commit = revPool.parseCommit(id);
		if (!find(commit, resultPath))
			return this;

		Candidate c = new Candidate(getRepository(), commit, resultPath);
		c.sourceBlob = idBuf.toObjectId();
		c.loadText(reader);
		c.regionList = new Region(0, 0, c.sourceText.size());
		remaining = c.sourceText.size();
		push(c);
		return this;
	}

	/**
	 * Configure the generator to compute reverse blame (history of deletes).
	 * <p>
	 * This method is expensive as it immediately runs a RevWalk over the
	 * history spanning the expression {@code start..end} (end being more recent
	 * than start) and then performs the equivalent operation as
	 * {@link #push(String, AnyObjectId)} to begin blame traversal from the
	 * commit named by {@code start} walking forwards through history until
	 * {@code end} blaming line deletions.
	 * <p>
	 * A reverse blame may produce multiple sources for the same result line,
	 * each of these is a descendant commit that removed the line, typically
	 * this occurs when the same deletion appears in multiple side branches such
	 * as due to a cherry-pick. Applications relying on reverse should use
	 * {@link org.eclipse.jgit.blame.BlameResult} as it filters these duplicate
	 * sources and only remembers the first (oldest) deletion.
	 *
	 * @param start
	 *            oldest commit to traverse from. The result file will be loaded
	 *            from this commit's tree.
	 * @param end
	 *            most recent commit to stop traversal at. Usually an active
	 *            branch tip, tag, or HEAD.
	 * @return {@code this}
	 * @throws java.io.IOException
	 *             the repository cannot be read.
	 */
	public BlameGenerator reverse(AnyObjectId start, AnyObjectId end)
			throws IOException {
		return reverse(start, Collections.singleton(end.toObjectId()));
	}

	/**
	 * Configure the generator to compute reverse blame (history of deletes).
	 * <p>
	 * This method is expensive as it immediately runs a RevWalk over the
	 * history spanning the expression {@code start..end} (end being more recent
	 * than start) and then performs the equivalent operation as
	 * {@link #push(String, AnyObjectId)} to begin blame traversal from the
	 * commit named by {@code start} walking forwards through history until
	 * {@code end} blaming line deletions.
	 * <p>
	 * A reverse blame may produce multiple sources for the same result line,
	 * each of these is a descendant commit that removed the line, typically
	 * this occurs when the same deletion appears in multiple side branches such
	 * as due to a cherry-pick. Applications relying on reverse should use
	 * {@link org.eclipse.jgit.blame.BlameResult} as it filters these duplicate
	 * sources and only remembers the first (oldest) deletion.
	 *
	 * @param start
	 *            oldest commit to traverse from. The result file will be loaded
	 *            from this commit's tree.
	 * @param end
	 *            most recent commits to stop traversal at. Usually an active
	 *            branch tip, tag, or HEAD.
	 * @return {@code this}
	 * @throws java.io.IOException
	 *             the repository cannot be read.
	 */
	public BlameGenerator reverse(AnyObjectId start,
			Collection<? extends ObjectId> end) throws IOException {
		initRevPool(true);

		ReverseCommit result = (ReverseCommit) revPool.parseCommit(start);
		if (!find(result, resultPath))
			return this;

		revPool.markUninteresting(result);
		for (ObjectId id : end)
			revPool.markStart(revPool.parseCommit(id));

		while (revPool.next() != null) {
			// just pump the queue
		}

		ReverseCandidate c = new ReverseCandidate(getRepository(), result,
				resultPath);
		c.sourceBlob = idBuf.toObjectId();
		c.loadText(reader);
		c.regionList = new Region(0, 0, c.sourceText.size());
		remaining = c.sourceText.size();
		push(c);
		return this;
	}

	/**
	 * Allocate a new RevFlag for use by the caller.
	 *
	 * @param name
	 *            unique name of the flag in the blame context.
	 * @return the newly allocated flag.
	 * @since 3.4
	 */
	public RevFlag newFlag(String name) {
		return revPool.newFlag(name);
	}

	/**
	 * Execute the generator in a blocking fashion until all data is ready.
	 *
	 * @return the complete result. Null if no file exists for the given path.
	 * @throws java.io.IOException
	 *             the repository cannot be read.
	 */
	public BlameResult computeBlameResult() throws IOException {
		try {
			BlameResult r = BlameResult.create(this);
			if (r != null)
				r.computeAll();
			return r;
		} finally {
			close();
		}
	}

	/**
	 * Step the blame algorithm one iteration.
	 *
	 * @return true if the generator has found a region's source. The getSource*
	 *         and {@link #getResultStart()}, {@link #getResultEnd()} methods
	 *         can be used to inspect the region found. False if there are no
	 *         more regions to describe.
	 * @throws java.io.IOException
	 *             repository cannot be read.
	 */
	public boolean next() throws IOException {
		// If there is a source still pending, produce the next region.
		if (outRegion != null) {
			Region r = outRegion;
			remaining -= r.length;
			if (r.next != null) {
				outRegion = r.next;
				return true;
			}

			if (outCandidate.queueNext != null)
				return result(outCandidate.queueNext);

			outCandidate = null;
			outRegion = null;
		}

		// If there are no lines remaining, the entire result is done,
		// even if there are revisions still available for the path.
		if (remaining == 0)
			return done();

		for (;;) {
			Candidate n = pop();
			if (n == null)
				return done();

			int pCnt = n.getParentCount();
			if (pCnt == 1) {
				if (processOne(n))
					return true;

			} else if (1 < pCnt) {
				if (processMerge(n))
					return true;

			} else if (n instanceof ReverseCandidate) {
				// Do not generate a tip of a reverse. The region
				// survives and should not appear to be deleted.

			} else /* if (pCnt == 0) */{
				// Root commit, with at least one surviving region.
				// Assign the remaining blame here.
				return result(n);
			}
		}
	}

	private boolean done() {
		close();
		return false;
	}

	private boolean result(Candidate n) throws IOException {
		n.beginResult(revPool);
		outCandidate = n;
		outRegion = n.regionList;
		return outRegion != null;
	}

	private boolean reverseResult(Candidate parent, Candidate source)
			throws IOException {
		// On a reverse blame present the application the parent
		// (as this is what did the removals), however the region
		// list to enumerate is the source's surviving list.
		Candidate res = parent.copy(parent.sourceCommit);
		res.regionList = source.regionList;
		return result(res);
	}

	private Candidate pop() {
		Candidate n = queue;
		if (n != null) {
			queue = n.queueNext;
			n.queueNext = null;
		}
		return n;
	}

	private void push(BlobCandidate toInsert) {
		Candidate c = queue;
		if (c != null) {
			c.remove(SEEN); // will be pushed by toInsert
			c.regionList = null;
			toInsert.parent = c;
		}
		queue = toInsert;
	}

	private void push(Candidate toInsert) {
		if (toInsert.has(SEEN)) {
			// We have already added a Candidate for this commit to the queue,
			// this can happen if the commit is a merge base for two or more
			// parallel branches that were merged together.
			//
			// It is likely the candidate was not yet processed. The queue
			// sorts descending by commit time and usually descendant commits
			// have higher timestamps than the ancestors.
			//
			// Find the existing candidate and merge the new candidate's
			// region list into it.
			for (Candidate p = queue; p != null; p = p.queueNext) {
				if (p.canMergeRegions(toInsert)) {
					p.mergeRegions(toInsert);
					return;
				}
			}
		}
		toInsert.add(SEEN);

		// Insert into the queue using descending commit time, so
		// the most recent commit will pop next.
		int time = toInsert.getTime();
		Candidate n = queue;
		if (n == null || time >= n.getTime()) {
			toInsert.queueNext = n;
			queue = toInsert;
			return;
		}

		for (Candidate p = n;; p = n) {
			n = p.queueNext;
			if (n == null || time >= n.getTime()) {
				toInsert.queueNext = n;
				p.queueNext = toInsert;
				return;
			}
		}
	}

	private boolean processOne(Candidate n) throws IOException {
		RevCommit parent = n.getParent(0);
		if (parent == null)
			return split(n.getNextCandidate(0), n);
		revPool.parseHeaders(parent);

		if (find(parent, n.sourcePath)) {
			if (idBuf.equals(n.sourceBlob))
				return blameEntireRegionOnParent(n, parent);
			return splitBlameWithParent(n, parent);
		}

		if (n.sourceCommit == null)
			return result(n);

		DiffEntry r = findRename(parent, n.sourceCommit, n.sourcePath);
		if (r == null)
			return result(n);

		if (0 == r.getOldId().prefixCompare(n.sourceBlob)) {
			// A 100% rename without any content change can also
			// skip directly to the parent.
			n.sourceCommit = parent;
			n.sourcePath = PathFilter.create(r.getOldPath());
			push(n);
			return false;
		}

		Candidate next = n.create(getRepository(), parent,
				PathFilter.create(r.getOldPath()));
		next.sourceBlob = r.getOldId().toObjectId();
		next.renameScore = r.getScore();
		next.loadText(reader);
		return split(next, n);
	}

	private boolean blameEntireRegionOnParent(Candidate n, RevCommit parent) {
		// File was not modified, blame parent.
		n.sourceCommit = parent;
		push(n);
		return false;
	}

	private boolean splitBlameWithParent(Candidate n, RevCommit parent)
			throws IOException {
		Candidate next = n.create(getRepository(), parent, n.sourcePath);
		next.sourceBlob = idBuf.toObjectId();
		next.loadText(reader);
		return split(next, n);
	}

	private boolean split(Candidate parent, Candidate source)
			throws IOException {
		EditList editList = diffAlgorithm.diff(textComparator,
				parent.sourceText, source.sourceText);
		if (editList.isEmpty()) {
			// Ignoring whitespace (or some other special comparator) can
			// cause non-identical blobs to have an empty edit list. In
			// a case like this push the parent alone.
			parent.regionList = source.regionList;
			push(parent);
			return false;
		}

		parent.takeBlame(editList, source);
		if (parent.regionList != null)
			push(parent);
		if (source.regionList != null) {
			if (source instanceof ReverseCandidate)
				return reverseResult(parent, source);
			return result(source);
		}
		return false;
	}

	private boolean processMerge(Candidate n) throws IOException {
		int pCnt = n.getParentCount();

		// If any single parent exactly matches the merge, follow only
		// that one parent through history.
		ObjectId[] ids = null;
		for (int pIdx = 0; pIdx < pCnt; pIdx++) {
			RevCommit parent = n.getParent(pIdx);
			revPool.parseHeaders(parent);
			if (!find(parent, n.sourcePath))
				continue;
			if (!(n instanceof ReverseCandidate) && idBuf.equals(n.sourceBlob))
				return blameEntireRegionOnParent(n, parent);
			if (ids == null)
				ids = new ObjectId[pCnt];
			ids[pIdx] = idBuf.toObjectId();
		}

		// If rename detection is enabled, search for any relevant names.
		DiffEntry[] renames = null;
		if (renameDetector != null) {
			renames = new DiffEntry[pCnt];
			for (int pIdx = 0; pIdx < pCnt; pIdx++) {
				RevCommit parent = n.getParent(pIdx);
				if (ids != null && ids[pIdx] != null)
					continue;

				DiffEntry r = findRename(parent, n.sourceCommit, n.sourcePath);
				if (r == null)
					continue;

				if (n instanceof ReverseCandidate) {
					if (ids == null)
						ids = new ObjectId[pCnt];
					ids[pCnt] = r.getOldId().toObjectId();
				} else if (0 == r.getOldId().prefixCompare(n.sourceBlob)) {
					// A 100% rename without any content change can also
					// skip directly to the parent. Note this bypasses an
					// earlier parent that had the path (above) but did not
					// have an exact content match. For performance reasons
					// we choose to follow the one parent over trying to do
					// possibly both parents.
					n.sourcePath = PathFilter.create(r.getOldPath());
					return blameEntireRegionOnParent(n, parent);
				}

				renames[pIdx] = r;
			}
		}

		// Construct the candidate for each parent.
		Candidate[] parents = new Candidate[pCnt];
		for (int pIdx = 0; pIdx < pCnt; pIdx++) {
			RevCommit parent = n.getParent(pIdx);

			Candidate p;
			if (renames != null && renames[pIdx] != null) {
				p = n.create(getRepository(), parent,
						PathFilter.create(renames[pIdx].getOldPath()));
				p.renameScore = renames[pIdx].getScore();
				p.sourceBlob = renames[pIdx].getOldId().toObjectId();
			} else if (ids != null && ids[pIdx] != null) {
				p = n.create(getRepository(), parent, n.sourcePath);
				p.sourceBlob = ids[pIdx];
			} else {
				continue;
			}

			EditList editList;
			if (n instanceof ReverseCandidate
					&& p.sourceBlob.equals(n.sourceBlob)) {
				// This special case happens on ReverseCandidate forks.
				p.sourceText = n.sourceText;
				editList = new EditList(0);
			} else {
				p.loadText(reader);
				editList = diffAlgorithm.diff(textComparator,
						p.sourceText, n.sourceText);
			}

			if (editList.isEmpty()) {
				// Ignoring whitespace (or some other special comparator) can
				// cause non-identical blobs to have an empty edit list. In
				// a case like this push the parent alone.
				if (n instanceof ReverseCandidate) {
					parents[pIdx] = p;
					continue;
				}

				p.regionList = n.regionList;
				n.regionList = null;
				parents[pIdx] = p;
				break;
			}

			p.takeBlame(editList, n);

			// Only remember this parent candidate if there is at least
			// one region that was blamed on the parent.
			if (p.regionList != null) {
				// Reverse blame requires inverting the regions. This puts
				// the regions the parent deleted from us into the parent,
				// and retains the common regions to look at other parents
				// for deletions.
				if (n instanceof ReverseCandidate) {
					Region r = p.regionList;
					p.regionList = n.regionList;
					n.regionList = r;
				}

				parents[pIdx] = p;
			}
		}

		if (n instanceof ReverseCandidate) {
			// On a reverse blame report all deletions found in the children,
			// and pass on to them a copy of our region list.
			Candidate resultHead = null;
			Candidate resultTail = null;

			for (int pIdx = 0; pIdx < pCnt; pIdx++) {
				Candidate p = parents[pIdx];
				if (p == null)
					continue;

				if (p.regionList != null) {
					Candidate r = p.copy(p.sourceCommit);
					if (resultTail != null) {
						resultTail.queueNext = r;
						resultTail = r;
					} else {
						resultHead = r;
						resultTail = r;
					}
				}

				if (n.regionList != null) {
					p.regionList = n.regionList.deepCopy();
					push(p);
				}
			}

			if (resultHead != null)
				return result(resultHead);
			return false;
		}

		// Push any parents that are still candidates.
		for (int pIdx = 0; pIdx < pCnt; pIdx++) {
			if (parents[pIdx] != null)
				push(parents[pIdx]);
		}

		if (n.regionList != null)
			return result(n);
		return false;
	}

	/**
	 * Get the revision blamed for the current region.
	 * <p>
	 * The source commit may be null if the line was blamed to an uncommitted
	 * revision, such as the working tree copy, or during a reverse blame if the
	 * line survives to the end revision (e.g. the branch tip).
	 *
	 * @return current revision being blamed.
	 */
	public RevCommit getSourceCommit() {
		return outCandidate.sourceCommit;
	}

	/**
	 * Get source author
	 *
	 * @return current author being blamed
	 */
	public PersonIdent getSourceAuthor() {
		return outCandidate.getAuthor();
	}

	/**
	 * Get source committer
	 *
	 * @return current committer being blamed
	 */
	public PersonIdent getSourceCommitter() {
		RevCommit c = getSourceCommit();
		return c != null ? c.getCommitterIdent() : null;
	}

	/**
	 * Get source path
	 *
	 * @return path of the file being blamed
	 */
	public String getSourcePath() {
		return outCandidate.sourcePath.getPath();
	}

	/**
	 * Get rename score
	 *
	 * @return rename score if a rename occurred in {@link #getSourceCommit}
	 */
	public int getRenameScore() {
		return outCandidate.renameScore;
	}

	/**
	 * Get first line of the source data that has been blamed for the current
	 * region
	 *
	 * @return first line of the source data that has been blamed for the
	 *         current region. This is line number of where the region was added
	 *         during {@link #getSourceCommit()} in file
	 *         {@link #getSourcePath()}.
	 */
	public int getSourceStart() {
		return outRegion.sourceStart;
	}

	/**
	 * Get one past the range of the source data that has been blamed for the
	 * current region
	 *
	 * @return one past the range of the source data that has been blamed for
	 *         the current region. This is line number of where the region was
	 *         added during {@link #getSourceCommit()} in file
	 *         {@link #getSourcePath()}.
	 */
	public int getSourceEnd() {
		Region r = outRegion;
		return r.sourceStart + r.length;
	}

	/**
	 * Get first line of the result that {@link #getSourceCommit()} has been
	 * blamed for providing
	 *
	 * @return first line of the result that {@link #getSourceCommit()} has been
	 *         blamed for providing. Line numbers use 0 based indexing.
	 */
	public int getResultStart() {
		return outRegion.resultStart;
	}

	/**
	 * Get one past the range of the result that {@link #getSourceCommit()} has
	 * been blamed for providing
	 *
	 * @return one past the range of the result that {@link #getSourceCommit()}
	 *         has been blamed for providing. Line numbers use 0 based indexing.
	 *         Because a source cannot be blamed for an empty region of the
	 *         result, {@link #getResultEnd()} is always at least one larger
	 *         than {@link #getResultStart()}.
	 */
	public int getResultEnd() {
		Region r = outRegion;
		return r.resultStart + r.length;
	}

	/**
	 * Get number of lines in the current region being blamed to
	 * {@link #getSourceCommit()}
	 *
	 * @return number of lines in the current region being blamed to
	 *         {@link #getSourceCommit()}. This is always the value of the
	 *         expression {@code getResultEnd() - getResultStart()}, but also
	 *         {@code getSourceEnd() - getSourceStart()}.
	 */
	public int getRegionLength() {
		return outRegion.length;
	}

	/**
	 * Get complete contents of the source file blamed for the current output
	 * region
	 *
	 * @return complete contents of the source file blamed for the current
	 *         output region. This is the contents of {@link #getSourcePath()}
	 *         within {@link #getSourceCommit()}. The source contents is
	 *         temporarily available as an artifact of the blame algorithm. Most
	 *         applications will want the result contents for display to users.
	 */
	public RawText getSourceContents() {
		return outCandidate.sourceText;
	}

	/**
	 * Get complete file contents of the result file blame is annotating
	 *
	 * @return complete file contents of the result file blame is annotating.
	 *         This value is accessible only after being configured and only
	 *         immediately before the first call to {@link #next()}. Returns
	 *         null if the path does not exist.
	 * @throws java.io.IOException
	 *             repository cannot be read.
	 * @throws java.lang.IllegalStateException
	 *             {@link #next()} has already been invoked.
	 */
	public RawText getResultContents() throws IOException {
		return queue != null ? queue.sourceText : null;
	}

	/**
	 * {@inheritDoc}
	 * <p>
	 * Release the current blame session.
	 *
	 * @since 4.0
	 */
	@Override
	public void close() {
		revPool.close();
		queue = null;
		outCandidate = null;
		outRegion = null;
	}

	private boolean find(RevCommit commit, PathFilter path) throws IOException {
		treeWalk.setFilter(path);
		treeWalk.reset(commit.getTree());
		if (treeWalk.next() && isFile(treeWalk.getRawMode(0))) {
			treeWalk.getObjectId(idBuf, 0);
			return true;
		}
		return false;
	}

	private static final boolean isFile(int rawMode) {
		return (rawMode & TYPE_MASK) == TYPE_FILE;
	}

	private DiffEntry findRename(RevCommit parent, RevCommit commit,
			PathFilter path) throws IOException {
		if (renameDetector == null)
			return null;

		treeWalk.setFilter(TreeFilter.ANY_DIFF);
		treeWalk.reset(parent.getTree(), commit.getTree());
		renameDetector.reset();
		renameDetector.addAll(DiffEntry.scan(treeWalk));
		for (DiffEntry ent : renameDetector.compute()) {
			if (isRename(ent) && ent.getNewPath().equals(path.getPath()))
				return ent;
		}
		return null;
	}

	private static boolean isRename(DiffEntry ent) {
		return ent.getChangeType() == ChangeType.RENAME
				|| ent.getChangeType() == ChangeType.COPY;
	}
}
