/*
 * Copyright (C) 2007, Dave Watson <dwatson@mimvista.com>
 * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
 * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
 * Copyright (C) 2013, Robin Stocker <robin@nibor.org> 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.lib;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.TreeSet;

import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.MergeResult;
import org.eclipse.jgit.api.MergeResult.MergeStatus;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.dircache.DirCache;
import org.eclipse.jgit.dircache.DirCacheBuilder;
import org.eclipse.jgit.dircache.DirCacheEditor;
import org.eclipse.jgit.dircache.DirCacheEditor.PathEdit;
import org.eclipse.jgit.dircache.DirCacheEntry;
import org.eclipse.jgit.junit.RepositoryTestCase;
import org.eclipse.jgit.lib.CoreConfig.AutoCRLF;
import org.eclipse.jgit.lib.IndexDiff.StageState;
import org.eclipse.jgit.merge.MergeStrategy;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.storage.file.FileBasedConfig;
import org.eclipse.jgit.treewalk.FileTreeIterator;
import org.eclipse.jgit.util.IO;
import org.junit.Test;

public class IndexDiffTest extends RepositoryTestCase {

	static PathEdit add(final Repository db, final File workdir,
			final String path) throws FileNotFoundException, IOException {
		final File f = new File(workdir, path);
		ObjectId id;
		try (ObjectInserter inserter = db.newObjectInserter()) {
			id = inserter.insert(Constants.OBJ_BLOB,
				IO.readFully(f));
		}
		return new PathEdit(path) {
			@Override
			public void apply(DirCacheEntry ent) {
				ent.setFileMode(FileMode.REGULAR_FILE);
				ent.setLength(f.length());
				ent.setObjectId(id);
			}
		};
	}

	@Test
	public void testAdded() throws IOException {
		writeTrashFile("file1", "file1");
		writeTrashFile("dir/subfile", "dir/subfile");
		ObjectId tree = insertTree(new TreeFormatter());

		DirCache index = db.lockDirCache();
		DirCacheEditor editor = index.editor();
		editor.add(add(db, trash, "file1"));
		editor.add(add(db, trash, "dir/subfile"));
		editor.commit();
		FileTreeIterator iterator = new FileTreeIterator(db);
		IndexDiff diff = new IndexDiff(db, tree, iterator);
		diff.diff();
		assertEquals(2, diff.getAdded().size());
		assertTrue(diff.getAdded().contains("file1"));
		assertTrue(diff.getAdded().contains("dir/subfile"));
		assertEquals(0, diff.getChanged().size());
		assertEquals(0, diff.getModified().size());
		assertEquals(0, diff.getRemoved().size());
		assertEquals(Collections.EMPTY_SET, diff.getUntrackedFolders());
	}

	@Test
	public void testMissing() throws Exception {
		File file2 = writeTrashFile("file2", "file2");
		File file3 = writeTrashFile("dir/file3", "dir/file3");
		try (Git git = new Git(db)) {
			git.add().addFilepattern("file2").addFilepattern("dir/file3")
					.call();
			git.commit().setMessage("commit").call();
		}
		assertTrue(file2.delete());
		assertTrue(file3.delete());
		IndexDiff diff = new IndexDiff(db, Constants.HEAD,
				new FileTreeIterator(db));
		diff.diff();
		assertEquals(2, diff.getMissing().size());
		assertTrue(diff.getMissing().contains("file2"));
		assertTrue(diff.getMissing().contains("dir/file3"));
		assertEquals(0, diff.getChanged().size());
		assertEquals(0, diff.getModified().size());
		assertEquals(0, diff.getAdded().size());
		assertEquals(0, diff.getRemoved().size());
		assertEquals(Collections.EMPTY_SET, diff.getUntrackedFolders());
	}

	@Test
	public void testRemoved() throws IOException {
		writeTrashFile("file2", "file2");
		writeTrashFile("dir/file3", "dir/file3");

		TreeFormatter dir = new TreeFormatter();
		dir.append("file3", FileMode.REGULAR_FILE, ObjectId.fromString("873fb8d667d05436d728c52b1d7a09528e6eb59b"));

		TreeFormatter tree = new TreeFormatter();
		tree.append("file2", FileMode.REGULAR_FILE, ObjectId.fromString("30d67d4672d5c05833b7192cc77a79eaafb5c7ad"));
		tree.append("dir", FileMode.TREE, insertTree(dir));
		ObjectId treeId = insertTree(tree);

		FileTreeIterator iterator = new FileTreeIterator(db);
		IndexDiff diff = new IndexDiff(db, treeId, iterator);
		diff.diff();
		assertEquals(2, diff.getRemoved().size());
		assertTrue(diff.getRemoved().contains("file2"));
		assertTrue(diff.getRemoved().contains("dir/file3"));
		assertEquals(0, diff.getChanged().size());
		assertEquals(0, diff.getModified().size());
		assertEquals(0, diff.getAdded().size());
		assertEquals(Collections.EMPTY_SET, diff.getUntrackedFolders());
	}

	@Test
	public void testModified() throws IOException, GitAPIException {

		writeTrashFile("file2", "file2");
		writeTrashFile("dir/file3", "dir/file3");

		try (Git git = new Git(db)) {
			git.add().addFilepattern("file2").addFilepattern("dir/file3").call();
		}

		writeTrashFile("dir/file3", "changed");

		TreeFormatter dir = new TreeFormatter();
		dir.append("file3", FileMode.REGULAR_FILE, ObjectId.fromString("0123456789012345678901234567890123456789"));

		TreeFormatter tree = new TreeFormatter();
		tree.append("dir", FileMode.TREE, insertTree(dir));
		tree.append("file2", FileMode.REGULAR_FILE, ObjectId.fromString("0123456789012345678901234567890123456789"));
		ObjectId treeId = insertTree(tree);

		FileTreeIterator iterator = new FileTreeIterator(db);
		IndexDiff diff = new IndexDiff(db, treeId, iterator);
		diff.diff();
		assertEquals(2, diff.getChanged().size());
		assertTrue(diff.getChanged().contains("file2"));
		assertTrue(diff.getChanged().contains("dir/file3"));
		assertEquals(1, diff.getModified().size());
		assertTrue(diff.getModified().contains("dir/file3"));
		assertEquals(0, diff.getAdded().size());
		assertEquals(0, diff.getRemoved().size());
		assertEquals(0, diff.getMissing().size());
		assertEquals(Collections.EMPTY_SET, diff.getUntrackedFolders());
	}

	@Test
	public void testConflicting() throws Exception {
		try (Git git = new Git(db)) {
			writeTrashFile("a", "1\na\n3\n");
			writeTrashFile("b", "1\nb\n3\n");
			git.add().addFilepattern("a").addFilepattern("b").call();
			RevCommit initialCommit = git.commit().setMessage("initial").call();

			// create side branch with two modifications
			createBranch(initialCommit, "refs/heads/side");
			checkoutBranch("refs/heads/side");
			writeTrashFile("a", "1\na(side)\n3\n");
			writeTrashFile("b", "1\nb\n3\n(side)");
			git.add().addFilepattern("a").addFilepattern("b").call();
			RevCommit secondCommit = git.commit().setMessage("side").call();

			// update a on master to generate conflict
			checkoutBranch("refs/heads/master");
			writeTrashFile("a", "1\na(main)\n3\n");
			git.add().addFilepattern("a").call();
			git.commit().setMessage("main").call();

			// merge side with master
			MergeResult result = git.merge().include(secondCommit.getId())
					.setStrategy(MergeStrategy.RESOLVE).call();
			assertEquals(MergeStatus.CONFLICTING, result.getMergeStatus());
		}

		FileTreeIterator iterator = new FileTreeIterator(db);
		IndexDiff diff = new IndexDiff(db, Constants.HEAD, iterator);
		diff.diff();

		assertEquals("[b]",
				new TreeSet<>(diff.getChanged()).toString());
		assertEquals("[]", diff.getAdded().toString());
		assertEquals("[]", diff.getRemoved().toString());
		assertEquals("[]", diff.getMissing().toString());
		assertEquals("[]", diff.getModified().toString());
		assertEquals("[a]", diff.getConflicting().toString());
		assertEquals(StageState.BOTH_MODIFIED,
				diff.getConflictingStageStates().get("a"));
		assertEquals(Collections.EMPTY_SET, diff.getUntrackedFolders());
	}

	@Test
	public void testConflictingDeletedAndModified() throws Exception {
		try (Git git = new Git(db)) {
			writeTrashFile("a", "1\na\n3\n");
			writeTrashFile("b", "1\nb\n3\n");
			git.add().addFilepattern("a").addFilepattern("b").call();
			RevCommit initialCommit = git.commit().setMessage("initial").call();

			// create side branch and delete "a"
			createBranch(initialCommit, "refs/heads/side");
			checkoutBranch("refs/heads/side");
			git.rm().addFilepattern("a").call();
			RevCommit secondCommit = git.commit().setMessage("side").call();

			// update a on master to generate conflict
			checkoutBranch("refs/heads/master");
			writeTrashFile("a", "1\na(main)\n3\n");
			git.add().addFilepattern("a").call();
			git.commit().setMessage("main").call();

			// merge side with master
			MergeResult result = git.merge().include(secondCommit.getId())
					.setStrategy(MergeStrategy.RESOLVE).call();
			assertEquals(MergeStatus.CONFLICTING, result.getMergeStatus());
		}

		FileTreeIterator iterator = new FileTreeIterator(db);
		IndexDiff diff = new IndexDiff(db, Constants.HEAD, iterator);
		diff.diff();

		assertEquals("[]", new TreeSet<>(diff.getChanged()).toString());
		assertEquals("[]", diff.getAdded().toString());
		assertEquals("[]", diff.getRemoved().toString());
		assertEquals("[]", diff.getMissing().toString());
		assertEquals("[]", diff.getModified().toString());
		assertEquals("[a]", diff.getConflicting().toString());
		assertEquals(StageState.DELETED_BY_THEM,
				diff.getConflictingStageStates().get("a"));
		assertEquals(Collections.EMPTY_SET, diff.getUntrackedFolders());
	}

	@Test
	public void testConflictingFromMultipleCreations() throws Exception {
		try (Git git = new Git(db)) {
			writeTrashFile("a", "1\na\n3\n");
			git.add().addFilepattern("a").call();
			RevCommit initialCommit = git.commit().setMessage("initial").call();

			createBranch(initialCommit, "refs/heads/side");
			checkoutBranch("refs/heads/side");

			writeTrashFile("b", "1\nb(side)\n3\n");
			git.add().addFilepattern("b").call();
			RevCommit secondCommit = git.commit().setMessage("side").call();

			checkoutBranch("refs/heads/master");

			writeTrashFile("b", "1\nb(main)\n3\n");
			git.add().addFilepattern("b").call();
			git.commit().setMessage("main").call();

			MergeResult result = git.merge().include(secondCommit.getId())
					.setStrategy(MergeStrategy.RESOLVE).call();
			assertEquals(MergeStatus.CONFLICTING, result.getMergeStatus());
		}

		FileTreeIterator iterator = new FileTreeIterator(db);
		IndexDiff diff = new IndexDiff(db, Constants.HEAD, iterator);
		diff.diff();

		assertEquals("[]", new TreeSet<>(diff.getChanged()).toString());
		assertEquals("[]", diff.getAdded().toString());
		assertEquals("[]", diff.getRemoved().toString());
		assertEquals("[]", diff.getMissing().toString());
		assertEquals("[]", diff.getModified().toString());
		assertEquals("[b]", diff.getConflicting().toString());
		assertEquals(Collections.EMPTY_SET, diff.getUntrackedFolders());
	}

	@Test
	public void testUnchangedSimple() throws IOException, GitAPIException {
		writeTrashFile("a.b", "a.b");
		writeTrashFile("a.c", "a.c");
		writeTrashFile("a=c", "a=c");
		writeTrashFile("a=d", "a=d");
		try (Git git = new Git(db)) {
			git.add().addFilepattern("a.b").call();
			git.add().addFilepattern("a.c").call();
			git.add().addFilepattern("a=c").call();
			git.add().addFilepattern("a=d").call();
		}

		TreeFormatter tree = new TreeFormatter();
		// got the hash id'd from the data using echo -n a.b|git hash-object -t blob --stdin
		tree.append("a.b", FileMode.REGULAR_FILE, ObjectId.fromString("f6f28df96c2b40c951164286e08be7c38ec74851"));
		tree.append("a.c", FileMode.REGULAR_FILE, ObjectId.fromString("6bc0e647512d2a0bef4f26111e484dc87df7f5ca"));
		tree.append("a=c", FileMode.REGULAR_FILE, ObjectId.fromString("06022365ddbd7fb126761319633bf73517770714"));
		tree.append("a=d", FileMode.REGULAR_FILE, ObjectId.fromString("fa6414df3da87840700e9eeb7fc261dd77ccd5c2"));
		ObjectId treeId = insertTree(tree);

		FileTreeIterator iterator = new FileTreeIterator(db);
		IndexDiff diff = new IndexDiff(db, treeId, iterator);
		diff.diff();
		assertEquals(0, diff.getChanged().size());
		assertEquals(0, diff.getAdded().size());
		assertEquals(0, diff.getRemoved().size());
		assertEquals(0, diff.getMissing().size());
		assertEquals(0, diff.getModified().size());
		assertEquals(Collections.EMPTY_SET, diff.getUntrackedFolders());
	}

	/**
	 * This test has both files and directories that involve the tricky ordering
	 * used by Git.
	 *
	 * @throws IOException
	 * @throws GitAPIException
	 */
	@Test
	public void testUnchangedComplex() throws IOException, GitAPIException {
		writeTrashFile("a.b", "a.b");
		writeTrashFile("a.c", "a.c");
		writeTrashFile("a/b.b/b", "a/b.b/b");
		writeTrashFile("a/b", "a/b");
		writeTrashFile("a/c", "a/c");
		writeTrashFile("a=c", "a=c");
		writeTrashFile("a=d", "a=d");
		try (Git git = new Git(db)) {
			git.add().addFilepattern("a.b").addFilepattern("a.c")
					.addFilepattern("a/b.b/b").addFilepattern("a/b")
					.addFilepattern("a/c").addFilepattern("a=c")
					.addFilepattern("a=d").call();
		}


		// got the hash id'd from the data using echo -n a.b|git hash-object -t blob --stdin
		TreeFormatter bb = new TreeFormatter();
		bb.append("b", FileMode.REGULAR_FILE, ObjectId.fromString("8d840bd4e2f3a48ff417c8e927d94996849933fd"));

		TreeFormatter a = new TreeFormatter();
		a.append("b", FileMode.REGULAR_FILE, ObjectId
				.fromString("db89c972fc57862eae378f45b74aca228037d415"));
		a.append("b.b", FileMode.TREE, insertTree(bb));
		a.append("c", FileMode.REGULAR_FILE, ObjectId.fromString("52ad142a008aeb39694bafff8e8f1be75ed7f007"));

		TreeFormatter tree = new TreeFormatter();
		tree.append("a.b", FileMode.REGULAR_FILE, ObjectId.fromString("f6f28df96c2b40c951164286e08be7c38ec74851"));
		tree.append("a.c", FileMode.REGULAR_FILE, ObjectId.fromString("6bc0e647512d2a0bef4f26111e484dc87df7f5ca"));
		tree.append("a", FileMode.TREE, insertTree(a));
		tree.append("a=c", FileMode.REGULAR_FILE, ObjectId.fromString("06022365ddbd7fb126761319633bf73517770714"));
		tree.append("a=d", FileMode.REGULAR_FILE, ObjectId.fromString("fa6414df3da87840700e9eeb7fc261dd77ccd5c2"));
		ObjectId treeId = insertTree(tree);

		FileTreeIterator iterator = new FileTreeIterator(db);
		IndexDiff diff = new IndexDiff(db, treeId, iterator);
		diff.diff();
		assertEquals(0, diff.getChanged().size());
		assertEquals(0, diff.getAdded().size());
		assertEquals(0, diff.getRemoved().size());
		assertEquals(0, diff.getMissing().size());
		assertEquals(0, diff.getModified().size());
		assertEquals(Collections.EMPTY_SET, diff.getUntrackedFolders());
	}

	private ObjectId insertTree(TreeFormatter tree) throws IOException {
		try (ObjectInserter oi = db.newObjectInserter()) {
			ObjectId id = oi.insert(tree);
			oi.flush();
			return id;
		}
	}

	/**
	 * A file is removed from the index but stays in the working directory. It
	 * is checked if IndexDiff detects this file as removed and untracked.
	 *
	 * @throws Exception
	 */
	@Test
	public void testRemovedUntracked() throws Exception{
		String path = "file";
		try (Git git = new Git(db)) {
			writeTrashFile(path, "content");
			git.add().addFilepattern(path).call();
			git.commit().setMessage("commit").call();
		}
		removeFromIndex(path);
		FileTreeIterator iterator = new FileTreeIterator(db);
		IndexDiff diff = new IndexDiff(db, Constants.HEAD, iterator);
		diff.diff();
		assertTrue(diff.getRemoved().contains(path));
		assertTrue(diff.getUntracked().contains(path));
		assertEquals(Collections.EMPTY_SET, diff.getUntrackedFolders());
	}

	/**
	 *
	 * @throws Exception
	 */
	@Test
	public void testUntrackedFolders() throws Exception {
		try (Git git = new Git(db)) {
			IndexDiff diff = new IndexDiff(db, Constants.HEAD,
					new FileTreeIterator(db));
			diff.diff();
			assertEquals(Collections.EMPTY_SET, diff.getUntrackedFolders());

			writeTrashFile("readme", "");
			writeTrashFile("src/com/A.java", "");
			writeTrashFile("src/com/B.java", "");
			writeTrashFile("src/org/A.java", "");
			writeTrashFile("src/org/B.java", "");
			writeTrashFile("target/com/A.java", "");
			writeTrashFile("target/com/B.java", "");
			writeTrashFile("target/org/A.java", "");
			writeTrashFile("target/org/B.java", "");

			git.add().addFilepattern("src").addFilepattern("readme").call();
			git.commit().setMessage("initial").call();

			diff = new IndexDiff(db, Constants.HEAD,
					new FileTreeIterator(db));
			diff.diff();
			assertEquals(new HashSet<>(Arrays.asList("target")),
					diff.getUntrackedFolders());

			writeTrashFile("src/tst/A.java", "");
			writeTrashFile("src/tst/B.java", "");

			diff = new IndexDiff(db, Constants.HEAD, new FileTreeIterator(db));
			diff.diff();
			assertEquals(new HashSet<>(Arrays.asList("target", "src/tst")),
					diff.getUntrackedFolders());

			git.rm().addFilepattern("src/com/B.java").addFilepattern("src/org")
					.call();
			git.commit().setMessage("second").call();
			writeTrashFile("src/org/C.java", "");

			diff = new IndexDiff(db, Constants.HEAD, new FileTreeIterator(db));
			diff.diff();
			assertEquals(
					new HashSet<>(Arrays.asList("src/org", "src/tst",
							"target")),
					diff.getUntrackedFolders());
		}
	}

	/**
	 * Test that ignored folders aren't listed as untracked, but are listed as
	 * ignored.
	 *
	 * @throws Exception
	 */
	@Test
	public void testUntrackedNotIgnoredFolders() throws Exception {
		try (Git git = new Git(db)) {
			IndexDiff diff = new IndexDiff(db, Constants.HEAD,
					new FileTreeIterator(db));
			diff.diff();
			assertEquals(Collections.EMPTY_SET, diff.getUntrackedFolders());

			writeTrashFile("readme", "");
			writeTrashFile("sr/com/X.java", "");
			writeTrashFile("src/com/A.java", "");
			writeTrashFile("src/org/B.java", "");
			writeTrashFile("srcs/org/Y.java", "");
			writeTrashFile("target/com/A.java", "");
			writeTrashFile("target/org/B.java", "");
			writeTrashFile(".gitignore", "/target\n/sr");

			git.add().addFilepattern("readme").addFilepattern(".gitignore")
					.addFilepattern("srcs/").call();
			git.commit().setMessage("initial").call();

			diff = new IndexDiff(db, Constants.HEAD, new FileTreeIterator(db));
			diff.diff();
			assertEquals(new HashSet<>(Arrays.asList("src")),
					diff.getUntrackedFolders());
			assertEquals(new HashSet<>(Arrays.asList("sr", "target")),
					diff.getIgnoredNotInIndex());

			git.add().addFilepattern("src").call();
			writeTrashFile("sr/com/X1.java", "");
			writeTrashFile("src/tst/A.java", "");
			writeTrashFile("src/tst/B.java", "");
			writeTrashFile("srcs/com/Y1.java", "");
			deleteTrashFile(".gitignore");

			diff = new IndexDiff(db, Constants.HEAD, new FileTreeIterator(db));
			diff.diff();
			assertEquals(
					new HashSet<>(Arrays.asList("srcs/com", "sr", "src/tst",
							"target")),
					diff.getUntrackedFolders());
		}
	}

	@Test
	public void testAssumeUnchanged() throws Exception {
		try (Git git = new Git(db)) {
			String path = "file";
			writeTrashFile(path, "content");
			git.add().addFilepattern(path).call();
			String path2 = "file2";
			writeTrashFile(path2, "content");
			String path3 = "file3";
			writeTrashFile(path3, "some content");
			git.add().addFilepattern(path2).addFilepattern(path3).call();
			git.commit().setMessage("commit").call();
			assumeUnchanged(path2);
			assumeUnchanged(path3);
			writeTrashFile(path, "more content");
			deleteTrashFile(path3);

			FileTreeIterator iterator = new FileTreeIterator(db);
			IndexDiff diff = new IndexDiff(db, Constants.HEAD, iterator);
			diff.diff();
			assertEquals(2, diff.getAssumeUnchanged().size());
			assertEquals(1, diff.getModified().size());
			assertEquals(0, diff.getChanged().size());
			assertTrue(diff.getAssumeUnchanged().contains("file2"));
			assertTrue(diff.getAssumeUnchanged().contains("file3"));
			assertTrue(diff.getModified().contains("file"));

			git.add().addFilepattern(".").call();

			iterator = new FileTreeIterator(db);
			diff = new IndexDiff(db, Constants.HEAD, iterator);
			diff.diff();
			assertEquals(2, diff.getAssumeUnchanged().size());
			assertEquals(0, diff.getModified().size());
			assertEquals(1, diff.getChanged().size());
			assertTrue(diff.getAssumeUnchanged().contains("file2"));
			assertTrue(diff.getAssumeUnchanged().contains("file3"));
			assertTrue(diff.getChanged().contains("file"));
			assertEquals(Collections.EMPTY_SET, diff.getUntrackedFolders());
		}
	}

	@Test
	public void testStageState() throws IOException {
		final int base = DirCacheEntry.STAGE_1;
		final int ours = DirCacheEntry.STAGE_2;
		final int theirs = DirCacheEntry.STAGE_3;
		verifyStageState(StageState.BOTH_DELETED, base);
		verifyStageState(StageState.DELETED_BY_THEM, ours, base);
		verifyStageState(StageState.DELETED_BY_US, base, theirs);
		verifyStageState(StageState.BOTH_MODIFIED, base, ours, theirs);
		verifyStageState(StageState.ADDED_BY_US, ours);
		verifyStageState(StageState.BOTH_ADDED, ours, theirs);
		verifyStageState(StageState.ADDED_BY_THEM, theirs);

		assertTrue(StageState.BOTH_DELETED.hasBase());
		assertFalse(StageState.BOTH_DELETED.hasOurs());
		assertFalse(StageState.BOTH_DELETED.hasTheirs());
		assertFalse(StageState.BOTH_ADDED.hasBase());
		assertTrue(StageState.BOTH_ADDED.hasOurs());
		assertTrue(StageState.BOTH_ADDED.hasTheirs());
	}

	@Test
	public void testStageState_mergeAndReset_bug() throws Exception {
		try (Git git = new Git(db)) {
			writeTrashFile("a", "content");
			git.add().addFilepattern("a").call();
			RevCommit initialCommit = git.commit().setMessage("initial commit")
					.call();

			// create branch and add a new file
			final String branchName = Constants.R_HEADS + "branch";
			createBranch(initialCommit, branchName);
			checkoutBranch(branchName);
			writeTrashFile("b", "second file content - branch");
			git.add().addFilepattern("b").call();
			RevCommit branchCommit = git.commit().setMessage("branch commit")
					.call();

			// checkout master and add the same new file
			checkoutBranch(Constants.R_HEADS + Constants.MASTER);
			writeTrashFile("b", "second file content - master");
			git.add().addFilepattern("b").call();
			git.commit().setMessage("master commit").call();

			// try and merge
			MergeResult result = git.merge().include(branchCommit).call();
			assertEquals(MergeStatus.CONFLICTING, result.getMergeStatus());

			FileTreeIterator iterator = new FileTreeIterator(db);
			IndexDiff diff = new IndexDiff(db, Constants.HEAD, iterator);
			diff.diff();

			assertTrue(diff.getChanged().isEmpty());
			assertTrue(diff.getAdded().isEmpty());
			assertTrue(diff.getRemoved().isEmpty());
			assertTrue(diff.getMissing().isEmpty());
			assertTrue(diff.getModified().isEmpty());
			assertEquals(1, diff.getConflicting().size());
			assertTrue(diff.getConflicting().contains("b"));
			assertEquals(StageState.BOTH_ADDED, diff.getConflictingStageStates()
					.get("b"));
			assertTrue(diff.getUntrackedFolders().isEmpty());

			// reset file b to its master state without altering the index
			writeTrashFile("b", "second file content - master");

			// we should have the same result
			iterator = new FileTreeIterator(db);
			diff = new IndexDiff(db, Constants.HEAD, iterator);
			diff.diff();

			assertTrue(diff.getChanged().isEmpty());
			assertTrue(diff.getAdded().isEmpty());
			assertTrue(diff.getRemoved().isEmpty());
			assertTrue(diff.getMissing().isEmpty());
			assertTrue(diff.getModified().isEmpty());
			assertEquals(1, diff.getConflicting().size());
			assertTrue(diff.getConflicting().contains("b"));
			assertEquals(StageState.BOTH_ADDED, diff.getConflictingStageStates()
					.get("b"));
			assertTrue(diff.getUntrackedFolders().isEmpty());
		}
	}

	@Test
	public void testStageState_simulated_bug() throws Exception {
		try (Git git = new Git(db)) {
			writeTrashFile("a", "content");
			git.add().addFilepattern("a").call();
			RevCommit initialCommit = git.commit().setMessage("initial commit")
					.call();

			// create branch and add a new file
			final String branchName = Constants.R_HEADS + "branch";
			createBranch(initialCommit, branchName);
			checkoutBranch(branchName);
			writeTrashFile("b", "second file content - branch");
			git.add().addFilepattern("b").call();
			git.commit().setMessage("branch commit")
					.call();

			// checkout master and add the same new file
			checkoutBranch(Constants.R_HEADS + Constants.MASTER);
			writeTrashFile("b", "second file content - master");
			git.add().addFilepattern("b").call();
			git.commit().setMessage("master commit").call();

			// Simulate a failed merge of branch into master
			DirCacheBuilder builder = db.lockDirCache().builder();
			DirCacheEntry entry = createEntry("a", FileMode.REGULAR_FILE, 0,
					"content");
			builder.add(entry);
			entry = createEntry("b", FileMode.REGULAR_FILE, 2,
					"second file content - master");
			builder.add(entry);
			entry = createEntry("b", FileMode.REGULAR_FILE, 3,
					"second file content - branch");
			builder.add(entry);
			builder.commit();

			FileTreeIterator iterator = new FileTreeIterator(db);
			IndexDiff diff = new IndexDiff(db, Constants.HEAD, iterator);
			diff.diff();

			assertTrue(diff.getChanged().isEmpty());
			assertTrue(diff.getAdded().isEmpty());
			assertTrue(diff.getRemoved().isEmpty());
			assertTrue(diff.getMissing().isEmpty());
			assertTrue(diff.getModified().isEmpty());
			assertEquals(1, diff.getConflicting().size());
			assertTrue(diff.getConflicting().contains("b"));
			assertEquals(StageState.BOTH_ADDED, diff.getConflictingStageStates()
					.get("b"));
			assertTrue(diff.getUntrackedFolders().isEmpty());
		}
	}

	@Test
	public void testAutoCRLFInput() throws Exception {
		try (Git git = new Git(db)) {
			FileBasedConfig config = db.getConfig();

			// Make sure core.autocrlf is false before adding
			config.setEnum(ConfigConstants.CONFIG_CORE_SECTION, null,
					ConfigConstants.CONFIG_KEY_AUTOCRLF, AutoCRLF.FALSE);
			config.save();

			// File is already in repository with CRLF
			writeTrashFile("crlf.txt", "this\r\ncontains\r\ncrlf\r\n");
			git.add().addFilepattern("crlf.txt").call();
			git.commit().setMessage("Add crlf.txt").call();

			// Now set core.autocrlf to input
			config.setEnum(ConfigConstants.CONFIG_CORE_SECTION, null,
					ConfigConstants.CONFIG_KEY_AUTOCRLF, AutoCRLF.INPUT);
			config.save();

			FileTreeIterator iterator = new FileTreeIterator(db);
			IndexDiff diff = new IndexDiff(db, Constants.HEAD, iterator);
			diff.diff();

			assertTrue(
					"Expected no modified files, but there were: "
							+ diff.getModified(), diff.getModified().isEmpty());
		}
	}

	private void verifyStageState(StageState expected, int... stages)
			throws IOException {
		DirCacheBuilder builder = db.lockDirCache().builder();
		for (int stage : stages) {
			DirCacheEntry entry = createEntry("a", FileMode.REGULAR_FILE,
					stage, "content");
			builder.add(entry);
		}
		builder.commit();

		IndexDiff diff = new IndexDiff(db, Constants.HEAD,
				new FileTreeIterator(db));
		diff.diff();

		assertEquals(
				"Conflict for entries in stages " + Arrays.toString(stages),
				expected, diff.getConflictingStageStates().get("a"));
	}

	private void removeFromIndex(String path) throws IOException {
		final DirCache dirc = db.lockDirCache();
		final DirCacheEditor edit = dirc.editor();
		edit.add(new DirCacheEditor.DeletePath(path));
		if (!edit.commit())
			throw new IOException("could not commit");
	}

	private void assumeUnchanged(String path) throws IOException {
		final DirCache dirc = db.lockDirCache();
		final DirCacheEntry ent = dirc.getEntry(path);
		if (ent != null)
			ent.setAssumeValid(true);
		dirc.write();
		if (!dirc.commit())
			throw new IOException("could not commit");
	}

}
