/*
 * Copyright (C) 2010, Mathias Kinzler <mathias.kinzler@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.assertNull;
import static org.junit.Assert.fail;

import java.util.List;

import org.eclipse.jgit.api.CreateBranchCommand.SetupUpstreamMode;
import org.eclipse.jgit.api.ListBranchCommand.ListMode;
import org.eclipse.jgit.api.errors.CannotDeleteCurrentBranchException;
import org.eclipse.jgit.api.errors.DetachedHeadException;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.api.errors.InvalidRefNameException;
import org.eclipse.jgit.api.errors.JGitInternalException;
import org.eclipse.jgit.api.errors.NotMergedException;
import org.eclipse.jgit.api.errors.RefAlreadyExistsException;
import org.eclipse.jgit.api.errors.RefNotFoundException;
import org.eclipse.jgit.junit.RepositoryTestCase;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.StoredConfig;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.transport.FetchResult;
import org.eclipse.jgit.transport.RefSpec;
import org.eclipse.jgit.transport.RemoteConfig;
import org.eclipse.jgit.transport.URIish;
import org.junit.Before;
import org.junit.Test;

public class BranchCommandTest extends RepositoryTestCase {
	private Git git;

	RevCommit initialCommit;

	RevCommit secondCommit;

	@Override
	@Before
	public void setUp() throws Exception {
		super.setUp();
		git = new Git(db);
		// checkout master
		git.commit().setMessage("initial commit").call();
		// commit something
		writeTrashFile("Test.txt", "Hello world");
		git.add().addFilepattern("Test.txt").call();
		initialCommit = git.commit().setMessage("Initial commit").call();
		writeTrashFile("Test.txt", "Some change");
		git.add().addFilepattern("Test.txt").call();
		secondCommit = git.commit().setMessage("Second commit").call();
		// create a master branch
		RefUpdate rup = db.updateRef("refs/heads/master");
		rup.setNewObjectId(initialCommit.getId());
		rup.setForceUpdate(true);
		rup.update();
	}

	private Git setUpRepoWithRemote() throws Exception {
		Repository remoteRepository = createWorkRepository();
		try (Git remoteGit = new Git(remoteRepository)) {
			// commit something
			writeTrashFile("Test.txt", "Hello world");
			remoteGit.add().addFilepattern("Test.txt").call();
			initialCommit = remoteGit.commit().setMessage("Initial commit").call();
			writeTrashFile("Test.txt", "Some change");
			remoteGit.add().addFilepattern("Test.txt").call();
			secondCommit = remoteGit.commit().setMessage("Second commit").call();
			// create a master branch
			RefUpdate rup = remoteRepository.updateRef("refs/heads/master");
			rup.setNewObjectId(initialCommit.getId());
			rup.forceUpdate();

			Repository localRepository = createWorkRepository();
			Git localGit = new Git(localRepository);
			StoredConfig config = localRepository.getConfig();
			RemoteConfig rc = new RemoteConfig(config, "origin");
			rc.addURI(new URIish(remoteRepository.getDirectory().getAbsolutePath()));
			rc.addFetchRefSpec(new RefSpec("+refs/heads/*:refs/remotes/origin/*"));
			rc.update(config);
			config.save();
			FetchResult res = localGit.fetch().setRemote("origin").call();
			assertFalse(res.getTrackingRefUpdates().isEmpty());
			rup = localRepository.updateRef("refs/heads/master");
			rup.setNewObjectId(initialCommit.getId());
			rup.forceUpdate();
			rup = localRepository.updateRef(Constants.HEAD);
			rup.link("refs/heads/master");
			rup.setNewObjectId(initialCommit.getId());
			rup.update();
			return localGit;
		}
	}

	@Test
	public void testCreateAndList() throws Exception {
		int localBefore;
		int remoteBefore;
		int allBefore;

		// invalid name not allowed
		try {
			git.branchCreate().setName("In va lid").call();
			fail("Create branch with invalid ref name should fail");
		} catch (InvalidRefNameException e) {
			// expected
		}
		// existing name not allowed w/o force
		try {
			git.branchCreate().setName("master").call();
			fail("Create branch with existing ref name should fail");
		} catch (RefAlreadyExistsException e) {
			// expected
		}

		localBefore = git.branchList().call().size();
		remoteBefore = git.branchList().setListMode(ListMode.REMOTE).call()
				.size();
		allBefore = git.branchList().setListMode(ListMode.ALL).call().size();

		assertEquals(localBefore + remoteBefore, allBefore);
		Ref newBranch = createBranch(git, "NewForTestList", false, "master",
				null);
		assertEquals("refs/heads/NewForTestList", newBranch.getName());

		assertEquals(1, git.branchList().call().size() - localBefore);
		assertEquals(0, git.branchList().setListMode(ListMode.REMOTE).call()
				.size()
				- remoteBefore);
		assertEquals(1, git.branchList().setListMode(ListMode.ALL).call()
				.size()
				- allBefore);
		// we can only create local branches
		newBranch = createBranch(git,
				"refs/remotes/origin/NewRemoteForTestList", false, "master",
				null);
		assertEquals("refs/heads/refs/remotes/origin/NewRemoteForTestList",
				newBranch.getName());
		assertEquals(2, git.branchList().call().size() - localBefore);
		assertEquals(0, git.branchList().setListMode(ListMode.REMOTE).call()
				.size()
				- remoteBefore);
		assertEquals(2, git.branchList().setListMode(ListMode.ALL).call()
				.size()
				- allBefore);
	}

	@Test(expected = InvalidRefNameException.class)
	public void testInvalidBranchHEAD() throws Exception {
		git.branchCreate().setName("HEAD").call();
		fail("Create branch with invalid ref name should fail");
	}

	@Test(expected = InvalidRefNameException.class)
	public void testInvalidBranchDash() throws Exception {
		git.branchCreate().setName("-x").call();
		fail("Create branch with invalid ref name should fail");
	}

	@Test
	public void testListAllBranchesShouldNotDie() throws Exception {
		setUpRepoWithRemote().branchList().setListMode(ListMode.ALL).call();
	}

	@Test
	public void testListBranchesWithContains() throws Exception {
		git.branchCreate().setName("foo").setStartPoint(secondCommit).call();

		List<Ref> refs = git.branchList().call();
		assertEquals(2, refs.size());

		List<Ref> refsContainingSecond = git.branchList()
				.setContains(secondCommit.name()).call();
		assertEquals(1, refsContainingSecond.size());
		// master is on initial commit, so it should not be returned
		assertEquals("refs/heads/foo", refsContainingSecond.get(0).getName());
	}

	@Test
	public void testCreateFromCommit() throws Exception {
		Ref branch = git.branchCreate().setName("FromInitial").setStartPoint(
				initialCommit).call();
		assertEquals(initialCommit.getId(), branch.getObjectId());
		branch = git.branchCreate().setName("FromInitial2").setStartPoint(
				initialCommit.getId().name()).call();
		assertEquals(initialCommit.getId(), branch.getObjectId());
		try {
			git.branchCreate().setName("FromInitial").setStartPoint(
					secondCommit).call();
		} catch (RefAlreadyExistsException e) {
			// expected
		}
		branch = git.branchCreate().setName("FromInitial").setStartPoint(
				secondCommit).setForce(true).call();
		assertEquals(secondCommit.getId(), branch.getObjectId());
	}

	@Test
	public void testCreateForce() throws Exception {
		// using commits
		Ref newBranch = createBranch(git, "NewForce", false, secondCommit
				.getId().name(), null);
		assertEquals(newBranch.getTarget().getObjectId(), secondCommit.getId());
		try {
			newBranch = createBranch(git, "NewForce", false, initialCommit
					.getId().name(), null);
			fail("Should have failed");
		} catch (RefAlreadyExistsException e) {
			// expected
		}
		newBranch = createBranch(git, "NewForce", true, initialCommit.getId()
				.name(), null);
		assertEquals(newBranch.getTarget().getObjectId(), initialCommit.getId());
		git.branchDelete().setBranchNames("NewForce").call();
		// using names

		git.branchCreate().setName("NewForce").setStartPoint("master").call();
		assertEquals(newBranch.getTarget().getObjectId(), initialCommit.getId());
		try {
			git.branchCreate().setName("NewForce").setStartPoint("master")
					.call();
			fail("Should have failed");
		} catch (RefAlreadyExistsException e) {
			// expected
		}
		git.branchCreate().setName("NewForce").setStartPoint("master")
				.setForce(true).call();
		assertEquals(newBranch.getTarget().getObjectId(), initialCommit.getId());
	}

	@Test
	public void testCreateFromLightweightTag() throws Exception {
		RefUpdate rup = db.updateRef("refs/tags/V10");
		rup.setNewObjectId(initialCommit);
		rup.setExpectedOldObjectId(ObjectId.zeroId());
		rup.update();

		Ref branch = git.branchCreate().setName("FromLightweightTag")
				.setStartPoint("refs/tags/V10").call();
		assertEquals(initialCommit.getId(), branch.getObjectId());

	}

	@Test
	public void testCreateFromAnnotatetdTag() throws Exception {
		Ref tagRef = git.tag().setName("V10").setObjectId(secondCommit).call();
		Ref branch = git.branchCreate().setName("FromAnnotatedTag")
				.setStartPoint("refs/tags/V10").call();
		assertFalse(tagRef.getObjectId().equals(branch.getObjectId()));
		assertEquals(secondCommit.getId(), branch.getObjectId());
	}

	@Test
	public void testDelete() throws Exception {
		createBranch(git, "ForDelete", false, "master", null);
		git.branchDelete().setBranchNames("ForDelete").call();
		// now point the branch to a non-merged commit
		createBranch(git, "ForDelete", false, secondCommit.getId().name(), null);
		try {
			git.branchDelete().setBranchNames("ForDelete").call();
			fail("Deletion of a non-merged branch without force should have failed");
		} catch (NotMergedException e) {
			// expected
		}
		List<String> deleted = git.branchDelete().setBranchNames("ForDelete")
				.setForce(true).call();
		assertEquals(1, deleted.size());
		assertEquals(Constants.R_HEADS + "ForDelete", deleted.get(0));
		createBranch(git, "ForDelete", false, "master", null);
		try {
			createBranch(git, "ForDelete", false, "master", null);
			fail("Repeated creation of same branch without force should fail");
		} catch (RefAlreadyExistsException e) {
			// expected
		}
		// change starting point
		Ref newBranch = createBranch(git, "ForDelete", true, initialCommit
				.name(), null);
		assertEquals(newBranch.getTarget().getObjectId(), initialCommit.getId());
		newBranch = createBranch(git, "ForDelete", true, secondCommit.name(),
				null);
		assertEquals(newBranch.getTarget().getObjectId(), secondCommit.getId());
		git.branchDelete().setBranchNames("ForDelete").setForce(true);
		try {
			git.branchDelete().setBranchNames("master").call();
			fail("Deletion of checked out branch without force should have failed");
		} catch (CannotDeleteCurrentBranchException e) {
			// expected
		}
		try {
			git.branchDelete().setBranchNames("master").setForce(true).call();
			fail("Deletion of checked out branch with force should have failed");
		} catch (CannotDeleteCurrentBranchException e) {
			// expected
		}
	}

	@Test
	public void testPullConfigRemoteBranch() throws Exception {
		Git localGit = setUpRepoWithRemote();
		Ref remote = localGit.branchList().setListMode(ListMode.REMOTE).call()
				.get(0);
		assertEquals("refs/remotes/origin/master", remote.getName());
		// by default, we should create pull configuration
		createBranch(localGit, "newFromRemote", false, remote.getName(), null);
		assertEquals("origin", localGit.getRepository().getConfig().getString(
				"branch", "newFromRemote", "remote"));
		localGit.branchDelete().setBranchNames("newFromRemote").call();
		// the pull configuration should be gone after deletion
		assertNull(localGit.getRepository().getConfig().getString("branch",
				"newFromRemote", "remote"));

		createBranch(localGit, "newFromRemote", false, remote.getName(), null);
		assertEquals("origin", localGit.getRepository().getConfig().getString(
				"branch", "newFromRemote", "remote"));
		localGit.branchDelete().setBranchNames("refs/heads/newFromRemote")
				.call();
		// the pull configuration should be gone after deletion
		assertNull(localGit.getRepository().getConfig().getString("branch",
				"newFromRemote", "remote"));

		// use --no-track
		createBranch(localGit, "newFromRemote", false, remote.getName(),
				SetupUpstreamMode.NOTRACK);
		assertNull(localGit.getRepository().getConfig().getString("branch",
				"newFromRemote", "remote"));
		localGit.branchDelete().setBranchNames("newFromRemote").call();
	}

	@Test
	public void testPullConfigLocalBranch() throws Exception {
		Git localGit = setUpRepoWithRemote();
		// by default, we should not create pull configuration
		createBranch(localGit, "newFromMaster", false, "master", null);
		assertNull(localGit.getRepository().getConfig().getString("branch",
				"newFromMaster", "remote"));
		localGit.branchDelete().setBranchNames("newFromMaster").call();
		// use --track
		createBranch(localGit, "newFromMaster", false, "master",
				SetupUpstreamMode.TRACK);
		assertEquals(".", localGit.getRepository().getConfig().getString(
				"branch", "newFromMaster", "remote"));
		localGit.branchDelete().setBranchNames("refs/heads/newFromMaster")
				.call();
		// the pull configuration should be gone after deletion
		assertNull(localGit.getRepository().getConfig().getString("branch",
				"newFromRemote", "remote"));
	}

	@Test
	public void testPullConfigRenameLocalBranch() throws Exception {
		Git localGit = setUpRepoWithRemote();
		// by default, we should not create pull configuration
		createBranch(localGit, "newFromMaster", false, "master", null);
		assertNull(localGit.getRepository().getConfig().getString("branch",
				"newFromMaster", "remote"));
		localGit.branchDelete().setBranchNames("newFromMaster").call();
		// use --track
		createBranch(localGit, "newFromMaster", false, "master",
				SetupUpstreamMode.TRACK);
		assertEquals(".", localGit.getRepository().getConfig().getString(
				"branch", "newFromMaster", "remote"));
		localGit.branchRename().setOldName("newFromMaster").setNewName(
				"renamed").call();
		assertNull(".", localGit.getRepository().getConfig().getString(
				"branch", "newFromMaster", "remote"));
		assertEquals(".", localGit.getRepository().getConfig().getString(
				"branch", "renamed", "remote"));
		localGit.branchDelete().setBranchNames("renamed").call();
		// the pull configuration should be gone after deletion
		assertNull(localGit.getRepository().getConfig().getString("branch",
				"newFromRemote", "remote"));
	}

	@Test
	public void testRenameLocalBranch() throws Exception {
		// null newName not allowed
		try {
			git.branchRename().call();
		} catch (InvalidRefNameException e) {
			// expected
		}
		// invalid newName not allowed
		try {
			git.branchRename().setNewName("In va lid").call();
		} catch (InvalidRefNameException e) {
			// expected
		}
		// not existing name not allowed
		try {
			git.branchRename().setOldName("notexistingbranch").setNewName(
					"newname").call();
		} catch (RefNotFoundException e) {
			// expected
		}
		// create some branch
		createBranch(git, "existing", false, "master", null);
		// a local branch
		Ref branch = createBranch(git, "fromMasterForRename", false, "master",
				null);
		assertEquals(Constants.R_HEADS + "fromMasterForRename", branch
				.getName());
		Ref renamed = git.branchRename().setOldName("fromMasterForRename")
				.setNewName("newName").call();
		assertEquals(Constants.R_HEADS + "newName", renamed.getName());
		try {
			git.branchRename().setOldName(renamed.getName()).setNewName(
					"existing").call();
			fail("Should have failed");
		} catch (RefAlreadyExistsException e) {
			// expected
		}
		try {
			git.branchRename().setNewName("In va lid").call();
			fail("Rename with invalid ref name should fail");
		} catch (InvalidRefNameException e) {
			// expected
		}
		// rename without old name and detached head not allowed
		RefUpdate rup = git.getRepository().updateRef(Constants.HEAD, true);
		rup.setNewObjectId(initialCommit);
		rup.forceUpdate();
		try {
			git.branchRename().setNewName("detached").call();
		} catch (DetachedHeadException e) {
			// expected
		}
	}

	@Test
	public void testRenameRemoteTrackingBranch() throws Exception {
		Git localGit = setUpRepoWithRemote();
		Ref remoteBranch = localGit.branchList().setListMode(ListMode.REMOTE)
				.call().get(0);
		Ref renamed = localGit.branchRename()
				.setOldName(remoteBranch.getName()).setNewName("newRemote")
				.call();
		assertEquals(Constants.R_REMOTES + "newRemote", renamed.getName());
	}

	@Test
	public void testCreationImplicitStart() throws Exception {
		git.branchCreate().setName("topic").call();
		assertEquals(db.resolve("HEAD"), db.resolve("topic"));
	}

	@Test
	public void testCreationNullStartPoint() throws Exception {
		String startPoint = null;
		git.branchCreate().setName("topic").setStartPoint(startPoint).call();
		assertEquals(db.resolve("HEAD"), db.resolve("topic"));
	}

	public Ref createBranch(Git actGit, String name, boolean force,
			String startPoint, SetupUpstreamMode mode)
			throws JGitInternalException, GitAPIException {
		CreateBranchCommand cmd = actGit.branchCreate();
		cmd.setName(name);
		cmd.setForce(force);
		cmd.setStartPoint(startPoint);
		cmd.setUpstreamMode(mode);
		return cmd.call();
	}
}
