package com.atlassian.jgitflow.core;
import com.atlassian.jgitflow.core.util.GitHelper;
import com.google.common.base.Strings;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.MergeCommand;
import org.eclipse.jgit.api.MergeResult;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.transport.RefSpec;
import static com.google.common.base.Preconditions.checkState;
/**
* @since version
*/
public class HotfixFinishCommand extends AbstractGitFlowCommand<Void>
{
private final String hotfixName;
private boolean fetch;
private String message;
private boolean push;
private boolean keepBranch;
private boolean noTag;
public HotfixFinishCommand(String hotfixName, Git git, GitFlowConfiguration gfConfig)
{
super(git, gfConfig);
checkState(!Strings.isNullOrEmpty(hotfixName));
this.hotfixName = hotfixName;
this.fetch = false;
this.message = "tagging hotfix " + hotfixName;
this.push = false;
this.keepBranch = false;
this.noTag = false;
}
@Override
public Void call() throws Exception
{
String prefixedHotfixName = gfConfig.getPrefixValue(JGitFlowConstants.PREFIXES.HOTFIX.configKey()) + hotfixName;
requireLocalBranchExists(prefixedHotfixName);
requireCleanWorkingTree();
if (fetch)
{
RefSpec developSpec = new RefSpec("+" + Constants.R_HEADS + gfConfig.getDevelop() + ":" + Constants.R_REMOTES + "origin/" + gfConfig.getDevelop());
RefSpec masterSpec = new RefSpec("+" + Constants.R_HEADS + gfConfig.getMaster() + ":" + Constants.R_REMOTES + "origin/" + gfConfig.getMaster());
git.fetch().setRemote(Constants.DEFAULT_REMOTE_NAME).setRefSpecs(masterSpec).call();
git.fetch().setRemote(Constants.DEFAULT_REMOTE_NAME).setRefSpecs(developSpec).call();
git.fetch().setRemote(Constants.DEFAULT_REMOTE_NAME).call();
}
if (GitHelper.remoteBranchExists(git, gfConfig.getMaster()))
{
requireLocalBranchNotBehindRemote(gfConfig.getMaster());
}
if (GitHelper.remoteBranchExists(git, gfConfig.getDevelop()))
{
requireLocalBranchNotBehindRemote(gfConfig.getDevelop());
}
Ref hotfixBranch = GitHelper.getLocalBranch(git, prefixedHotfixName);
RevCommit hotfixCommit = GitHelper.getLatestCommit(git,prefixedHotfixName);
/*
try to merge into master
in case a previous attempt to finish this release branch has failed,
but the merge into master was successful, we skip it now
*/
if (!GitHelper.isMergedInto(git, prefixedHotfixName, gfConfig.getMaster()))
{
git.checkout().setName(gfConfig.getMaster()).call();
MergeResult masterResult = masterResult = git.merge().setFastForward(MergeCommand.FastForwardMode.NO_FF).include(hotfixBranch).call();
}
if (!noTag)
{
/*
try to tag the release
in case a previous attempt to finish this release branch has failed,
but the tag was successful, we skip it now
*/
String tagName = gfConfig.getPrefixValue(JGitFlowConstants.PREFIXES.VERSIONTAG.configKey()) + hotfixName;
if(!GitHelper.tagExists(git,tagName))
{
git.tag().setName(tagName).setMessage(message).setObjectId(hotfixCommit).call();
}
}
/*
try to merge into develop
in case a previous attempt to finish this release branch has failed,
but the merge into develop was successful, we skip it now
*/
if (!GitHelper.isMergedInto(git, prefixedHotfixName, gfConfig.getDevelop()))
{
git.checkout().setName(gfConfig.getDevelop()).call();
MergeResult developResult = git.merge().setFastForward(MergeCommand.FastForwardMode.NO_FF).include(hotfixBranch).call();
}
if(!keepBranch)
{
//make sure we're on master
git.checkout().setName(gfConfig.getMaster()).call();
git.branchDelete().setForce(true).setBranchNames(prefixedHotfixName).call();
}
if(push)
{
//push to develop
RefSpec developSpec = new RefSpec(gfConfig.getDevelop());
git.push().setRemote(Constants.DEFAULT_REMOTE_NAME).setRefSpecs(developSpec).call();
//push to master
RefSpec masterSpec = new RefSpec(gfConfig.getMaster());
git.push().setRemote(Constants.DEFAULT_REMOTE_NAME).setRefSpecs(masterSpec).call();
if(!noTag)
{
git.push().setRemote(Constants.DEFAULT_REMOTE_NAME).setPushTags().call();
}
if (GitHelper.remoteBranchExists(git, prefixedHotfixName))
{
RefSpec branchSpec = new RefSpec(prefixedHotfixName);
git.push().setRemote(Constants.DEFAULT_REMOTE_NAME).setRefSpecs(branchSpec).call();
}
}
git.checkout().setName(gfConfig.getDevelop()).call();
return null; //To change body of implemented methods use File | Settings | File Templates.
}
public HotfixFinishCommand setFetch(boolean fetch)
{
this.fetch = fetch;
return this;
}
public HotfixFinishCommand setMessage(String message)
{
this.message = message;
return this;
}
public HotfixFinishCommand setPush(boolean push)
{
this.push = push;
return this;
}
public HotfixFinishCommand setKeepBranch(boolean keepBranch)
{
this.keepBranch = keepBranch;
return this;
}
public HotfixFinishCommand setNoTag(boolean noTag)
{
this.noTag = noTag;
return this;
}
}