/*
 * Copyright (C) 2017 Thomas Wolf <thomas.wolf@paranor.ch>
 * 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.attributes;

import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;

import org.eclipse.jgit.junit.RepositoryTestCase;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.StoredConfig;
import org.eclipse.jgit.treewalk.FileTreeIterator;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.jgit.treewalk.filter.NotIgnoredFilter;
import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.FS.ExecutionResult;
import org.eclipse.jgit.util.RawParseUtils;
import org.eclipse.jgit.util.TemporaryBuffer;
import org.junit.Before;
import org.junit.Test;

/**
 * Tests that verify that the attributes of files in a repository are the same
 * in JGit and in C-git.
 */
public class CGitAttributesTest extends RepositoryTestCase {

	@Before
	public void initRepo() throws IOException {
		// Because we run C-git, we must ensure that global or user exclude
		// files cannot influence the tests. So we set core.excludesFile to an
		// empty file inside the repository.
		StoredConfig config = db.getConfig();
		File fakeUserGitignore = writeTrashFile(".fake_user_gitignore", "");
		config.setString("core", null, "excludesFile",
				fakeUserGitignore.getAbsolutePath());
		// Disable case-insensitivity -- JGit doesn't handle that yet.
		config.setBoolean("core", null, "ignoreCase", false);
		// And try to switch off the global attributes file, too.
		config.setString("core", null, "attributesFile",
				fakeUserGitignore.getAbsolutePath());
		config.save();
	}

	private void createFiles(String... paths) throws IOException {
		for (String path : paths) {
			writeTrashFile(path, "x");
		}
	}

	private String toString(TemporaryBuffer b) throws IOException {
		return RawParseUtils.decode(b.toByteArray());
	}

	private Attribute fromString(String key, String value) {
		if ("set".equals(value)) {
			return new Attribute(key, Attribute.State.SET);
		}
		if ("unset".equals(value)) {
			return new Attribute(key, Attribute.State.UNSET);
		}
		if ("unspecified".equals(value)) {
			return new Attribute(key, Attribute.State.UNSPECIFIED);
		}
		return new Attribute(key, value);
	}

	private LinkedHashMap<String, Attributes> cgitAttributes(
			Set<String> allFiles) throws Exception {
		FS fs = db.getFS();
		StringBuilder input = new StringBuilder();
		for (String filename : allFiles) {
			input.append(filename).append('\n');
		}
		ProcessBuilder builder = fs.runInShell("git",
				new String[] { "check-attr", "--stdin", "--all" });
		builder.directory(db.getWorkTree());
		builder.environment().put("HOME", fs.userHome().getAbsolutePath());
		ExecutionResult result = fs.execute(builder, new ByteArrayInputStream(
				input.toString().getBytes(Constants.CHARSET)));
		String errorOut = toString(result.getStderr());
		assertEquals("External git failed", "exit 0\n",
				"exit " + result.getRc() + '\n' + errorOut);
		LinkedHashMap<String, Attributes> map = new LinkedHashMap<>();
		try (BufferedReader r = new BufferedReader(new InputStreamReader(
				new BufferedInputStream(result.getStdout().openInputStream()),
				Constants.CHARSET))) {
			r.lines().forEach(line -> {
				// Parse the line and add to result map
				int start = 0;
				int i = line.indexOf(':');
				String path = line.substring(0, i).trim();
				start = i + 1;
				i = line.indexOf(':', start);
				String key = line.substring(start, i).trim();
				String value = line.substring(i + 1).trim();
				Attribute attr = fromString(key, value);
				Attributes attrs = map.get(path);
				if (attrs == null) {
					attrs = new Attributes(attr);
					map.put(path, attrs);
				} else {
					attrs.put(attr);
				}
			});
		}
		return map;
	}

	private LinkedHashMap<String, Attributes> jgitAttributes()
			throws IOException {
		// Do a tree walk and return a list of all files and directories with
		// their attributes
		LinkedHashMap<String, Attributes> result = new LinkedHashMap<>();
		try (TreeWalk walk = new TreeWalk(db)) {
			walk.addTree(new FileTreeIterator(db));
			walk.setFilter(new NotIgnoredFilter(0));
			while (walk.next()) {
				String path = walk.getPathString();
				if (walk.isSubtree() && !path.endsWith("/")) {
					// git check-attr expects directory paths to end with a
					// slash
					path += '/';
				}
				Attributes attrs = walk.getAttributes();
				if (attrs != null && !attrs.isEmpty()) {
					result.put(path, attrs);
				} else {
					result.put(path, null);
				}
				if (walk.isSubtree()) {
					walk.enterSubtree();
				}
			}
		}
		return result;
	}

	private void assertSameAsCGit() throws Exception {
		LinkedHashMap<String, Attributes> jgit = jgitAttributes();
		LinkedHashMap<String, Attributes> cgit = cgitAttributes(jgit.keySet());
		// remove all without attributes
		Iterator<Map.Entry<String, Attributes>> iterator = jgit.entrySet()
				.iterator();
		while (iterator.hasNext()) {
			Map.Entry<String, Attributes> entry = iterator.next();
			if (entry.getValue() == null) {
				iterator.remove();
			}
		}
		assertArrayEquals("JGit attributes differ from C git",
				cgit.entrySet().toArray(), jgit.entrySet().toArray());
	}

	@Test
	public void testBug508568() throws Exception {
		createFiles("foo.xml/bar.jar", "sub/foo.xml/bar.jar");
		writeTrashFile(".gitattributes", "*.xml xml\n" + "*.jar jar\n");
		assertSameAsCGit();
	}

	@Test
	public void testRelativePath() throws Exception {
		createFiles("sub/foo.txt");
		writeTrashFile("sub/.gitattributes", "sub/** sub\n" + "*.txt txt\n");
		assertSameAsCGit();
	}

	@Test
	public void testRelativePaths() throws Exception {
		createFiles("sub/foo.txt", "sub/sub/bar", "foo/sub/a.txt",
				"foo/sub/bar/a.tmp");
		writeTrashFile(".gitattributes", "sub/** sub\n" + "*.txt txt\n");
		assertSameAsCGit();
	}

	@Test
	public void testNestedMatchNot() throws Exception {
		createFiles("foo.xml/bar.jar", "foo.xml/bar.xml", "sub/b.jar",
				"sub/b.xml");
		writeTrashFile("sub/.gitattributes", "*.xml xml\n" + "*.jar jar\n");
		assertSameAsCGit();
	}

	@Test
	public void testNestedMatch() throws Exception {
		// This is an interesting test. At the time of this writing, the
		// gitignore documentation says: "In other words, foo/ will match a
		// directory foo AND PATHS UNDERNEATH IT, but will not match a regular
		// file or a symbolic link foo". (Emphasis added.) And gitattributes is
		// supposed to follow the same rules. But the documentation appears to
		// lie: C-git will *not* apply the attribute "xml" to *any* files in
		// any subfolder "foo" here. It will only apply the "jar" attribute
		// to the three *.jar files.
		//
		// The point is probably that ignores are handled top-down, and once a
		// directory "foo" is matched (here: on paths "foo" and "sub/foo" by
		// pattern "foo/"), the directory is excluded and the gitignore
		// documentation also says: "It is not possible to re-include a file if
		// a parent directory of that file is excluded." So once the pattern
		// "foo/" has matched, it appears as if everything beneath would also be
		// matched.
		//
		// But not so for gitattributes! The foo/ rule only matches the
		// directory itself, but not anything beneath.
		createFiles("foo/bar.jar", "foo/bar.xml", "sub/b.jar", "sub/b.xml",
				"sub/foo/b.jar");
		writeTrashFile(".gitattributes",
				"foo/ xml\n" + "sub/foo/ sub\n" + "*.jar jar\n");
		assertSameAsCGit();
	}

	@Test
	public void testNestedMatchWithWildcard() throws Exception {
		// See above.
		createFiles("foo/bar.jar", "foo/bar.xml", "sub/b.jar", "sub/b.xml",
				"sub/foo/b.jar");
		writeTrashFile(".gitattributes",
				"**/foo/ xml\n" + "*/foo/ sub\n" + "*.jar jar\n");
		assertSameAsCGit();
	}

	@Test
	public void testNestedMatchRecursive() throws Exception {
		createFiles("foo/bar.jar", "foo/bar.xml", "sub/b.jar", "sub/b.xml",
				"sub/foo/b.jar");
		writeTrashFile(".gitattributes", "foo/** xml\n" + "*.jar jar\n");
		assertSameAsCGit();
	}

	@Test
	public void testStarMatchOnSlashNot() throws Exception {
		createFiles("sub/a.txt", "foo/sext", "foo/s.txt");
		writeTrashFile(".gitattributes", "s*xt bar");
		assertSameAsCGit();
	}

	@Test
	public void testPrefixMatchNot() throws Exception {
		createFiles("src/new/foo.txt");
		writeTrashFile(".gitattributes", "src/new bar\n");
		assertSameAsCGit();
	}

	@Test
	public void testComplexPathMatchNot() throws Exception {
		createFiles("src/new/foo.txt", "src/ndw");
		writeTrashFile(".gitattributes", "s[p-s]c/n[de]w bar\n");
		assertSameAsCGit();
	}

	@Test
	public void testStarPathMatchNot() throws Exception {
		createFiles("src/new/foo.txt", "src/ndw");
		writeTrashFile(".gitattributes", "src/* bar\n");
		assertSameAsCGit();
	}

	@Test
	public void testDirectoryMatchSubSimple() throws Exception {
		createFiles("src/new/foo.txt", "foo/src/new/foo.txt", "sub/src/new");
		writeTrashFile(".gitattributes", "src/new/ bar\n");
		assertSameAsCGit();
	}

	@Test
	public void testDirectoryMatchSubRecursive() throws Exception {
		createFiles("src/new/foo.txt", "foo/src/new/foo.txt", "sub/src/new");
		writeTrashFile(".gitattributes", "**/src/new/ bar\n");
		assertSameAsCGit();
	}

	@Test
	public void testDirectoryMatchSubRecursiveBacktrack() throws Exception {
		createFiles("src/new/foo.txt", "src/src/new/foo.txt");
		writeTrashFile(".gitattributes", "**/src/new/ bar\n");
		assertSameAsCGit();
	}

	@Test
	public void testDirectoryMatchSubRecursiveBacktrack2() throws Exception {
		createFiles("src/new/foo.txt", "src/src/new/foo.txt");
		writeTrashFile(".gitattributes", "**/**/src/new/ bar\n");
		assertSameAsCGit();
	}

	@Test
	public void testDirectoryMatchSubRecursiveBacktrack3() throws Exception {
		createFiles("src/new/src/new/foo.txt",
				"foo/src/new/bar/src/new/foo.txt");
		writeTrashFile(".gitattributes", "**/src/new/ bar\n");
		assertSameAsCGit();
	}

	@Test
	public void testDirectoryMatchSubRecursiveBacktrack4() throws Exception {
		createFiles("src/src/src/new/foo.txt",
				"foo/src/src/bar/src/new/foo.txt");
		writeTrashFile(".gitattributes", "**/src/ bar\n");
		assertSameAsCGit();
	}

	@Test
	public void testDirectoryMatchSubRecursiveBacktrack5() throws Exception {
		createFiles("x/a/a/b/foo.txt", "x/y/z/b/a/b/foo.txt",
				"x/y/a/a/a/a/b/foo.txt", "x/y/a/a/a/a/b/a/b/foo.txt");
		writeTrashFile(".gitattributes", "**/*/a/b bar\n");
		assertSameAsCGit();
	}

	@Test
	public void testDirectoryMatchSubRecursiveBacktrack6() throws Exception {
		createFiles("x/a/a/b/foo.txt", "x/y/a/b/a/b/foo.txt");
		writeTrashFile(".gitattributes", "**/*/**/a/b bar\n");
		assertSameAsCGit();
	}

	@Test
	public void testDirectoryMatchSubComplex() throws Exception {
		createFiles("src/new/foo.txt", "foo/src/new/foo.txt", "sub/src/new");
		writeTrashFile(".gitattributes", "s[rs]c/n*/ bar\n");
		assertSameAsCGit();
	}

	@Test
	public void testDirectoryMatch() throws Exception {
		createFiles("src/new/foo.txt", "foo/src/new/foo.txt", "sub/src/new");
		writeTrashFile(".gitattributes", "new/ bar\n");
		assertSameAsCGit();
	}

	@Test
	public void testBracketsInGroup() throws Exception {
		createFiles("[", "]", "[]", "][", "[[]", "[]]", "[[]]");
		writeTrashFile(".gitattributes", "[[]] bar1\n" + "[\\[]] bar2\n"
				+ "[[\\]] bar3\n" + "[\\[\\]] bar4\n");
		assertSameAsCGit();
	}
}
