/*
 * 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 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.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 {
		ObjectInserter inserter = db.newObjectInserter();
		final File f = new File(workdir, path);
		final ObjectId id = inserter.insert(Constants.OBJ_BLOB,
				IO.readFully(f));
		return new PathEdit(path) {
			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 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<String>(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<String>(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<String>(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<String>(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<String>(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<String>(Arrays.asList("src/org", "src/tst",
							"target")),
					diff.getUntrackedFolders());
		}
	}

	/**
	 * Test that ignored folders aren't listed as untracked
	 *
	 * @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<String>(Arrays.asList("src")),
					diff.getUntrackedFolders());

			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<String>(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");
	}

}
