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

import static org.eclipse.jgit.api.CherryPickCommitMessageProvider.ORIGINAL;
import static org.eclipse.jgit.api.CherryPickCommitMessageProvider.ORIGINAL_WITH_REFERENCE;
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.Assert.fail;

import java.io.File;
import java.io.IOException;
import java.util.Iterator;

import org.eclipse.jgit.api.CherryPickResult.CherryPickStatus;
import org.eclipse.jgit.api.ResetCommand.ResetType;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.api.errors.JGitInternalException;
import org.eclipse.jgit.api.errors.MultipleParentsNotAllowedException;
import org.eclipse.jgit.dircache.DirCache;
import org.eclipse.jgit.events.ChangeRecorder;
import org.eclipse.jgit.events.ListenerHandle;
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.ReflogReader;
import org.eclipse.jgit.lib.RepositoryState;
import org.eclipse.jgit.merge.ContentMergeStrategy;
import org.eclipse.jgit.merge.MergeStrategy;
import org.eclipse.jgit.merge.ResolveMerger.MergeFailureReason;
import org.eclipse.jgit.revwalk.RevCommit;
import org.junit.Test;

/**
 * Test cherry-pick command
 */
public class CherryPickCommandTest extends RepositoryTestCase {
	@Test
	public void testCherryPick() throws IOException, JGitInternalException,
			GitAPIException {
		doTestCherryPick(false);
	}

	@Test
	public void testCherryPickNoCommit() throws IOException,
			JGitInternalException, GitAPIException {
		doTestCherryPick(true);
	}

	private void doTestCherryPick(boolean noCommit) throws IOException,
			JGitInternalException,
			GitAPIException {
		try (Git git = new Git(db)) {
			writeTrashFile("a", "first line\nsec. line\nthird line\n");
			git.add().addFilepattern("a").call();
			RevCommit firstCommit = git.commit().setMessage("create a").call();

			writeTrashFile("b", "content\n");
			git.add().addFilepattern("b").call();
			git.commit().setMessage("create b").call();

			writeTrashFile("a", "first line\nsec. line\nthird line\nfourth line\n");
			git.add().addFilepattern("a").call();
			git.commit().setMessage("enlarged a").call();

			writeTrashFile("a",
					"first line\nsecond line\nthird line\nfourth line\n");
			git.add().addFilepattern("a").call();
			RevCommit fixingA = git.commit().setMessage("fixed a").call();

			git.branchCreate().setName("side").setStartPoint(firstCommit).call();
			checkoutBranch("refs/heads/side");

			writeTrashFile("a", "first line\nsec. line\nthird line\nfeature++\n");
			git.add().addFilepattern("a").call();
			git.commit().setMessage("enhanced a").call();

			CherryPickResult pickResult = git.cherryPick().include(fixingA)
					.setNoCommit(noCommit).call();

			assertEquals(CherryPickStatus.OK, pickResult.getStatus());
			assertFalse(new File(db.getWorkTree(), "b").exists());
			checkFile(new File(db.getWorkTree(), "a"),
					"first line\nsecond line\nthird line\nfeature++\n");
			Iterator<RevCommit> history = git.log().call().iterator();
			if (!noCommit)
				assertEquals("fixed a", history.next().getFullMessage());
			assertEquals("enhanced a", history.next().getFullMessage());
			assertEquals("create a", history.next().getFullMessage());
			assertFalse(history.hasNext());
		}
	}

	@Test
	public void testSequentialCherryPick()
			throws IOException, JGitInternalException, GitAPIException {
		try (Git git = new Git(db)) {
			writeTrashFile("a", "first line\nsec. line\nthird line\n");
			git.add().addFilepattern("a").call();
			RevCommit firstCommit = git.commit().setMessage("create a").call();

			writeTrashFile("a",
					"first line\nsec. line\nthird line\nfourth line\n");
			git.add().addFilepattern("a").call();
			RevCommit enlargingA = git.commit().setMessage("enlarged a").call();

			writeTrashFile("a",
					"first line\nsecond line\nthird line\nfourth line\n");
			git.add().addFilepattern("a").call();
			RevCommit fixingA = git.commit().setMessage("fixed a").call();

			git.branchCreate().setName("side").setStartPoint(firstCommit)
					.call();
			checkoutBranch("refs/heads/side");

			writeTrashFile("b", "nothing to do with a");
			git.add().addFilepattern("b").call();
			git.commit().setMessage("create b").call();

			CherryPickResult result = git.cherryPick().include(enlargingA)
					.include(fixingA).call();
			assertEquals(CherryPickResult.CherryPickStatus.OK,
					result.getStatus());

			Iterator<RevCommit> history = git.log().call().iterator();
			assertEquals("fixed a", history.next().getFullMessage());
			assertEquals("enlarged a", history.next().getFullMessage());
			assertEquals("create b", history.next().getFullMessage());
			assertEquals("create a", history.next().getFullMessage());
			assertFalse(history.hasNext());
		}
	}

	@Test
	public void testRootCherryPick()
			throws IOException, JGitInternalException, GitAPIException {
		try (Git git = new Git(db)) {
			writeTrashFile("a", "a");
			writeTrashFile("b", "b");
			git.add().addFilepattern("a").addFilepattern("b").call();
			RevCommit firstCommit = git.commit().setMessage("Create a and b")
					.call();

			git.checkout().setOrphan(true).setName("orphan").call();
			git.rm().addFilepattern("a").addFilepattern("b").call();
			writeTrashFile("a", "a");
			git.add().addFilepattern("a").call();
			git.commit().setMessage("Orphan a").call();

			CherryPickResult result = git.cherryPick().include(firstCommit)
					.call();
			assertEquals(CherryPickResult.CherryPickStatus.OK,
					result.getStatus());

			Iterator<RevCommit> history = git.log().call().iterator();
			assertEquals("Create a and b", history.next().getFullMessage());
			assertEquals("Orphan a", history.next().getFullMessage());
			assertFalse(history.hasNext());
		}
	}

	@Test
	public void testCherryPickDirtyIndex() throws Exception {
		try (Git git = new Git(db)) {
			RevCommit sideCommit = prepareCherryPick(git);

			// modify and add file a
			writeTrashFile("a", "a(modified)");
			git.add().addFilepattern("a").call();
			// do not commit

			doCherryPickAndCheckResult(git, sideCommit,
					MergeFailureReason.DIRTY_INDEX);
		}
	}

	@Test
	public void testCherryPickDirtyWorktree() throws Exception {
		try (Git git = new Git(db)) {
			RevCommit sideCommit = prepareCherryPick(git);

			// modify file a
			writeTrashFile("a", "a(modified)");
			// do not add and commit

			doCherryPickAndCheckResult(git, sideCommit,
					MergeFailureReason.DIRTY_WORKTREE);
		}
	}

	@Test
	public void testCherryPickConflictResolution() throws Exception {
		try (Git git = new Git(db)) {
			RevCommit sideCommit = prepareCherryPick(git);

			CherryPickResult result = git.cherryPick().include(sideCommit.getId())
					.call();

			assertEquals(CherryPickStatus.CONFLICTING, result.getStatus());
			assertTrue(new File(db.getDirectory(), Constants.MERGE_MSG).exists());
			assertEquals("side\n\n# Conflicts:\n#\ta\n",
					db.readMergeCommitMsg());
			assertTrue(new File(db.getDirectory(), Constants.CHERRY_PICK_HEAD)
					.exists());
			assertEquals(sideCommit.getId(), db.readCherryPickHead());
			assertEquals(RepositoryState.CHERRY_PICKING, db.getRepositoryState());

			// Resolve
			writeTrashFile("a", "a");
			git.add().addFilepattern("a").call();

			assertEquals(RepositoryState.CHERRY_PICKING_RESOLVED,
					db.getRepositoryState());

			git.commit().setOnly("a").setMessage("resolve").call();

			assertEquals(RepositoryState.SAFE, db.getRepositoryState());
		}
	}

	@Test
	public void testCherryPickConflictResolutionNoCommit() throws Exception {
		Git git = new Git(db);
		RevCommit sideCommit = prepareCherryPick(git);

		CherryPickResult result = git.cherryPick().include(sideCommit.getId())
				.setNoCommit(true).call();

		assertEquals(CherryPickStatus.CONFLICTING, result.getStatus());
		assertTrue(db.readDirCache().hasUnmergedPaths());
		String expected = "<<<<<<< master\na(master)\n=======\na(side)\n>>>>>>> 527460a side\n";
		assertEquals(expected, read("a"));
		assertTrue(new File(db.getDirectory(), Constants.MERGE_MSG).exists());
		assertEquals("side\n\n# Conflicts:\n#\ta\n", db.readMergeCommitMsg());
		assertFalse(new File(db.getDirectory(), Constants.CHERRY_PICK_HEAD)
				.exists());
		assertEquals(RepositoryState.SAFE, db.getRepositoryState());

		// Resolve
		writeTrashFile("a", "a");
		git.add().addFilepattern("a").call();

		assertEquals(RepositoryState.SAFE, db.getRepositoryState());

		git.commit().setOnly("a").setMessage("resolve").call();

		assertEquals(RepositoryState.SAFE, db.getRepositoryState());
	}

	@Test
	public void testCherryPickConflictReset() throws Exception {
		try (Git git = new Git(db)) {
			RevCommit sideCommit = prepareCherryPick(git);

			CherryPickResult result = git.cherryPick().include(sideCommit.getId())
					.call();

			assertEquals(CherryPickStatus.CONFLICTING, result.getStatus());
			assertEquals(RepositoryState.CHERRY_PICKING, db.getRepositoryState());
			assertTrue(new File(db.getDirectory(), Constants.CHERRY_PICK_HEAD)
					.exists());

			git.reset().setMode(ResetType.MIXED).setRef("HEAD").call();

			assertEquals(RepositoryState.SAFE, db.getRepositoryState());
			assertFalse(new File(db.getDirectory(), Constants.CHERRY_PICK_HEAD)
					.exists());
		}
	}

	@Test
	public void testCherryPickOverExecutableChangeOnNonExectuableFileSystem()
			throws Exception {
		try (Git git = new Git(db)) {
			File file = writeTrashFile("test.txt", "a");
			assertNotNull(git.add().addFilepattern("test.txt").call());
			assertNotNull(git.commit().setMessage("commit1").call());

			assertNotNull(git.checkout().setCreateBranch(true).setName("a").call());

			writeTrashFile("test.txt", "b");
			assertNotNull(git.add().addFilepattern("test.txt").call());
			RevCommit commit2 = git.commit().setMessage("commit2").call();
			assertNotNull(commit2);

			assertNotNull(git.checkout().setName(Constants.MASTER).call());

			DirCache cache = db.lockDirCache();
			cache.getEntry("test.txt").setFileMode(FileMode.EXECUTABLE_FILE);
			cache.write();
			assertTrue(cache.commit());
			cache.unlock();

			assertNotNull(git.commit().setMessage("commit3").call());

			db.getFS().setExecute(file, false);
			git.getRepository()
					.getConfig()
					.setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null,
							ConfigConstants.CONFIG_KEY_FILEMODE, false);

			CherryPickResult result = git.cherryPick().include(commit2).call();
			assertNotNull(result);
			assertEquals(CherryPickStatus.OK, result.getStatus());
		}
	}

	@Test
	public void testCherryPickOurs() throws Exception {
		try (Git git = new Git(db)) {
			RevCommit sideCommit = prepareCherryPick(git);

			CherryPickResult result = git.cherryPick()
					.include(sideCommit.getId())
					.setStrategy(MergeStrategy.OURS)
					.call();
			assertEquals(CherryPickStatus.OK, result.getStatus());

			String expected = "a(master)";
			checkFile(new File(db.getWorkTree(), "a"), expected);
		}
	}

	@Test
	public void testCherryPickTheirs() throws Exception {
		try (Git git = new Git(db)) {
			RevCommit sideCommit = prepareCherryPick(git);

			CherryPickResult result = git.cherryPick()
					.include(sideCommit.getId())
					.setStrategy(MergeStrategy.THEIRS)
					.call();
			assertEquals(CherryPickStatus.OK, result.getStatus());

			String expected = "a(side)";
			checkFile(new File(db.getWorkTree(), "a"), expected);
		}
	}

	@Test
	public void testCherryPickXours() throws Exception {
		try (Git git = new Git(db)) {
			RevCommit sideCommit = prepareCherryPickStrategyOption(git);

			CherryPickResult result = git.cherryPick()
					.include(sideCommit.getId())
					.setContentMergeStrategy(ContentMergeStrategy.OURS)
					.call();
			assertEquals(CherryPickStatus.OK, result.getStatus());

			String expected = "a\nmaster\nc\nd\n";
			checkFile(new File(db.getWorkTree(), "a"), expected);
		}
	}

	@Test
	public void testCherryPickXtheirs() throws Exception {
		try (Git git = new Git(db)) {
			RevCommit sideCommit = prepareCherryPickStrategyOption(git);

			CherryPickResult result = git.cherryPick()
					.include(sideCommit.getId())
					.setContentMergeStrategy(ContentMergeStrategy.THEIRS)
					.call();
			assertEquals(CherryPickStatus.OK, result.getStatus());

			String expected = "a\nside\nc\nd\n";
			checkFile(new File(db.getWorkTree(), "a"), expected);
		}
	}

	@Test
	public void testCherryPickConflictMarkers() throws Exception {
		try (Git git = new Git(db)) {
			RevCommit sideCommit = prepareCherryPick(git);

			CherryPickResult result = git.cherryPick().include(sideCommit.getId())
					.call();
			assertEquals(CherryPickStatus.CONFLICTING, result.getStatus());

			String expected = "<<<<<<< master\na(master)\n=======\na(side)\n>>>>>>> 527460a side\n";
			checkFile(new File(db.getWorkTree(), "a"), expected);
		}
	}

	@Test
	public void testCherryPickConflictFiresModifiedEvent() throws Exception {
		ListenerHandle listener = null;
		try (Git git = new Git(db)) {
			RevCommit sideCommit = prepareCherryPick(git);
			ChangeRecorder recorder = new ChangeRecorder();
			listener = db.getListenerList()
					.addWorkingTreeModifiedListener(recorder);
			CherryPickResult result = git.cherryPick()
					.include(sideCommit.getId()).call();
			assertEquals(CherryPickStatus.CONFLICTING, result.getStatus());
			recorder.assertEvent(new String[] { "a" }, ChangeRecorder.EMPTY);
		} finally {
			if (listener != null) {
				listener.remove();
			}
		}
	}

	@Test
	public void testCherryPickNewFileFiresModifiedEvent() throws Exception {
		ListenerHandle listener = null;
		try (Git git = new Git(db)) {
			writeTrashFile("test.txt", "a");
			git.add().addFilepattern("test.txt").call();
			git.commit().setMessage("commit1").call();
			git.checkout().setCreateBranch(true).setName("a").call();

			writeTrashFile("side.txt", "side");
			git.add().addFilepattern("side.txt").call();
			RevCommit side = git.commit().setMessage("side").call();
			assertNotNull(side);

			assertNotNull(git.checkout().setName(Constants.MASTER).call());
			writeTrashFile("test.txt", "b");
			assertNotNull(git.add().addFilepattern("test.txt").call());
			assertNotNull(git.commit().setMessage("commit2").call());

			ChangeRecorder recorder = new ChangeRecorder();
			listener = db.getListenerList()
					.addWorkingTreeModifiedListener(recorder);
			CherryPickResult result = git.cherryPick()
					.include(side.getId()).call();
			assertEquals(CherryPickStatus.OK, result.getStatus());
			recorder.assertEvent(new String[] { "side.txt" },
					ChangeRecorder.EMPTY);
		} finally {
			if (listener != null) {
				listener.remove();
			}
		}
	}

	@Test
	public void testCherryPickOurCommitName() throws Exception {
		try (Git git = new Git(db)) {
			RevCommit sideCommit = prepareCherryPick(git);

			CherryPickResult result = git.cherryPick().include(sideCommit.getId())
					.setOurCommitName("custom name").call();
			assertEquals(CherryPickStatus.CONFLICTING, result.getStatus());

			String expected = "<<<<<<< custom name\na(master)\n=======\na(side)\n>>>>>>> 527460a side\n";
			checkFile(new File(db.getWorkTree(), "a"), expected);
		}
	}

	private RevCommit prepareCherryPick(Git git) throws Exception {
		// create, add and commit file a
		writeTrashFile("a", "a");
		git.add().addFilepattern("a").call();
		RevCommit firstMasterCommit = git.commit().setMessage("first master")
				.call();

		// create and checkout side branch
		createBranch(firstMasterCommit, "refs/heads/side");
		checkoutBranch("refs/heads/side");
		// modify, add and commit file a
		writeTrashFile("a", "a(side)");
		git.add().addFilepattern("a").call();
		RevCommit sideCommit = git.commit().setMessage("side").call();

		// checkout master branch
		checkoutBranch("refs/heads/master");
		// modify, add and commit file a
		writeTrashFile("a", "a(master)");
		git.add().addFilepattern("a").call();
		git.commit().setMessage("second master").call();
		return sideCommit;
	}

	private RevCommit prepareCherryPickStrategyOption(Git git)
			throws Exception {
		// create, add and commit file a
		writeTrashFile("a", "a\nb\nc\n");
		git.add().addFilepattern("a").call();
		RevCommit firstMasterCommit = git.commit().setMessage("first master")
				.call();

		// create and checkout side branch
		createBranch(firstMasterCommit, "refs/heads/side");
		checkoutBranch("refs/heads/side");
		// modify, add and commit file a
		writeTrashFile("a", "a\nside\nc\nd\n");
		git.add().addFilepattern("a").call();
		RevCommit sideCommit = git.commit().setMessage("side").call();

		// checkout master branch
		checkoutBranch("refs/heads/master");
		// modify, add and commit file a
		writeTrashFile("a", "a\nmaster\nc\n");
		git.add().addFilepattern("a").call();
		git.commit().setMessage("second master").call();
		return sideCommit;
	}

	private void doCherryPickAndCheckResult(final Git git,
			final RevCommit sideCommit, final MergeFailureReason reason)
			throws Exception {
		// get current index state
		String indexState = indexState(CONTENT);

		// cherry-pick
		CherryPickResult result = git.cherryPick().include(sideCommit.getId())
				.call();
		assertEquals(CherryPickStatus.FAILED, result.getStatus());
		// staged file a causes DIRTY_INDEX
		assertEquals(1, result.getFailingPaths().size());
		assertEquals(reason, result.getFailingPaths().get("a"));
		assertEquals("a(modified)", read(new File(db.getWorkTree(), "a")));
		// index shall be unchanged
		assertEquals(indexState, indexState(CONTENT));
		assertEquals(RepositoryState.SAFE, db.getRepositoryState());

		if (reason == null) {
			ReflogReader reader = db.getReflogReader(Constants.HEAD);
			assertTrue(reader.getLastEntry().getComment()
					.startsWith("cherry-pick: "));
			reader = db.getReflogReader(db.getBranch());
			assertTrue(reader.getLastEntry().getComment()
					.startsWith("cherry-pick: "));
		}
	}

	/**
	 * Cherry-picking merge commit M onto T
	 * <pre>
	 *    M
	 *    |\
	 *    C D
	 *    |/
	 * T  B
	 * | /
	 * A
	 * </pre>
	 * @throws Exception
	 */
	@Test
	public void testCherryPickMerge() throws Exception {
		try (Git git = new Git(db)) {
			commitFile("file", "1\n2\n3\n", "master");
			commitFile("file", "1\n2\n3\n", "side");
			checkoutBranch("refs/heads/side");
			RevCommit commitD = commitFile("file", "1\n2\n3\n4\n5\n", "side2");
			commitFile("file", "a\n2\n3\n", "side");
			MergeResult mergeResult = git.merge().include(commitD).call();
			ObjectId commitM = mergeResult.getNewHead();
			checkoutBranch("refs/heads/master");
			RevCommit commitT = commitFile("another", "t", "master");

			try {
				git.cherryPick().include(commitM).call();
				fail("merges should not be cherry-picked by default");
			} catch (MultipleParentsNotAllowedException e) {
				// expected
			}
			try {
				git.cherryPick().include(commitM).setMainlineParentNumber(3).call();
				fail("specifying a non-existent parent should fail");
			} catch (JGitInternalException e) {
				// expected
				assertTrue(e.getMessage().endsWith(
						"does not have a parent number 3."));
			}

			CherryPickResult result = git.cherryPick().include(commitM)
					.setMainlineParentNumber(1).call();
			assertEquals(CherryPickStatus.OK, result.getStatus());
			checkFile(new File(db.getWorkTree(), "file"), "1\n2\n3\n4\n5\n");

			git.reset().setMode(ResetType.HARD).setRef(commitT.getName()).call();

			CherryPickResult result2 = git.cherryPick().include(commitM)
					.setMainlineParentNumber(2).call();
			assertEquals(CherryPickStatus.OK, result2.getStatus());
			checkFile(new File(db.getWorkTree(), "file"), "a\n2\n3\n");
		}
	}

	private void doCherryPickWithCustomProviderBaseTest(Git git,
			CherryPickCommitMessageProvider commitMessageProvider)
			throws Exception {
		writeTrashFile("fileA", "line 1\nline 2\nline 3\n");
		git.add().addFilepattern("fileA").call();
		RevCommit commitFirst = git.commit().setMessage("create fileA").call();

		writeTrashFile("fileB", "content from file B\n");
		git.add().addFilepattern("fileB").call();
		RevCommit commitCreateFileB = git.commit()
				.setMessage("create fileB\n\nsome commit details").call();

		writeTrashFile("fileA", "line 1\nline 2\nline 3\nline 4\n");
		git.add().addFilepattern("fileA").call();
		RevCommit commitEditFileA1 = git.commit().setMessage("patch fileA 1")
				.call();

		writeTrashFile("fileA", "line 1\nline 2\nline 3\nline 4\nline 5\n");
		git.add().addFilepattern("fileA").call();
		RevCommit commitEditFileA2 = git.commit().setMessage("patch fileA 2")
				.call();

		git.branchCreate().setName("side").setStartPoint(commitFirst).call();
		checkoutBranch("refs/heads/side");

		CherryPickResult pickResult = git.cherryPick()
				.setCherryPickCommitMessageProvider(commitMessageProvider)
				.include(commitCreateFileB).include(commitEditFileA1)
				.include(commitEditFileA2).call();

		assertEquals(CherryPickStatus.OK, pickResult.getStatus());

		assertTrue(new File(db.getWorkTree(), "fileA").exists());
		assertTrue(new File(db.getWorkTree(), "fileB").exists());

		checkFile(new File(db.getWorkTree(), "fileA"),
				"line 1\nline 2\nline 3\nline 4\nline 5\n");
		checkFile(new File(db.getWorkTree(), "fileB"), "content from file B\n");
	}

	@Test
	public void testCherryPickWithCustomCommitMessageProvider()
			throws Exception {
		try (Git git = new Git(db)) {
			@SuppressWarnings("boxing")
			CherryPickCommitMessageProvider messageProvider = srcCommit -> {
				String message = srcCommit.getFullMessage();
				return String.format("%s (message length: %d)", message,
						message.length());
			};
			doCherryPickWithCustomProviderBaseTest(git, messageProvider);

			Iterator<RevCommit> history = git.log().call().iterator();
			assertEquals("patch fileA 2 (message length: 13)",
					history.next().getFullMessage());
			assertEquals("patch fileA 1 (message length: 13)",
					history.next().getFullMessage());
			assertEquals(
					"create fileB\n\nsome commit details (message length: 33)",
					history.next().getFullMessage());
			assertEquals("create fileA", history.next().getFullMessage());
			assertFalse(history.hasNext());
		}
	}

	@Test
	public void testCherryPickWithCustomCommitMessageProvider_ORIGINAL()
			throws Exception {
		try (Git git = new Git(db)) {
			doCherryPickWithCustomProviderBaseTest(git, ORIGINAL);

			Iterator<RevCommit> history = git.log().call().iterator();
			assertEquals("patch fileA 2", history.next().getFullMessage());
			assertEquals("patch fileA 1", history.next().getFullMessage());
			assertEquals("create fileB\n\nsome commit details",
					history.next().getFullMessage());
			assertEquals("create fileA", history.next().getFullMessage());
			assertFalse(history.hasNext());
		}
	}

	@Test
	public void testCherryPickWithCustomCommitMessageProvider_ORIGINAL_WITH_REFERENCE()
			throws Exception {
		try (Git git = new Git(db)) {
			doCherryPickWithCustomProviderBaseTest(git,
					ORIGINAL_WITH_REFERENCE);

			Iterator<RevCommit> history = git.log().call().iterator();
			assertEquals("patch fileA 2\n\n(cherry picked from commit 1ac121e90b0fb6fb18bbb4307e3e9731ceeba9e1)", history.next().getFullMessage());
			assertEquals("patch fileA 1\n\n(cherry picked from commit 71475239df59076e18564fa360e3a74280926c2a)", history.next().getFullMessage());
			assertEquals("create fileB\n\nsome commit details\n\n(cherry picked from commit 29b4501297ccf8de9de9f451e7beb384b51f5378)",
					history.next().getFullMessage());
			assertEquals("create fileA", history.next().getFullMessage());
			assertFalse(history.hasNext());
		}
	}

	@Test
	public void testCherryPickWithCustomCommitMessageProvider_ORIGINAL_WITH_REFERENCE_DonNotAddNewLineAfterFooter()
			throws Exception {
		try (Git git = new Git(db)) {
			CherryPickCommitMessageProvider commitMessageProvider = CherryPickCommitMessageProvider.ORIGINAL_WITH_REFERENCE;

			RevCommit commit1 = addFileAndCommit(git, "file1", "content 1",
					"commit1: no footer line");
			RevCommit commit2 = addFileAndCommit(git, "file2", "content 2",
					"commit2: simple single footer line"
							+ "\n\nSigned-off-by: Alice <alice@example.com>");
			RevCommit commit3 = addFileAndCommit(git, "file3", "content 3",
					"commit3: multiple footer lines\n\n"
							+ "Signed-off-by: Alice <alice@example.com>\n"
							+ "Signed-off-by: Bob <bob@example.com>");
			RevCommit commit4 = addFileAndCommit(git, "file4", "content 4",
					"commit4: extra commit text before footer line\n\n"
							+ "Commit message details\n\n"
							+ "Signed-off-by: Alice <alice@example.com>\n"
							+ "Signed-off-by: Bob <bob@example.com>");
			RevCommit commit5 = addFileAndCommit(git, "file5", "content 5",
					"commit5: extra commit text after footer line\n\n"
							+ "Signed-off-by: Alice <alice@example.com>\n"
							+ "Signed-off-by: Bob <bob@example.com>\n\n"
							+ "some extra description after footer");

			git.branchCreate().setName("side").setStartPoint(commit1).call();
			checkoutBranch("refs/heads/side");

			CherryPickResult pickResult = git.cherryPick()
					.setCherryPickCommitMessageProvider(commitMessageProvider)
					.include(commit2).include(commit3).include(commit4)
					.include(commit5).call();

			assertEquals(CherryPickStatus.OK, pickResult.getStatus());

			assertTrue(new File(db.getWorkTree(), "file1").exists());
			assertTrue(new File(db.getWorkTree(), "file2").exists());
			assertTrue(new File(db.getWorkTree(), "file3").exists());
			assertTrue(new File(db.getWorkTree(), "file4").exists());
			assertTrue(new File(db.getWorkTree(), "file5").exists());

			Iterator<RevCommit> history = git.log().call().iterator();
			RevCommit cpCommit1 = history.next();
			RevCommit cpCommit2 = history.next();
			RevCommit cpCommit3 = history.next();
			RevCommit cpCommit4 = history.next();
			RevCommit cpCommitInit = history.next();
			assertFalse(history.hasNext());

			assertEquals("commit5: extra commit text after footer line\n\n"
					+ "Signed-off-by: Alice <alice@example.com>\n"
					+ "Signed-off-by: Bob <bob@example.com>\n\n"
					+ "some extra description after footer\n\n"
					+ "(cherry picked from commit c3c9959207dc7ae7c83da5d36dc14ef2ca42d572)",
					cpCommit1.getFullMessage());
			assertEquals("commit4: extra commit text before footer line\n\n"
					+ "Commit message details\n\n"
					+ "Signed-off-by: Alice <alice@example.com>\n"
					+ "Signed-off-by: Bob <bob@example.com>\n"
					+ "(cherry picked from commit af3e8106c12cb946a37b403ddb2dd6c11a883698)",
					cpCommit2.getFullMessage());
			assertEquals("commit3: multiple footer lines\n\n"
					+ "Signed-off-by: Alice <alice@example.com>\n"
					+ "Signed-off-by: Bob <bob@example.com>\n"
					+ "(cherry picked from commit 6d60f1a70a11a32dff4402c157c4ac328c32ce6c)",
					cpCommit3.getFullMessage());
			assertEquals("commit2: simple single footer line\n\n"
					+ "Signed-off-by: Alice <alice@example.com>\n"
					+ "(cherry picked from commit 92bf0ec458814ecc73da8e050e60547d2ea6cce5)",
					cpCommit4.getFullMessage());

			assertEquals("commit1: no footer line",
					cpCommitInit.getFullMessage());
		}
	}

	private RevCommit addFileAndCommit(Git git, String fileName,
			String fileText, String commitMessage)
			throws IOException, GitAPIException {
		writeTrashFile(fileName, fileText);
		git.add().addFilepattern(fileName).call();
		return git.commit().setMessage(commitMessage).call();
	}
}
