package ut.com.atlassian.jgitflow.core;
import java.io.File;
import java.util.List;
import com.atlassian.jgitflow.core.JGitFlow;
import com.atlassian.jgitflow.core.JGitFlowInitCommand;
import com.atlassian.jgitflow.core.ReleaseMergeResult;
import com.atlassian.jgitflow.core.exception.BranchOutOfDateException;
import com.atlassian.jgitflow.core.exception.DirtyWorkingTreeException;
import com.atlassian.jgitflow.core.util.GitHelper;
import org.apache.commons.io.FileUtils;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.ListBranchCommand;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.revwalk.RevCommit;
import org.junit.Test;
import ut.com.atlassian.jgitflow.core.testutils.RepoUtil;
import static org.junit.Assert.*;
/**
* @since version
*/
public class ReleaseFinishTest extends BaseGitFlowTest
{
@Test
public void finishRelease() throws Exception
{
Git git = RepoUtil.createRepositoryWithMaster(newDir());
JGitFlowInitCommand initCommand = new JGitFlowInitCommand();
JGitFlow flow = initCommand.setDirectory(git.getRepository().getWorkTree()).call();
flow.releaseStart("1.0").call();
assertEquals(flow.getReleaseBranchPrefix() + "1.0", git.getRepository().getBranch());
ReleaseMergeResult result = flow.releaseFinish("1.0").call();
assertTrue(result.wasSuccessful());
//we should be on develop branch
assertEquals(flow.getDevelopBranchName(), git.getRepository().getBranch());
//release branch should be gone
Ref ref2check = git.getRepository().getRef(flow.getReleaseBranchPrefix() + "1.0");
assertNull(ref2check);
}
@Test(expected = DirtyWorkingTreeException.class)
public void finishReleaseWithUnStagedFile() throws Exception
{
Git git = RepoUtil.createRepositoryWithMasterAndDevelop(newDir());
JGitFlowInitCommand initCommand = new JGitFlowInitCommand();
JGitFlow flow = initCommand.setDirectory(git.getRepository().getWorkTree()).call();
flow.releaseStart("1.0").call();
//create a new file
File junkFile = new File(git.getRepository().getWorkTree(), "junk.txt");
FileUtils.writeStringToFile(junkFile, "I am junk");
//try to finish
ReleaseMergeResult result = flow.releaseFinish("1.0").call();
assertTrue(result.wasSuccessful());
}
@Test(expected = DirtyWorkingTreeException.class)
public void finishReleaseUnCommittedFile() throws Exception
{
Git git = RepoUtil.createRepositoryWithMasterAndDevelop(newDir());
JGitFlowInitCommand initCommand = new JGitFlowInitCommand();
JGitFlow flow = initCommand.setDirectory(git.getRepository().getWorkTree()).call();
flow.releaseStart("1.0").call();
//create a new file and add it to the index
File junkFile = new File(git.getRepository().getWorkTree(), "junk.txt");
FileUtils.writeStringToFile(junkFile, "I am junk");
git.add().addFilepattern(junkFile.getName()).call();
//try to finish
ReleaseMergeResult result = flow.releaseFinish("1.0").call();
assertTrue(result.wasSuccessful());
}
@Test
public void finishReleaseWithNewCommit() throws Exception
{
Git git = RepoUtil.createRepositoryWithMasterAndDevelop(newDir());
JGitFlowInitCommand initCommand = new JGitFlowInitCommand();
JGitFlow flow = initCommand.setDirectory(git.getRepository().getWorkTree()).call();
flow.releaseStart("1.0").call();
//create a new commit
File junkFile = new File(git.getRepository().getWorkTree(), "junk.txt");
FileUtils.writeStringToFile(junkFile, "I am junk");
git.add().addFilepattern(junkFile.getName()).call();
RevCommit commit = git.commit().setMessage("committing junk file").call();
//make sure develop doesn't report our commit yet
assertFalse(GitHelper.isMergedInto(git, commit, flow.getDevelopBranchName()));
//try to finish
ReleaseMergeResult result = flow.releaseFinish("1.0").call();
assertTrue(result.wasSuccessful());
//we should be on develop branch
assertEquals(flow.getDevelopBranchName(), git.getRepository().getBranch());
//release branch should be gone
Ref ref2check = git.getRepository().getRef(flow.getReleaseBranchPrefix() + "1.0");
assertNull(ref2check);
//the develop branch should have our commit
assertTrue(GitHelper.isMergedInto(git, commit, flow.getDevelopBranchName()));
//since fast-forward is suppressed the latest commit on develop should be a merge commit with 2 parents
assertEquals(2, GitHelper.getLatestCommit(git, flow.getDevelopBranchName()).getParentCount());
//the master branch should have our commit
assertTrue(GitHelper.isMergedInto(git, commit, flow.getMasterBranchName()));
//since fast-forward is suppressed the latest commit on master should be a merge commit with 2 parents
assertEquals(2, GitHelper.getLatestCommit(git, flow.getMasterBranchName()).getParentCount());
}
@Test
public void finishReleaseWithNewCommitNoMerge() throws Exception
{
Git git = RepoUtil.createRepositoryWithMasterAndDevelop(newDir());
JGitFlowInitCommand initCommand = new JGitFlowInitCommand();
JGitFlow flow = initCommand.setDirectory(git.getRepository().getWorkTree()).call();
flow.releaseStart("1.0").call();
//create a new commit
File junkFile = new File(git.getRepository().getWorkTree(), "junk.txt");
FileUtils.writeStringToFile(junkFile, "I am junk");
git.add().addFilepattern(junkFile.getName()).call();
RevCommit commit = git.commit().setMessage("committing junk file").call();
//make sure develop doesn't report our commit yet
assertFalse(GitHelper.isMergedInto(git, commit, flow.getDevelopBranchName()));
//try to finish
ReleaseMergeResult result = flow.releaseFinish("1.0").setNoMerge(true).call();
assertTrue(result.wasSuccessful());
//we should be on develop branch
assertEquals(flow.getDevelopBranchName(), git.getRepository().getBranch());
//release branch should be gone
Ref ref2check = git.getRepository().getRef(flow.getReleaseBranchPrefix() + "1.0");
assertNull(ref2check);
//the develop branch should have NOT our commit
assertFalse(GitHelper.isMergedInto(git, commit, flow.getDevelopBranchName()));
//the master branch should NOT have our commit
assertFalse(GitHelper.isMergedInto(git, commit, flow.getMasterBranchName()));
}
@Test
public void finishReleaseKeepBranch() throws Exception
{
Git git = RepoUtil.createRepositoryWithMasterAndDevelop(newDir());
JGitFlowInitCommand initCommand = new JGitFlowInitCommand();
JGitFlow flow = initCommand.setDirectory(git.getRepository().getWorkTree()).call();
flow.releaseStart("1.0").call();
//just in case
assertEquals(flow.getReleaseBranchPrefix() + "1.0", git.getRepository().getBranch());
ReleaseMergeResult result = flow.releaseFinish("1.0").setKeepBranch(true).call();
assertTrue(result.wasSuccessful());
//we should be on develop branch
assertEquals(flow.getDevelopBranchName(), git.getRepository().getBranch());
//release branch should still exist
Ref ref2check = git.getRepository().getRef(flow.getReleaseBranchPrefix() + "1.0");
assertNotNull(ref2check);
}
@Test
public void finishReleaseWithMultipleCommits() throws Exception
{
Git git = RepoUtil.createRepositoryWithMasterAndDevelop(newDir());
JGitFlowInitCommand initCommand = new JGitFlowInitCommand();
JGitFlow flow = initCommand.setDirectory(git.getRepository().getWorkTree()).call();
flow.releaseStart("1.0").call();
//create a new commit
File junkFile = new File(git.getRepository().getWorkTree(), "junk.txt");
FileUtils.writeStringToFile(junkFile, "I am junk");
git.add().addFilepattern(junkFile.getName()).call();
RevCommit commit = git.commit().setMessage("committing junk file").call();
//create second commit
File junkFile2 = new File(git.getRepository().getWorkTree(), "junk2.txt");
FileUtils.writeStringToFile(junkFile2, "I am junk, and so are you");
git.add().addFilepattern(junkFile2.getName()).call();
RevCommit commit2 = git.commit().setMessage("updating junk file").call();
//make sure develop doesn't have our commits yet
assertFalse(GitHelper.isMergedInto(git, commit, flow.getDevelopBranchName()));
assertFalse(GitHelper.isMergedInto(git, commit2, flow.getDevelopBranchName()));
//try to finish
ReleaseMergeResult result = flow.releaseFinish("1.0").call();
assertTrue(result.wasSuccessful());
//we should be on develop branch
assertEquals(flow.getDevelopBranchName(), git.getRepository().getBranch());
//release branch should be gone
Ref ref2check = git.getRepository().getRef(flow.getReleaseBranchPrefix() + "1.0");
assertNull(ref2check);
//the develop branch should have both of our commits now
assertTrue(GitHelper.isMergedInto(git, commit, flow.getDevelopBranchName()));
assertTrue(GitHelper.isMergedInto(git, commit2, flow.getDevelopBranchName()));
//the master branch should have both of our commits now
assertTrue(GitHelper.isMergedInto(git, commit, flow.getMasterBranchName()));
assertTrue(GitHelper.isMergedInto(git, commit2, flow.getMasterBranchName()));
}
@Test
public void finishReleaseWithSquash() throws Exception
{
Git git = RepoUtil.createRepositoryWithMasterAndDevelop(newDir());
JGitFlowInitCommand initCommand = new JGitFlowInitCommand();
JGitFlow flow = initCommand.setDirectory(git.getRepository().getWorkTree()).call();
flow.releaseStart("1.0").call();
//create a new commit
File junkFile = new File(git.getRepository().getWorkTree(), "junk.txt");
FileUtils.writeStringToFile(junkFile, "I am junk");
git.add().addFilepattern(junkFile.getName()).call();
RevCommit commit = git.commit().setMessage("committing junk file").call();
//create second commit
File junkFile2 = new File(git.getRepository().getWorkTree(), "junk2.txt");
FileUtils.writeStringToFile(junkFile2, "I am junk, and so are you");
git.add().addFilepattern(junkFile2.getName()).call();
RevCommit commit2 = git.commit().setMessage("updating junk file").call();
//make sure develop doesn't have our commits yet
assertFalse(GitHelper.isMergedInto(git, commit, flow.getDevelopBranchName()));
assertFalse(GitHelper.isMergedInto(git, commit2, flow.getDevelopBranchName()));
//try to finish
ReleaseMergeResult result = flow.releaseFinish("1.0").setSquash(true).call();
assertTrue(result.wasSuccessful());
//we should be on develop branch
assertEquals(flow.getDevelopBranchName(), git.getRepository().getBranch());
//release branch should be gone
Ref ref2check = git.getRepository().getRef(flow.getReleaseBranchPrefix() + "1.0");
assertNull(ref2check);
//the develop branch should NOT have both of our commits now
assertFalse(GitHelper.isMergedInto(git, commit, flow.getDevelopBranchName()));
assertFalse(GitHelper.isMergedInto(git, commit2, flow.getDevelopBranchName()));
//the master branch should NOT have both of our commits now
assertFalse(GitHelper.isMergedInto(git, commit, flow.getMasterBranchName()));
assertFalse(GitHelper.isMergedInto(git, commit2, flow.getMasterBranchName()));
//we should have the release files
git.checkout().setName(flow.getDevelopBranchName()).call();
File developJunk = new File(git.getRepository().getWorkTree(), "junk.txt");
File developJunk2 = new File(git.getRepository().getWorkTree(), "junk2.txt");
assertTrue(developJunk.exists());
assertTrue(developJunk2.exists());
git.checkout().setName(flow.getMasterBranchName()).call();
File masterJunk = new File(git.getRepository().getWorkTree(), "junk.txt");
File masterJunk2 = new File(git.getRepository().getWorkTree(), "junk2.txt");
assertTrue(masterJunk.exists());
assertTrue(masterJunk2.exists());
}
@Test(expected = BranchOutOfDateException.class)
public void finishReleaseDevelopBehindRemoteWithFetch() throws Exception
{
Git git = null;
Git remoteGit = null;
remoteGit = RepoUtil.createRepositoryWithMasterAndDevelop(newDir());
git = Git.cloneRepository().setDirectory(newDir()).setURI("file://" + remoteGit.getRepository().getWorkTree().getPath()).call();
JGitFlowInitCommand initCommand = new JGitFlowInitCommand();
JGitFlow flow = initCommand.setDirectory(git.getRepository().getWorkTree()).call();
flow.releaseStart("1.0").call();
//do a commit to the remote develop branch
remoteGit.checkout().setName(flow.getDevelopBranchName()).call();
File junkFile = new File(remoteGit.getRepository().getWorkTree(), "junk.txt");
FileUtils.writeStringToFile(junkFile, "I am junk");
remoteGit.add().addFilepattern(junkFile.getName()).call();
remoteGit.commit().setMessage("adding junk file").call();
ReleaseMergeResult result = flow.releaseFinish("1.0").setFetch(true).call();
assertTrue(result.wasSuccessful());
}
@Test(expected = BranchOutOfDateException.class)
public void finishReleaseMasterBehindRemoteWithFetch() throws Exception
{
Git git = null;
Git remoteGit = null;
remoteGit = RepoUtil.createRepositoryWithMasterAndDevelop(newDir());
git = Git.cloneRepository().setDirectory(newDir()).setURI("file://" + remoteGit.getRepository().getWorkTree().getPath()).call();
JGitFlowInitCommand initCommand = new JGitFlowInitCommand();
JGitFlow flow = initCommand.setDirectory(git.getRepository().getWorkTree()).call();
flow.releaseStart("1.0").call();
//do a commit to the remote master branch
remoteGit.checkout().setName(flow.getMasterBranchName()).call();
File junkFile = new File(remoteGit.getRepository().getWorkTree(), "junk.txt");
FileUtils.writeStringToFile(junkFile, "I am junk");
remoteGit.add().addFilepattern(junkFile.getName()).call();
remoteGit.commit().setMessage("adding junk file").call();
ReleaseMergeResult result = flow.releaseFinish("1.0").setFetch(true).call();
assertTrue(result.wasSuccessful());
}
//TODO: add tests for push and tag flags
@Test
public void finishReleaseWithRemoteReleaseAndPush() throws Exception
{
Git git = null;
Git remoteGit = null;
remoteGit = RepoUtil.createRepositoryWithMasterAndDevelop(newDir());
git = Git.cloneRepository().setDirectory(newDir()).setURI("file://" + remoteGit.getRepository().getWorkTree().getPath()).call();
JGitFlowInitCommand initCommand = new JGitFlowInitCommand();
JGitFlow flow = initCommand.setDirectory(git.getRepository().getWorkTree()).call();
flow.releaseStart("1.0").call();
flow.git().push().setRemote("origin").call();
//do a commit to the remote develop branch
List<Ref> remoteBranches = remoteGit.branchList().setListMode(ListBranchCommand.ListMode.ALL).call();
boolean hasRemoteRelease = false;
for (Ref remoteBranch : remoteBranches)
{
if (remoteBranch.getName().equals(Constants.R_HEADS + flow.getReleaseBranchPrefix() + "1.0"))
{
hasRemoteRelease = true;
break;
}
}
assertTrue(hasRemoteRelease);
File junkFile = new File(flow.git().getRepository().getWorkTree(), "junk.txt");
FileUtils.writeStringToFile(junkFile, "I am junk");
flow.git().add().addFilepattern(junkFile.getName()).call();
RevCommit localcommit = flow.git().commit().setMessage("adding junk file").call();
ReleaseMergeResult result = flow.releaseFinish("1.0").setPush(true).call();
assertTrue(result.wasSuccessful());
assertTrue(GitHelper.isMergedInto(remoteGit, localcommit, flow.getMasterBranchName()));
assertTrue(GitHelper.isMergedInto(remoteGit, localcommit, flow.getDevelopBranchName()));
assertFalse(GitHelper.remoteBranchExists(git, flow.getReleaseBranchPrefix() + "1.0"));
assertFalse(GitHelper.localBranchExists(remoteGit, flow.getReleaseBranchPrefix() + "1.0"));
}
@Test
public void finishReleaseAfterHotfix() throws Exception
{
Git git = RepoUtil.createRepositoryWithMasterAndDevelop(newDir());
JGitFlowInitCommand initCommand = new JGitFlowInitCommand();
JGitFlow flow = initCommand.setDirectory(git.getRepository().getWorkTree()).call();
//create a hotfix
flow.hotfixStart("1.1").call();
//create a release
flow.git().checkout().setName(flow.getDevelopBranchName()).call();
flow.releaseStart("2.0").call();
//add a commit on hotfix
flow.git().checkout().setName(flow.getHotfixBranchPrefix() + "1.1").call();
File junkFile = new File(git.getRepository().getWorkTree(), "junk.txt");
FileUtils.writeStringToFile(junkFile, "I am junk");
git.add().addFilepattern(junkFile.getName()).call();
RevCommit commit = git.commit().setMessage("committing junk file").call();
//add a commit on release
flow.git().checkout().setName(flow.getReleaseBranchPrefix() + "2.0").call();
File junkFile2 = new File(git.getRepository().getWorkTree(), "junk2.txt");
FileUtils.writeStringToFile(junkFile2, "I am junk");
git.add().addFilepattern(junkFile2.getName()).call();
RevCommit commit2 = git.commit().setMessage("committing junk file").call();
//finish the hotfix
flow.git().checkout().setName(flow.getHotfixBranchPrefix() + "1.1").call();
flow.hotfixFinish("1.1").call();
//make sure release has the hotfix commit
flow.git().checkout().setName(flow.getReleaseBranchPrefix() + "2.0").call();
assertTrue(GitHelper.isMergedInto(flow.git(), commit, flow.getReleaseBranchPrefix() + "2.0"));
//finish the release
ReleaseMergeResult result = flow.releaseFinish("2.0").call();
assertTrue(result.wasSuccessful());
//we should be on develop branch
assertEquals(flow.getDevelopBranchName(), git.getRepository().getBranch());
//release branch should be gone
Ref ref2check = git.getRepository().getRef(flow.getReleaseBranchPrefix() + "2.0");
assertNull(ref2check);
}
}