/*
 * Copyright (C) 2008, 2017, Google Inc. and others
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Distribution License v. 1.0 which is available at
 * https://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

package org.eclipse.jgit.treewalk;

import static java.nio.charset.StandardCharsets.UTF_8;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeNoException;

import java.io.File;
import java.io.IOException;
import java.nio.file.InvalidPathException;
import java.security.MessageDigest;
import java.time.Instant;

import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.ResetCommand.ResetType;
import org.eclipse.jgit.dircache.DirCache;
import org.eclipse.jgit.dircache.DirCacheCheckout;
import org.eclipse.jgit.dircache.DirCacheEditor;
import org.eclipse.jgit.dircache.DirCacheEditor.PathEdit;
import org.eclipse.jgit.dircache.DirCacheEntry;
import org.eclipse.jgit.dircache.DirCacheIterator;
import org.eclipse.jgit.errors.CorruptObjectException;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.junit.JGitTestUtil;
import org.eclipse.jgit.junit.RepositoryTestCase;
import org.eclipse.jgit.lib.ConfigConstants;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.FileMode;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
import org.eclipse.jgit.treewalk.WorkingTreeIterator.MetadataDiff;
import org.eclipse.jgit.treewalk.filter.PathFilter;
import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.FileUtils;
import org.eclipse.jgit.util.RawParseUtils;
import org.junit.Before;
import org.junit.Test;

public class FileTreeIteratorTest extends RepositoryTestCase {
	private final String[] paths = { "a,", "a,b", "a/b", "a0b" };

	private Instant[] mtime;

	@Override
	@Before
	public void setUp() throws Exception {
		super.setUp();

		// We build the entries backwards so that on POSIX systems we
		// are likely to get the entries in the trash directory in the
		// opposite order of what they should be in for the iteration.
		// This should stress the sorting code better than doing it in
		// the correct order.
		//
		mtime = new Instant[paths.length];
		for (int i = paths.length - 1; i >= 0; i--) {
			final String s = paths[i];
			writeTrashFile(s, s);
			mtime[i] = db.getFS().lastModifiedInstant(new File(trash, s));
		}
	}

	@Test
	public void testGetEntryContentLength() throws Exception {
		final FileTreeIterator fti = new FileTreeIterator(db);
		fti.next(1);
		assertEquals(3, fti.getEntryContentLength());
		fti.back(1);
		assertEquals(2, fti.getEntryContentLength());
		fti.next(1);
		assertEquals(3, fti.getEntryContentLength());
		fti.reset();
		assertEquals(2, fti.getEntryContentLength());
	}

	@Test
	public void testEmptyIfRootIsFile() throws Exception {
		final File r = new File(trash, paths[0]);
		assertTrue(r.isFile());
		final FileTreeIterator fti = new FileTreeIterator(r, db.getFS(),
				db.getConfig().get(WorkingTreeOptions.KEY));
		assertTrue(fti.first());
		assertTrue(fti.eof());
	}

	@Test
	public void testEmptyIfRootDoesNotExist() throws Exception {
		final File r = new File(trash, "not-existing-file");
		assertFalse(r.exists());
		final FileTreeIterator fti = new FileTreeIterator(r, db.getFS(),
				db.getConfig().get(WorkingTreeOptions.KEY));
		assertTrue(fti.first());
		assertTrue(fti.eof());
	}

	@Test
	public void testEmptyIfRootIsEmpty() throws Exception {
		final File r = new File(trash, "not-existing-file");
		assertFalse(r.exists());
		FileUtils.mkdir(r);

		final FileTreeIterator fti = new FileTreeIterator(r, db.getFS(),
				db.getConfig().get(WorkingTreeOptions.KEY));
		assertTrue(fti.first());
		assertTrue(fti.eof());
	}

	@Test
	public void testEmptyIteratorOnEmptyDirectory() throws Exception {
		String nonExistingFileName = "not-existing-file";
		final File r = new File(trash, nonExistingFileName);
		assertFalse(r.exists());
		FileUtils.mkdir(r);

		final FileTreeIterator parent = new FileTreeIterator(db);

		while (!parent.getEntryPathString().equals(nonExistingFileName))
			parent.next(1);

		final FileTreeIterator childIter = new FileTreeIterator(parent, r,
				db.getFS());
		assertTrue(childIter.first());
		assertTrue(childIter.eof());

		String parentPath = parent.getEntryPathString();
		assertEquals(nonExistingFileName, parentPath);

		// must be "not-existing-file/", but getEntryPathString() was broken by
		// 445363 too
		String childPath = childIter.getEntryPathString();

		// in bug 445363 the iterator wrote garbage to the parent "path" field
		EmptyTreeIterator e = childIter.createEmptyTreeIterator();
		assertNotNull(e);

		// check if parent path is not overridden by empty iterator (bug 445363)
		// due bug 445363 this was "/ot-existing-file" instead of
		// "not-existing-file"
		assertEquals(parentPath, parent.getEntryPathString());
		assertEquals(parentPath + "/", childPath);
		assertEquals(parentPath + "/", childIter.getEntryPathString());
		assertEquals(childPath + "/", e.getEntryPathString());
	}

	@Test
	public void testSimpleIterate() throws Exception {
		final FileTreeIterator top = new FileTreeIterator(trash, db.getFS(),
				db.getConfig().get(WorkingTreeOptions.KEY));

		assertTrue(top.first());
		assertFalse(top.eof());
		assertEquals(FileMode.REGULAR_FILE.getBits(), top.mode);
		assertEquals(paths[0], nameOf(top));
		assertEquals(paths[0].length(), top.getEntryLength());
		assertEquals(mtime[0], top.getEntryLastModifiedInstant());

		top.next(1);
		assertFalse(top.first());
		assertFalse(top.eof());
		assertEquals(FileMode.REGULAR_FILE.getBits(), top.mode);
		assertEquals(paths[1], nameOf(top));
		assertEquals(paths[1].length(), top.getEntryLength());
		assertEquals(mtime[1], top.getEntryLastModifiedInstant());

		top.next(1);
		assertFalse(top.first());
		assertFalse(top.eof());
		assertEquals(FileMode.TREE.getBits(), top.mode);

		try (ObjectReader reader = db.newObjectReader()) {
			final AbstractTreeIterator sub = top.createSubtreeIterator(reader);
			assertTrue(sub instanceof FileTreeIterator);
			final FileTreeIterator subfti = (FileTreeIterator) sub;
			assertTrue(sub.first());
			assertFalse(sub.eof());
			assertEquals(paths[2], nameOf(sub));
			assertEquals(paths[2].length(), subfti.getEntryLength());
			assertEquals(mtime[2], subfti.getEntryLastModifiedInstant());

			sub.next(1);
			assertTrue(sub.eof());
			top.next(1);
			assertFalse(top.first());
			assertFalse(top.eof());
			assertEquals(FileMode.REGULAR_FILE.getBits(), top.mode);
			assertEquals(paths[3], nameOf(top));
			assertEquals(paths[3].length(), top.getEntryLength());
			assertEquals(mtime[3], top.getEntryLastModifiedInstant());

			top.next(1);
			assertTrue(top.eof());
		}
	}

	@Test
	public void testComputeFileObjectId() throws Exception {
		final FileTreeIterator top = new FileTreeIterator(trash, db.getFS(),
				db.getConfig().get(WorkingTreeOptions.KEY));

		final MessageDigest md = Constants.newMessageDigest();
		md.update(Constants.encodeASCII(Constants.TYPE_BLOB));
		md.update((byte) ' ');
		md.update(Constants.encodeASCII(paths[0].length()));
		md.update((byte) 0);
		md.update(Constants.encode(paths[0]));
		final ObjectId expect = ObjectId.fromRaw(md.digest());

		assertEquals(expect, top.getEntryObjectId());

		// Verify it was cached by removing the file and getting it again.
		//
		FileUtils.delete(new File(trash, paths[0]));
		assertEquals(expect, top.getEntryObjectId());
	}

	@Test
	public void testDirCacheMatchingId() throws Exception {
		File f = writeTrashFile("file", "content");
		try (Git git = new Git(db)) {
			writeTrashFile("file", "content");
			fsTick(f);
			git.add().addFilepattern("file").call();
		}
		DirCacheEntry dce = db.readDirCache().getEntry("file");
		try (TreeWalk tw = new TreeWalk(db)) {
			FileTreeIterator fti = new FileTreeIterator(trash, db.getFS(),
					db.getConfig().get(WorkingTreeOptions.KEY));
			tw.addTree(fti);
			DirCacheIterator dci = new DirCacheIterator(db.readDirCache());
			tw.addTree(dci);
			fti.setDirCacheIterator(tw, 1);
			while (tw.next() && !tw.getPathString().equals("file")) {
				//
			}
			assertEquals(MetadataDiff.EQUAL, fti.compareMetadata(dce));
			ObjectId fromRaw = ObjectId.fromRaw(fti.idBuffer(), fti.idOffset());
			assertEquals("6b584e8ece562ebffc15d38808cd6b98fc3d97ea",
					fromRaw.getName());
			try (ObjectReader objectReader = db.newObjectReader()) {
				assertFalse(fti.isModified(dce, false, objectReader));
			}
		}
	}

	@Test
	public void testTreewalkEnterSubtree() throws Exception {
		try (Git git = new Git(db); TreeWalk tw = new TreeWalk(db)) {
			writeTrashFile("b/c", "b/c");
			writeTrashFile("z/.git", "gitdir: /tmp/somewhere");
			git.add().addFilepattern(".").call();
			git.rm().addFilepattern("a,").addFilepattern("a,b")
					.addFilepattern("a0b").call();
			assertEquals("[a/b, mode:100644][b/c, mode:100644][z, mode:160000]",
					indexState(0));
			FileUtils.delete(new File(db.getWorkTree(), "b"),
					FileUtils.RECURSIVE);

			tw.addTree(new DirCacheIterator(db.readDirCache()));
			tw.addTree(new FileTreeIterator(db));
			assertTrue(tw.next());
			assertEquals("a", tw.getPathString());
			tw.enterSubtree();
			tw.next();
			assertEquals("a/b", tw.getPathString());
			tw.next();
			assertEquals("b", tw.getPathString());
			tw.enterSubtree();
			tw.next();
			assertEquals("b/c", tw.getPathString());
			assertNotNull(tw.getTree(0, AbstractTreeIterator.class));
			assertNotNull(tw.getTree(EmptyTreeIterator.class));
		}
	}

	@Test
	public void testIsModifiedSymlinkAsFile() throws Exception {
		writeTrashFile("symlink", "content");
		try (Git git = new Git(db)) {
			db.getConfig().setString(ConfigConstants.CONFIG_CORE_SECTION, null,
					ConfigConstants.CONFIG_KEY_SYMLINKS, "false");
			git.add().addFilepattern("symlink").call();
			git.commit().setMessage("commit").call();
		}

		// Modify previously committed DirCacheEntry and write it back to disk
		DirCacheEntry dce = db.readDirCache().getEntry("symlink");
		dce.setFileMode(FileMode.SYMLINK);
		try (ObjectReader objectReader = db.newObjectReader()) {
			DirCacheCheckout.checkoutEntry(db, dce, objectReader, false, null);

			FileTreeIterator fti = new FileTreeIterator(trash, db.getFS(),
					db.getConfig().get(WorkingTreeOptions.KEY));
			while (!fti.getEntryPathString().equals("symlink"))
				fti.next(1);
			assertFalse(fti.isModified(dce, false, objectReader));
		}
	}

	@Test
	public void testIsModifiedFileSmudged() throws Exception {
		File f = writeTrashFile("file", "content");
		FS fs = db.getFS();
		try (Git git = new Git(db)) {
			// The idea of this test is to check the smudged handling
			// Hopefully fsTick will make sure our entry gets smudged
			fsTick(f);
			writeTrashFile("file", "content");
			Instant lastModified = fs.lastModifiedInstant(f);
			git.add().addFilepattern("file").call();
			writeTrashFile("file", "conten2");
			fs.setLastModified(f.toPath(), lastModified);
			// We cannot trust this to go fast enough on
			// a system with less than one-second lastModified
			// resolution, so we force the index to have the
			// same timestamp as the file we look at.
			fs.setLastModified(db.getIndexFile().toPath(), lastModified);
		}
		DirCacheEntry dce = db.readDirCache().getEntry("file");
		FileTreeIterator fti = new FileTreeIterator(trash, db.getFS(), db
				.getConfig().get(WorkingTreeOptions.KEY));
		while (!fti.getEntryPathString().equals("file"))
			fti.next(1);
		// If the rounding trick does not work we could skip the compareMetaData
		// test and hope that we are usually testing the intended code path.
		assertEquals(MetadataDiff.SMUDGED, fti.compareMetadata(dce));
		try (ObjectReader objectReader = db.newObjectReader()) {
			assertTrue(fti.isModified(dce, false, objectReader));
		}
	}

	@Test
	public void submoduleHeadMatchesIndex() throws Exception {
		try (Git git = new Git(db);
				TreeWalk walk = new TreeWalk(db)) {
			writeTrashFile("file.txt", "content");
			git.add().addFilepattern("file.txt").call();
			final RevCommit id = git.commit().setMessage("create file").call();
			final String path = "sub";
			DirCache cache = db.lockDirCache();
			DirCacheEditor editor = cache.editor();
			editor.add(new PathEdit(path) {

				@Override
				public void apply(DirCacheEntry ent) {
					ent.setFileMode(FileMode.GITLINK);
					ent.setObjectId(id);
				}
			});
			editor.commit();

			Git.cloneRepository().setURI(db.getDirectory().toURI().toString())
					.setDirectory(new File(db.getWorkTree(), path)).call()
					.getRepository().close();

			DirCacheIterator indexIter = new DirCacheIterator(db.readDirCache());
			FileTreeIterator workTreeIter = new FileTreeIterator(db);
			walk.addTree(indexIter);
			walk.addTree(workTreeIter);
			walk.setFilter(PathFilter.create(path));

			assertTrue(walk.next());
			assertTrue(indexIter.idEqual(workTreeIter));
		}
	}

	@Test
	public void submoduleWithNoGitDirectory() throws Exception {
		try (Git git = new Git(db);
				TreeWalk walk = new TreeWalk(db)) {
			writeTrashFile("file.txt", "content");
			git.add().addFilepattern("file.txt").call();
			final RevCommit id = git.commit().setMessage("create file").call();
			final String path = "sub";
			DirCache cache = db.lockDirCache();
			DirCacheEditor editor = cache.editor();
			editor.add(new PathEdit(path) {

				@Override
				public void apply(DirCacheEntry ent) {
					ent.setFileMode(FileMode.GITLINK);
					ent.setObjectId(id);
				}
			});
			editor.commit();

			File submoduleRoot = new File(db.getWorkTree(), path);
			assertTrue(submoduleRoot.mkdir());
			assertTrue(new File(submoduleRoot, Constants.DOT_GIT).mkdir());

			DirCacheIterator indexIter = new DirCacheIterator(db.readDirCache());
			FileTreeIterator workTreeIter = new FileTreeIterator(db);
			walk.addTree(indexIter);
			walk.addTree(workTreeIter);
			walk.setFilter(PathFilter.create(path));

			assertTrue(walk.next());
			assertFalse(indexIter.idEqual(workTreeIter));
			assertEquals(ObjectId.zeroId(), workTreeIter.getEntryObjectId());
		}
	}

	@Test
	public void submoduleWithNoHead() throws Exception {
		try (Git git = new Git(db);
				TreeWalk walk = new TreeWalk(db)) {
			writeTrashFile("file.txt", "content");
			git.add().addFilepattern("file.txt").call();
			final RevCommit id = git.commit().setMessage("create file").call();
			final String path = "sub";
			DirCache cache = db.lockDirCache();
			DirCacheEditor editor = cache.editor();
			editor.add(new PathEdit(path) {

				@Override
				public void apply(DirCacheEntry ent) {
					ent.setFileMode(FileMode.GITLINK);
					ent.setObjectId(id);
				}
			});
			editor.commit();

			assertNotNull(Git.init().setDirectory(new File(db.getWorkTree(), path))
					.call().getRepository());

			DirCacheIterator indexIter = new DirCacheIterator(db.readDirCache());
			FileTreeIterator workTreeIter = new FileTreeIterator(db);
			walk.addTree(indexIter);
			walk.addTree(workTreeIter);
			walk.setFilter(PathFilter.create(path));

			assertTrue(walk.next());
			assertFalse(indexIter.idEqual(workTreeIter));
			assertEquals(ObjectId.zeroId(), workTreeIter.getEntryObjectId());
		}
	}

	@Test
	public void submoduleDirectoryIterator() throws Exception {
		try (Git git = new Git(db);
				TreeWalk walk = new TreeWalk(db)) {
			writeTrashFile("file.txt", "content");
			git.add().addFilepattern("file.txt").call();
			final RevCommit id = git.commit().setMessage("create file").call();
			final String path = "sub";
			DirCache cache = db.lockDirCache();
			DirCacheEditor editor = cache.editor();
			editor.add(new PathEdit(path) {

				@Override
				public void apply(DirCacheEntry ent) {
					ent.setFileMode(FileMode.GITLINK);
					ent.setObjectId(id);
				}
			});
			editor.commit();

			Git.cloneRepository().setURI(db.getDirectory().toURI().toString())
					.setDirectory(new File(db.getWorkTree(), path)).call()
					.getRepository().close();

			DirCacheIterator indexIter = new DirCacheIterator(db.readDirCache());
			FileTreeIterator workTreeIter = new FileTreeIterator(db.getWorkTree(),
					db.getFS(), db.getConfig().get(WorkingTreeOptions.KEY));
			walk.addTree(indexIter);
			walk.addTree(workTreeIter);
			walk.setFilter(PathFilter.create(path));

			assertTrue(walk.next());
			assertTrue(indexIter.idEqual(workTreeIter));
		}
	}

	@Test
	public void submoduleNestedWithHeadMatchingIndex() throws Exception {
		try (Git git = new Git(db);
				TreeWalk walk = new TreeWalk(db)) {
			writeTrashFile("file.txt", "content");
			git.add().addFilepattern("file.txt").call();
			final RevCommit id = git.commit().setMessage("create file").call();
			final String path = "sub/dir1/dir2";
			DirCache cache = db.lockDirCache();
			DirCacheEditor editor = cache.editor();
			editor.add(new PathEdit(path) {

				@Override
				public void apply(DirCacheEntry ent) {
					ent.setFileMode(FileMode.GITLINK);
					ent.setObjectId(id);
				}
			});
			editor.commit();

			Git.cloneRepository().setURI(db.getDirectory().toURI().toString())
					.setDirectory(new File(db.getWorkTree(), path)).call()
					.getRepository().close();

			DirCacheIterator indexIter = new DirCacheIterator(db.readDirCache());
			FileTreeIterator workTreeIter = new FileTreeIterator(db);
			walk.addTree(indexIter);
			walk.addTree(workTreeIter);
			walk.setFilter(PathFilter.create(path));

			assertTrue(walk.next());
			assertTrue(indexIter.idEqual(workTreeIter));
		}
	}

	@Test
	public void idOffset() throws Exception {
		try (Git git = new Git(db);
				TreeWalk tw = new TreeWalk(db)) {
			writeTrashFile("fileAinfsonly", "A");
			File fileBinindex = writeTrashFile("fileBinindex", "B");
			fsTick(fileBinindex);
			git.add().addFilepattern("fileBinindex").call();
			writeTrashFile("fileCinfsonly", "C");
			DirCacheIterator indexIter = new DirCacheIterator(db.readDirCache());
			FileTreeIterator workTreeIter = new FileTreeIterator(db);
			tw.addTree(indexIter);
			tw.addTree(workTreeIter);
			workTreeIter.setDirCacheIterator(tw, 0);
			assertEntry("d46c305e85b630558ee19cc47e73d2e5c8c64cdc", "a,", tw);
			assertEntry("58ee403f98538ec02409538b3f80adf610accdec", "a,b", tw);
			assertEntry("0000000000000000000000000000000000000000", "a", tw);
			assertEntry("b8d30ff397626f0f1d3538d66067edf865e201d6", "a0b", tw);
			// The reason for adding this test. Check that the id is correct for
			// mixed
			assertEntry("8c7e5a667f1b771847fe88c01c3de34413a1b220",
					"fileAinfsonly", tw);
			assertEntry("7371f47a6f8bd23a8fa1a8b2a9479cdd76380e54", "fileBinindex",
					tw);
			assertEntry("96d80cd6c4e7158dbebd0849f4fb7ce513e5828c",
					"fileCinfsonly", tw);
			assertFalse(tw.next());
		}
	}

	private final FileTreeIterator.FileModeStrategy NO_GITLINKS_STRATEGY = (
			File f, FS.Attributes attributes) -> {
		if (attributes.isSymbolicLink()) {
			return FileMode.SYMLINK;
		} else if (attributes.isDirectory()) {
			// NOTE: in the production DefaultFileModeStrategy, there is
			// a check here for a subdirectory called '.git', and if it
			// exists, we create a GITLINK instead of recursing into the
			// tree. In this custom strategy, we ignore nested git dirs
			// and treat all directories the same.
			return FileMode.TREE;
		} else if (attributes.isExecutable()) {
			return FileMode.EXECUTABLE_FILE;
		} else {
			return FileMode.REGULAR_FILE;
		}
	};

	private Repository createNestedRepo() throws IOException {
		File gitdir = createUniqueTestGitDir(false);
		FileRepositoryBuilder builder = new FileRepositoryBuilder();
		builder.setGitDir(gitdir);
		Repository nestedRepo = builder.build();
		nestedRepo.create();

		JGitTestUtil.writeTrashFile(nestedRepo, "sub", "a.txt", "content");

		File nestedRepoPath = new File(nestedRepo.getWorkTree(), "sub/nested");
		FileRepositoryBuilder nestedBuilder = new FileRepositoryBuilder();
		nestedBuilder.setWorkTree(nestedRepoPath);
		nestedBuilder.build().create();

		JGitTestUtil.writeTrashFile(nestedRepo, "sub/nested", "b.txt",
				"content b");

		return nestedRepo;
	}

	@Test
	public void testCustomFileModeStrategy() throws Exception {
		try (Repository nestedRepo = createNestedRepo();
				Git git = new Git(nestedRepo)) {
			// validate that our custom strategy is honored
			WorkingTreeIterator customIterator = new FileTreeIterator(
					nestedRepo, NO_GITLINKS_STRATEGY);
			git.add().setWorkingTreeIterator(customIterator).addFilepattern(".")
					.call();
			assertEquals(
					"[sub/a.txt, mode:100644, content:content]"
							+ "[sub/nested/b.txt, mode:100644, content:content b]",
					indexState(nestedRepo, CONTENT));
		}
	}

	@Test
	public void testCustomFileModeStrategyFromParentIterator() throws Exception {
		try (Repository nestedRepo = createNestedRepo();
				Git git = new Git(nestedRepo)) {
			FileTreeIterator customIterator = new FileTreeIterator(nestedRepo,
					NO_GITLINKS_STRATEGY);
			File r = new File(nestedRepo.getWorkTree(), "sub");

			// here we want to validate that if we create a new iterator using
			// the constructor that accepts a parent iterator, that the child
			// iterator correctly inherits the FileModeStrategy from the parent
			// iterator.
			FileTreeIterator childIterator = new FileTreeIterator(
					customIterator, r, nestedRepo.getFS());
			git.add().setWorkingTreeIterator(childIterator).addFilepattern(".")
					.call();
			assertEquals(
					"[sub/a.txt, mode:100644, content:content]"
							+ "[sub/nested/b.txt, mode:100644, content:content b]",
					indexState(nestedRepo, CONTENT));
		}
	}

	@Test
	public void testFileModeSymLinkIsNotATree() throws IOException {
		org.junit.Assume.assumeTrue(FS.DETECTED.supportsSymlinks());
		FS fs = db.getFS();
		// mål = target in swedish, just to get some unicode in here
		writeTrashFile("mål/data", "targetdata");
		File file = new File(trash, "länk");

		try {
			file.toPath();
		} catch (InvalidPathException e) {
			// When executing a test with LANG environment variable set to non
			// UTF-8 encoding, it seems that JRE cannot handle Unicode file
			// paths. This happens when this test is executed in Bazel as it
			// unsets LANG
			// (https://docs.bazel.build/versions/master/test-encyclopedia.html#initial-conditions).
			// Skip the test if the runtime cannot handle Unicode characters.
			assumeNoException(e);
		}

		fs.createSymLink(file, "mål");
		FileTreeIterator fti = new FileTreeIterator(db);
		assertFalse(fti.eof());
		while (!fti.getEntryPathString().equals("länk")) {
			fti.next(1);
		}
		assertEquals("länk", fti.getEntryPathString());
		assertEquals(FileMode.SYMLINK, fti.getEntryFileMode());
		fti.next(1);
		assertFalse(fti.eof());
		assertEquals("mål", fti.getEntryPathString());
		assertEquals(FileMode.TREE, fti.getEntryFileMode());
		fti.next(1);
		assertTrue(fti.eof());
	}

	@Test
	public void testSymlinkNotModifiedThoughNormalized() throws Exception {
		DirCache dc = db.lockDirCache();
		DirCacheEditor dce = dc.editor();
		final String UNNORMALIZED = "target/";
		final byte[] UNNORMALIZED_BYTES = Constants.encode(UNNORMALIZED);
		try (ObjectInserter oi = db.newObjectInserter()) {
			final ObjectId linkid = oi.insert(Constants.OBJ_BLOB,
					UNNORMALIZED_BYTES, 0, UNNORMALIZED_BYTES.length);
			dce.add(new DirCacheEditor.PathEdit("link") {
				@Override
				public void apply(DirCacheEntry ent) {
					ent.setFileMode(FileMode.SYMLINK);
					ent.setObjectId(linkid);
					ent.setLength(UNNORMALIZED_BYTES.length);
				}
			});
			assertTrue(dce.commit());
		}
		try (Git git = new Git(db)) {
			git.commit().setMessage("Adding link").call();
			git.reset().setMode(ResetType.HARD).call();
			DirCacheIterator dci = new DirCacheIterator(db.readDirCache());
			FileTreeIterator fti = new FileTreeIterator(db);

			// self-check
			while (!fti.getEntryPathString().equals("link")) {
				fti.next(1);
			}
			assertEquals("link", fti.getEntryPathString());
			assertEquals("link", dci.getEntryPathString());

			// test
			assertFalse(fti.isModified(dci.getDirCacheEntry(), true,
					db.newObjectReader()));
		}
	}

	/**
	 * Like #testSymlinkNotModifiedThoughNormalized but there is no
	 * normalization being done.
	 *
	 * @throws Exception
	 */
	@Test
	public void testSymlinkModifiedNotNormalized() throws Exception {
		DirCache dc = db.lockDirCache();
		DirCacheEditor dce = dc.editor();
		final String NORMALIZED = "target";
		final byte[] NORMALIZED_BYTES = Constants.encode(NORMALIZED);
		try (ObjectInserter oi = db.newObjectInserter()) {
			final ObjectId linkid = oi.insert(Constants.OBJ_BLOB,
					NORMALIZED_BYTES, 0, NORMALIZED_BYTES.length);
			dce.add(new DirCacheEditor.PathEdit("link") {
				@Override
				public void apply(DirCacheEntry ent) {
					ent.setFileMode(FileMode.SYMLINK);
					ent.setObjectId(linkid);
					ent.setLength(NORMALIZED_BYTES.length);
				}
			});
			assertTrue(dce.commit());
		}
		try (Git git = new Git(db)) {
			git.commit().setMessage("Adding link").call();
			git.reset().setMode(ResetType.HARD).call();
			DirCacheIterator dci = new DirCacheIterator(db.readDirCache());
			FileTreeIterator fti = new FileTreeIterator(db);

			// self-check
			while (!fti.getEntryPathString().equals("link")) {
				fti.next(1);
			}
			assertEquals("link", fti.getEntryPathString());
			assertEquals("link", dci.getEntryPathString());

			// test
			assertFalse(fti.isModified(dci.getDirCacheEntry(), true,
					db.newObjectReader()));
		}
	}

	/**
	 * Like #testSymlinkNotModifiedThoughNormalized but here the link is
	 * modified.
	 *
	 * @throws Exception
	 */
	@Test
	public void testSymlinkActuallyModified() throws Exception {
		org.junit.Assume.assumeTrue(FS.DETECTED.supportsSymlinks());
		final String NORMALIZED = "target";
		final byte[] NORMALIZED_BYTES = Constants.encode(NORMALIZED);
		try (ObjectInserter oi = db.newObjectInserter()) {
			final ObjectId linkid = oi.insert(Constants.OBJ_BLOB,
					NORMALIZED_BYTES, 0, NORMALIZED_BYTES.length);
			DirCache dc = db.lockDirCache();
			DirCacheEditor dce = dc.editor();
			dce.add(new DirCacheEditor.PathEdit("link") {
				@Override
				public void apply(DirCacheEntry ent) {
					ent.setFileMode(FileMode.SYMLINK);
					ent.setObjectId(linkid);
					ent.setLength(NORMALIZED_BYTES.length);
				}
			});
			assertTrue(dce.commit());
		}
		try (Git git = new Git(db)) {
			git.commit().setMessage("Adding link").call();
			git.reset().setMode(ResetType.HARD).call();

			FileUtils.delete(new File(trash, "link"), FileUtils.NONE);
			FS.DETECTED.createSymLink(new File(trash, "link"), "newtarget");
			DirCacheIterator dci = new DirCacheIterator(db.readDirCache());
			FileTreeIterator fti = new FileTreeIterator(db);

			// self-check
			while (!fti.getEntryPathString().equals("link")) {
				fti.next(1);
			}
			assertEquals("link", fti.getEntryPathString());
			assertEquals("link", dci.getEntryPathString());

			// test
			assertTrue(fti.isModified(dci.getDirCacheEntry(), true,
					db.newObjectReader()));
		}
	}

	private static void assertEntry(String sha1string, String path, TreeWalk tw)
			throws MissingObjectException, IncorrectObjectTypeException,
			CorruptObjectException, IOException {
		assertTrue(tw.next());
		assertEquals(path, tw.getPathString());
		assertEquals(sha1string, tw.getObjectId(1).getName() /* 1=filetree here */);
	}

	private static String nameOf(AbstractTreeIterator i) {
		return RawParseUtils.decode(UTF_8, i.path, 0, i.pathLen);
	}
}
