/*
 * Copyright (C) 2010, Christian Halstrick <christian.halstrick@sap.com>
 * 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.api;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeFalse;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;

import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.api.errors.JGitInternalException;
import org.eclipse.jgit.api.errors.NoMessageException;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.junit.RepositoryTestCase;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.ReflogReader;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.FileUtils;
import org.eclipse.jgit.util.RawParseUtils;
import org.junit.Test;

/**
 * Testing the git commit and log commands
 */
public class CommitAndLogCommandTest extends RepositoryTestCase {
	@Test
	public void testSomeCommits() throws JGitInternalException, IOException,
			GitAPIException {

		// do 4 commits
		try (Git git = new Git(db)) {
			git.commit().setMessage("initial commit").call();
			git.commit().setMessage("second commit").setCommitter(committer).call();
			git.commit().setMessage("third commit").setAuthor(author).call();
			git.commit().setMessage("fourth commit").setAuthor(author)
					.setCommitter(committer).call();
			Iterable<RevCommit> commits = git.log().call();

			// check that all commits came in correctly
			PersonIdent defaultCommitter = new PersonIdent(db);
			PersonIdent expectedAuthors[] = new PersonIdent[] { defaultCommitter,
					committer, author, author };
			PersonIdent expectedCommitters[] = new PersonIdent[] {
					defaultCommitter, committer, defaultCommitter, committer };
			String expectedMessages[] = new String[] { "initial commit",
					"second commit", "third commit", "fourth commit" };
			int l = expectedAuthors.length - 1;
			for (RevCommit c : commits) {
				assertEquals(expectedAuthors[l].getName(), c.getAuthorIdent()
						.getName());
				assertEquals(expectedCommitters[l].getName(), c.getCommitterIdent()
						.getName());
				assertEquals(c.getFullMessage(), expectedMessages[l]);
				l--;
			}
			assertEquals(l, -1);
			ReflogReader reader = db.getReflogReader(Constants.HEAD);
			assertTrue(reader.getLastEntry().getComment().startsWith("commit:"));
			reader = db.getReflogReader(db.getBranch());
			assertTrue(reader.getLastEntry().getComment().startsWith("commit:"));
		}
	}

	@Test
	public void testLogWithFilter() throws IOException, JGitInternalException,
			GitAPIException {

		try (Git git = new Git(db)) {
			// create first file
			File file = new File(db.getWorkTree(), "a.txt");
			FileUtils.createNewFile(file);
			PrintWriter writer = new PrintWriter(file);
			writer.print("content1");
			writer.close();

			// First commit - a.txt file
			git.add().addFilepattern("a.txt").call();
			git.commit().setMessage("commit1").setCommitter(committer).call();

			// create second file
			file = new File(db.getWorkTree(), "b.txt");
			FileUtils.createNewFile(file);
			writer = new PrintWriter(file);
			writer.print("content2");
			writer.close();

			// Second commit - b.txt file
			git.add().addFilepattern("b.txt").call();
			git.commit().setMessage("commit2").setCommitter(committer).call();

			// First log - a.txt filter
			int count = 0;
			for (RevCommit c : git.log().addPath("a.txt").call()) {
				assertEquals("commit1", c.getFullMessage());
				count++;
			}
			assertEquals(1, count);

			// Second log - b.txt filter
			count = 0;
			for (RevCommit c : git.log().addPath("b.txt").call()) {
				assertEquals("commit2", c.getFullMessage());
				count++;
			}
			assertEquals(1, count);

			// Third log - without filter
			count = 0;
			for (RevCommit c : git.log().call()) {
				assertEquals(committer, c.getCommitterIdent());
				count++;
			}
			assertEquals(2, count);
		}
	}

	// try to do a commit without specifying a message. Should fail!
	@Test
	public void testWrongParams() throws GitAPIException {
		try (Git git = new Git(db)) {
			git.commit().setAuthor(author).call();
			fail("Didn't get the expected exception");
		} catch (NoMessageException e) {
			// expected
		}
	}

	// try to work with Commands after command has been invoked. Should throw
	// exceptions
	@Test
	public void testMultipleInvocations() throws GitAPIException {
		try (Git git = new Git(db)) {
			CommitCommand commitCmd = git.commit();
			commitCmd.setMessage("initial commit").call();
			try {
				// check that setters can't be called after invocation
				commitCmd.setAuthor(author);
				fail("didn't catch the expected exception");
			} catch (IllegalStateException e) {
				// expected
			}
			LogCommand logCmd = git.log();
			logCmd.call();
			try {
				// check that call can't be called twice
				logCmd.call();
				fail("didn't catch the expected exception");
			} catch (IllegalStateException e) {
				// expected
			}
		}
	}

	@Test
	public void testMergeEmptyBranches() throws IOException,
			JGitInternalException, GitAPIException {
		try (Git git = new Git(db)) {
			git.commit().setMessage("initial commit").call();
			RefUpdate r = db.updateRef("refs/heads/side");
			r.setNewObjectId(db.resolve(Constants.HEAD));
			assertEquals(r.forceUpdate(), RefUpdate.Result.NEW);
			RevCommit second = git.commit().setMessage("second commit").setCommitter(committer).call();
			db.updateRef(Constants.HEAD).link("refs/heads/side");
			RevCommit firstSide = git.commit().setMessage("first side commit").setAuthor(author).call();

			write(new File(db.getDirectory(), Constants.MERGE_HEAD), ObjectId
					.toString(db.resolve("refs/heads/master")));
			write(new File(db.getDirectory(), Constants.MERGE_MSG), "merging");

			RevCommit commit = git.commit().call();
			RevCommit[] parents = commit.getParents();
			assertEquals(parents[0], firstSide);
			assertEquals(parents[1], second);
			assertEquals(2, parents.length);
		}
	}

	@Test
	public void testAddUnstagedChanges() throws IOException,
			JGitInternalException, GitAPIException {
		File file = new File(db.getWorkTree(), "a.txt");
		FileUtils.createNewFile(file);
		PrintWriter writer = new PrintWriter(file);
		writer.print("content");
		writer.close();

		try (Git git = new Git(db)) {
			git.add().addFilepattern("a.txt").call();
			RevCommit commit = git.commit().setMessage("initial commit").call();
			TreeWalk tw = TreeWalk.forPath(db, "a.txt", commit.getTree());
			assertEquals("6b584e8ece562ebffc15d38808cd6b98fc3d97ea",
					tw.getObjectId(0).getName());

			writer = new PrintWriter(file);
			writer.print("content2");
			writer.close();
			commit = git.commit().setMessage("second commit").call();
			tw = TreeWalk.forPath(db, "a.txt", commit.getTree());
			assertEquals("6b584e8ece562ebffc15d38808cd6b98fc3d97ea",
					tw.getObjectId(0).getName());

			commit = git.commit().setAll(true).setMessage("third commit")
					.setAll(true).call();
			tw = TreeWalk.forPath(db, "a.txt", commit.getTree());
			assertEquals("db00fd65b218578127ea51f3dffac701f12f486a",
					tw.getObjectId(0).getName());
		}
	}

	@Test
	public void testModeChange() throws IOException, GitAPIException {
		assumeFalse(System.getProperty("os.name").startsWith("Windows"));// SKIP
		try (Git git = new Git(db)) {
			// create file
			File file = new File(db.getWorkTree(), "a.txt");
			FileUtils.createNewFile(file);
			PrintWriter writer = new PrintWriter(file);
			writer.print("content1");
			writer.close();

			// First commit - a.txt file
			git.add().addFilepattern("a.txt").call();
			git.commit().setMessage("commit1").setCommitter(committer).call();

			// pure mode change should be committable
			FS fs = db.getFS();
			fs.setExecute(file, true);
			git.add().addFilepattern("a.txt").call();
			git.commit().setMessage("mode change").setCommitter(committer).call();

			// pure mode change should be committable with -o option
			fs.setExecute(file, false);
			git.add().addFilepattern("a.txt").call();
			git.commit().setMessage("mode change").setCommitter(committer)
					.setOnly("a.txt").call();
		}
	}

	@Test
	public void testCommitRange() throws GitAPIException,
			JGitInternalException, MissingObjectException,
			IncorrectObjectTypeException {
		// do 4 commits and set the range to the second and fourth one
		try (Git git = new Git(db)) {
			git.commit().setMessage("first commit").call();
			RevCommit second = git.commit().setMessage("second commit")
					.setCommitter(committer).call();
			git.commit().setMessage("third commit").setAuthor(author).call();
			RevCommit last = git.commit().setMessage("fourth commit").setAuthor(
					author)
					.setCommitter(committer).call();
			Iterable<RevCommit> commits = git.log().addRange(second.getId(),
					last.getId()).call();

			// check that we have the third and fourth commit
			PersonIdent defaultCommitter = new PersonIdent(db);
			PersonIdent expectedAuthors[] = new PersonIdent[] { author, author };
			PersonIdent expectedCommitters[] = new PersonIdent[] {
					defaultCommitter, committer };
			String expectedMessages[] = new String[] { "third commit",
					"fourth commit" };
			int l = expectedAuthors.length - 1;
			for (RevCommit c : commits) {
				assertEquals(expectedAuthors[l].getName(), c.getAuthorIdent()
						.getName());
				assertEquals(expectedCommitters[l].getName(), c.getCommitterIdent()
						.getName());
				assertEquals(c.getFullMessage(), expectedMessages[l]);
				l--;
			}
			assertEquals(l, -1);
		}
	}

	@Test
	public void testCommitAmend() throws JGitInternalException, IOException,
			GitAPIException {
		try (Git git = new Git(db)) {
			git.commit().setMessage("first comit").call(); // typo
			git.commit().setAmend(true).setMessage("first commit").call();

			Iterable<RevCommit> commits = git.log().call();
			int c = 0;
			for (RevCommit commit : commits) {
				assertEquals("first commit", commit.getFullMessage());
				c++;
			}
			assertEquals(1, c);
			ReflogReader reader = db.getReflogReader(Constants.HEAD);
			assertTrue(reader.getLastEntry().getComment()
					.startsWith("commit (amend):"));
			reader = db.getReflogReader(db.getBranch());
			assertTrue(reader.getLastEntry().getComment()
					.startsWith("commit (amend):"));
		}
	}

	@Test
	public void testInsertChangeId() throws JGitInternalException,
			GitAPIException {
		try (Git git = new Git(db)) {
			String messageHeader = "Some header line\n\nSome detail explanation\n";
			String changeIdTemplate = "\nChange-Id: I"
					+ ObjectId.zeroId().getName() + "\n";
			String messageFooter = "Some foooter lines\nAnother footer line\n";
			RevCommit commit = git.commit().setMessage(
					messageHeader + messageFooter)
					.setInsertChangeId(true).call();
			// we should find a real change id (at the end of the file)
			byte[] chars = commit.getFullMessage().getBytes();
			int lastLineBegin = RawParseUtils.prevLF(chars, chars.length - 2);
			String lastLine = RawParseUtils.decode(chars, lastLineBegin + 1,
					chars.length);
			assertTrue(lastLine.contains("Change-Id:"));
			assertFalse(lastLine.contains(
					"Change-Id: I" + ObjectId.zeroId().getName()));

			commit = git.commit().setMessage(
					messageHeader + changeIdTemplate + messageFooter)
					.setInsertChangeId(true).call();
			// we should find a real change id (in the line as dictated by the
			// template)
			chars = commit.getFullMessage().getBytes();
			int lineStart = 0;
			int lineEnd = 0;
			for (int i = 0; i < 4; i++) {
				lineStart = RawParseUtils.nextLF(chars, lineStart);
			}
			lineEnd = RawParseUtils.nextLF(chars, lineStart);

			String line = RawParseUtils.decode(chars, lineStart, lineEnd);

			assertTrue(line.contains("Change-Id:"));
			assertFalse(line.contains(
					"Change-Id: I" + ObjectId.zeroId().getName()));

			commit = git.commit().setMessage(
					messageHeader + changeIdTemplate + messageFooter)
					.setInsertChangeId(false).call();
			// we should find the untouched template
			chars = commit.getFullMessage().getBytes();
			lineStart = 0;
			lineEnd = 0;
			for (int i = 0; i < 4; i++) {
				lineStart = RawParseUtils.nextLF(chars, lineStart);
			}
			lineEnd = RawParseUtils.nextLF(chars, lineStart);

			line = RawParseUtils.decode(chars, lineStart, lineEnd);

			assertTrue(commit.getFullMessage().contains(
					"Change-Id: I" + ObjectId.zeroId().getName()));
		}
	}
}
