package ut.com.atlassian.jgitflow.core; import java.io.File; import com.atlassian.jgitflow.core.JGitFlow; import com.atlassian.jgitflow.core.JGitFlowInitCommand; 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.lib.Ref; import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.revwalk.RevTag; import org.eclipse.jgit.revwalk.RevWalk; import org.junit.Test; import ut.com.atlassian.jgitflow.core.testutils.RepoUtil; import static org.junit.Assert.*; /** * @since version */ public class HotfixFinishTest extends BaseGitFlowTest { @Test public void finishHotfix() throws Exception { Git git = RepoUtil.createRepositoryWithMaster(newDir()); JGitFlowInitCommand initCommand = new JGitFlowInitCommand(); JGitFlow flow = initCommand.setDirectory(git.getRepository().getWorkTree()).call(); flow.hotfixStart("1.0").call(); assertEquals(flow.getHotfixBranchPrefix() + "1.0", git.getRepository().getBranch()); flow.hotfixFinish("1.0").call(); //we should be on develop branch assertEquals(flow.getDevelopBranchName(), git.getRepository().getBranch()); //release branch should be gone Ref ref2check = git.getRepository().getRef(flow.getHotfixBranchPrefix() + "1.0"); assertNull(ref2check); } @Test public void finishHotfixMultipleTimesWithCommits() throws Exception { String hfOneLabel = "1.0.1"; String hfTwoLabel = "1.0.2"; Git git = RepoUtil.createRepositoryWithMaster(newDir()); JGitFlowInitCommand initCommand = new JGitFlowInitCommand(); JGitFlow flow = initCommand.setDirectory(git.getRepository().getWorkTree()).call(); flow.hotfixStart(hfOneLabel).call(); assertEquals(flow.getHotfixBranchPrefix() + hfOneLabel, git.getRepository().getBranch()); File versionFile = new File(git.getRepository().getWorkTree(), "version.txt"); FileUtils.writeStringToFile(versionFile, hfOneLabel); git.add().addFilepattern(".").call(); git.commit().setMessage("commiting version 1").call(); flow.hotfixFinish(hfOneLabel).call(); //we should be on develop branch assertEquals(flow.getDevelopBranchName(), git.getRepository().getBranch()); FileUtils.writeStringToFile(versionFile, "develop"); git.add().addFilepattern(".").call(); git.commit().setMessage("commiting develop").call(); flow.hotfixStart(hfTwoLabel).call(); assertEquals(flow.getHotfixBranchPrefix() + hfTwoLabel, git.getRepository().getBranch()); FileUtils.writeStringToFile(versionFile, hfTwoLabel); git.add().addFilepattern(".").call(); git.commit().setMessage("commiting version 2").call(); flow.hotfixFinish(hfTwoLabel).call(); //we should be on develop branch assertEquals(flow.getDevelopBranchName(), git.getRepository().getBranch()); } @Test(expected = DirtyWorkingTreeException.class) public void finishHotfixWithUnStagedFile() throws Exception { Git git = RepoUtil.createRepositoryWithMasterAndDevelop(newDir()); JGitFlowInitCommand initCommand = new JGitFlowInitCommand(); JGitFlow flow = initCommand.setDirectory(git.getRepository().getWorkTree()).call(); flow.hotfixStart("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 flow.hotfixFinish("1.0").call(); } @Test(expected = DirtyWorkingTreeException.class) public void finishHotfixUnCommittedFile() throws Exception { Git git = RepoUtil.createRepositoryWithMasterAndDevelop(newDir()); JGitFlowInitCommand initCommand = new JGitFlowInitCommand(); JGitFlow flow = initCommand.setDirectory(git.getRepository().getWorkTree()).call(); flow.hotfixStart("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 flow.hotfixFinish("1.0").call(); } @Test public void finishHotfixWithNewCommit() throws Exception { Git git = RepoUtil.createRepositoryWithMasterAndDevelop(newDir()); JGitFlowInitCommand initCommand = new JGitFlowInitCommand(); JGitFlow flow = initCommand.setDirectory(git.getRepository().getWorkTree()).call(); flow.hotfixStart("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 flow.hotfixFinish("1.0").call(); //we should be on develop branch assertEquals(flow.getDevelopBranchName(), git.getRepository().getBranch()); //release branch should be gone Ref ref2check = git.getRepository().getRef(flow.getHotfixBranchPrefix() + "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 finishHotfixWithNewCommitAndReleaseBranch() throws Exception { Git git = RepoUtil.createRepositoryWithMasterAndDevelop(newDir()); JGitFlowInitCommand initCommand = new JGitFlowInitCommand(); JGitFlow flow = initCommand.setDirectory(git.getRepository().getWorkTree()).call(); flow.releaseStart("1.0").call(); String releaseName = "release/1.0"; flow.git().checkout().setName("develop").call(); flow.hotfixStart("1.0.1").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())); //make sure release doesn't report our commit yet assertFalse(GitHelper.isMergedInto(git, commit, releaseName)); //try to finish flow.hotfixFinish("1.0.1").setKeepBranch(false).call(); //we should be on develop branch assertEquals(flow.getDevelopBranchName(), git.getRepository().getBranch()); //hotfix branch should be gone Ref ref2check = git.getRepository().getRef(flow.getHotfixBranchPrefix() + "1.0.1"); 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()); //the release branch should have our commit assertTrue(GitHelper.isMergedInto(git, commit, releaseName)); //since fast-forward is suppressed the latest commit on the release branch should be a merge commit with 2 parents assertEquals(2, GitHelper.getLatestCommit(git, releaseName).getParentCount()); } @Test public void finishHotfixKeepBranch() throws Exception { Git git = RepoUtil.createRepositoryWithMasterAndDevelop(newDir()); JGitFlowInitCommand initCommand = new JGitFlowInitCommand(); JGitFlow flow = initCommand.setDirectory(git.getRepository().getWorkTree()).call(); flow.hotfixStart("1.0").call(); //just in case assertEquals(flow.getHotfixBranchPrefix() + "1.0", git.getRepository().getBranch()); flow.hotfixFinish("1.0").setKeepBranch(true).call(); //we should be on develop branch assertEquals(flow.getDevelopBranchName(), git.getRepository().getBranch()); //release branch should still exist Ref ref2check = git.getRepository().getRef(flow.getHotfixBranchPrefix() + "1.0"); assertNotNull(ref2check); } @Test public void finishHotfixWithMultipleCommits() throws Exception { Git git = RepoUtil.createRepositoryWithMasterAndDevelop(newDir()); JGitFlowInitCommand initCommand = new JGitFlowInitCommand(); JGitFlow flow = initCommand.setDirectory(git.getRepository().getWorkTree()).call(); flow.hotfixStart("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 flow.hotfixFinish("1.0").call(); //we should be on develop branch assertEquals(flow.getDevelopBranchName(), git.getRepository().getBranch()); //release branch should be gone Ref ref2check = git.getRepository().getRef(flow.getHotfixBranchPrefix() + "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(expected = BranchOutOfDateException.class) public void finishHotfixDevelopBehindRemoteWithFetch() 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.hotfixStart("1.0").call(); //do a commit to the remote develop branch remoteGit.checkout().setName(flow.getDevelopBranchName()); 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(); flow.hotfixFinish("1.0").setFetch(true).call(); } @Test(expected = BranchOutOfDateException.class) public void finishHotfixMasterBehindRemoteWithFetch() 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.hotfixStart("1.0").call(); //do a commit to the remote develop branch remoteGit.checkout().setName(flow.getMasterBranchName()); 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(); flow.hotfixFinish("1.0").setFetch(true).call(); } @Test public void finishHotfixMasterIsTagged() throws Exception { Git git = RepoUtil.createRepositoryWithMasterAndDevelop(newDir()); JGitFlowInitCommand initCommand = new JGitFlowInitCommand(); JGitFlow flow = initCommand.setDirectory(git.getRepository().getWorkTree()).call(); String masterBranchName = flow.getMasterBranchName(); RevCommit oldMasterHead = GitHelper.getLatestCommit(git, masterBranchName); flow.hotfixStart("1.0").call(); // Make sure we move away from master on a hotfix branch // This is important to validate JGITFFLOW-14 //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(); git.commit().setMessage("committing junk file").call(); flow.hotfixFinish("1.0").setNoTag(false).call(); //we should be on develop branch assertEquals(flow.getDevelopBranchName(), git.getRepository().getBranch()); // There should be a tag reference Ref hotfixTagRef = git.getRepository().getTags().get(flow.getVersionTagPrefix() + "1.0"); assertNotNull(hotfixTagRef); RevTag hotfixTag = new RevWalk(git.getRepository()).parseTag(hotfixTagRef.getObjectId()); assertNotNull(hotfixTag); RevCommit newMasterHead = GitHelper.getLatestCommit(git, masterBranchName); // Check that master has moved assertFalse(newMasterHead.equals(oldMasterHead)); // Hotfix tag should reference new master assertEquals(newMasterHead, hotfixTag.getObject()); } //TODO: add tests for push and tag flags }