package com.atlassian.jgitflow.core;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.Callable;
import com.atlassian.jgitflow.core.exception.*;
import com.atlassian.jgitflow.core.util.GitHelper;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.revwalk.filter.RevFilter;
import static com.google.common.base.Preconditions.checkNotNull;
public abstract class AbstractGitFlowCommand<T> implements Callable<T>
{
protected final Git git;
protected final GitFlowConfiguration gfConfig;
protected AbstractGitFlowCommand(Git git, GitFlowConfiguration gfConfig)
{
checkNotNull(git);
checkNotNull(gfConfig);
this.git = git;
this.gfConfig = gfConfig;
}
protected void requireGitFlowInitialized() throws JGitFlowException
{
try
{
if (!gfConfig.gitFlowIsInitialized())
{
throw new NotInitializedException("Git flow is not initialized in " + git.getRepository().getWorkTree().getPath());
}
}
catch (GitAPIException e)
{
throw new JGitFlowException(e);
}
}
protected void requireLocalBranchAbsent(String branch) throws JGitFlowException
{
try
{
if (GitHelper.localBranchExists(git, branch))
{
throw new BranchExistsException("local branch '" + branch + "' already exists");
}
}
catch (GitAPIException e)
{
throw new JGitFlowException(e);
}
}
protected void requireLocalBranchExists(String branch) throws JGitFlowException
{
try
{
if(!GitHelper.localBranchExists(git, branch))
{
throw new MissingBranchException("local branch " + branch + " does not exist");
}
}
catch (GitAPIException e)
{
throw new JGitFlowException(e);
}
}
protected void requireRemoteBranchAbsent(String branch) throws JGitFlowException
{
try
{
if (GitHelper.remoteBranchExists(git, branch))
{
throw new BranchExistsException("remote branch '" + branch + "' already exists");
}
}
catch (GitAPIException e)
{
throw new JGitFlowException(e);
}
}
protected void requireRemoteBranchExists(String branch) throws JGitFlowException
{
try
{
if(!GitHelper.remoteBranchExists(git, branch))
{
throw new MissingBranchException("remote branch " + branch + " does not exist");
}
}
catch (GitAPIException e)
{
throw new JGitFlowException(e);
}
}
protected void requireTagAbsent(String name) throws JGitFlowException
{
try
{
if (GitHelper.tagExists(git, name))
{
throw new BranchExistsException("tag '" + name + "' already exists");
}
}
catch (GitAPIException e)
{
throw new JGitFlowException(e);
}
}
protected void requireLocalBranchNotBehindRemote(String branch) throws JGitFlowException
{
final RevWalk walk = new RevWalk(git.getRepository());
walk.setRetainBody(true);
boolean behind = false;
try
{
Ref remote = GitHelper.getRemoteBranch(git, branch);
Ref local = GitHelper.getLocalBranch(git, branch);
checkNotNull(remote);
checkNotNull(local);
ObjectId remoteId = git.getRepository().resolve(remote.getObjectId().getName());
RevCommit remoteCommit = walk.parseCommit(remoteId);
RevCommit localCommit = walk.parseCommit(local.getObjectId());
if (!localCommit.equals(remoteCommit))
{
behind = true;
walk.setRevFilter(RevFilter.MERGE_BASE);
walk.markStart(localCommit);
walk.markStart(remoteCommit);
RevCommit base = walk.next();
if (null != base)
{
walk.parseBody(base);
//remote is behind
if (remoteCommit.equals(base))
{
behind = false;
}
}
}
}
catch (IOException e)
{
throw new JGitFlowException(e);
}
finally
{
walk.release();
}
if (behind)
{
throw new BranchOutOfDateException("local branch '" + branch + "' is behind the remote branch");
}
}
protected void requireCleanWorkingTree() throws JGitFlowException
{
try
{
if (!GitHelper.workingTreeIsClean(git))
{
throw new DirtyWorkingTreeException("Working tree has uncommitted changes");
}
}
catch (GitAPIException e)
{
throw new JGitFlowException(e);
}
catch (IOException e)
{
throw new JGitFlowException(e);
}
}
protected void requireNoExistingReleaseBranches() throws JGitFlowException
{
try
{
List<Ref> branches = GitHelper.listBranchesWithPrefix(git, JGitFlowConstants.PREFIXES.RELEASE.configKey());
if(!branches.isEmpty())
{
throw new BranchExistsException("a release branch [" + branches.get(0).getName() + "] already exists. Finish that first!");
}
}
catch (GitAPIException e)
{
throw new JGitFlowException(e);
}
}
protected void requireNoExistingHotfixBranches() throws JGitFlowException
{
try
{
List<Ref> branches = GitHelper.listBranchesWithPrefix(git, JGitFlowConstants.PREFIXES.HOTFIX.configKey());
if(!branches.isEmpty())
{
throw new BranchExistsException("a hotfix branch [" + branches.get(0).getName() + "] already exists. Finish that first!");
}
}
catch (GitAPIException e)
{
throw new JGitFlowException(e);
}
}
}