package com.atlassian.jgitflow.core.util;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import com.atlassian.jgitflow.core.JGitFlowConstants;
import com.atlassian.jgitflow.core.exception.MissingBranchException;
import com.google.common.base.Strings;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.ListBranchCommand;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.diff.DiffEntry;
import org.eclipse.jgit.lib.*;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.treewalk.FileTreeIterator;
import static com.google.common.collect.Lists.newArrayList;
/**
* @since version
*/
public class GitHelper
{
public static boolean isMergedInto(Git git, String branchName, String baseName) throws IOException, MissingBranchException, GitAPIException
{
Repository repo = git.getRepository();
RevWalk walk = new RevWalk(repo);
walk.setRetainBody(false);
ObjectId branch = repo.resolve(branchName);
if (null == branch)
{
throw new MissingBranchException(branchName + " does not exist");
}
RevCommit branchCommit = walk.parseCommit(branch);
return isMergedInto(git, branchCommit, baseName);
}
public static boolean isMergedInto(Git git, RevCommit commit, String branchName) throws IOException, GitAPIException
{
Repository repo = git.getRepository();
ObjectId base = repo.resolve(branchName);
if(null == base)
{
return false;
}
Iterable<RevCommit> baseCommits = git.log().add(base).call();
boolean merged = false;
for (RevCommit entry : baseCommits)
{
if (entry.getId().equals(commit))
{
merged = true;
break;
}
if (entry.getParentCount() > 1 && Arrays.asList(entry.getParents()).contains(commit))
{
merged = true;
break;
}
}
return merged;
}
public static RevCommit getLatestCommit(Git git, String branchName) throws IOException, GitAPIException
{
ObjectId branch = git.getRepository().resolve(branchName);
RevWalk walk = new RevWalk(git.getRepository());
walk.setRetainBody(true);
try
{
return walk.parseCommit(branch);
}
finally
{
walk.release();
}
}
public static boolean localBranchExists(Git git, String branchName) throws GitAPIException
{
boolean exists = false;
if(Strings.isNullOrEmpty(branchName))
{
return exists;
}
List<Ref> refs = git.branchList().setListMode(null).call();
for (Ref ref : refs)
{
String simpleName = ref.getName().substring(ref.getName().indexOf(Constants.R_HEADS) + Constants.R_HEADS.length());
if (simpleName.equals(branchName))
{
exists = true;
break;
}
}
return exists;
}
public static boolean remoteBranchExists(Git git, final String branch) throws GitAPIException
{
boolean exists = false;
if(Strings.isNullOrEmpty(branch))
{
return exists;
}
List<Ref> refs = git.branchList().setListMode(ListBranchCommand.ListMode.REMOTE).call();
for (Ref ref : refs)
{
String simpleName = ref.getName().substring(ref.getName().indexOf(JGitFlowConstants.R_REMOTE_ORIGIN) + JGitFlowConstants.R_REMOTE_ORIGIN.length());
if (simpleName.equals(branch))
{
exists = true;
break;
}
}
return exists;
}
public static Ref getRemoteBranch(Git git, String branchName) throws IOException
{
final Map<String, Ref> refList = git.getRepository().getRefDatabase().getRefs(Constants.R_REMOTES);
Ref remote = null;
for (Map.Entry<String, Ref> entry : refList.entrySet())
{
int index = entry.getValue().getName().indexOf(JGitFlowConstants.R_REMOTE_ORIGIN);
if(index < 0)
{
continue;
}
String simpleName = entry.getValue().getName().substring(index + JGitFlowConstants.R_REMOTE_ORIGIN.length());
if (simpleName.equals(branchName))
{
remote = entry.getValue();
break;
}
}
return remote;
}
public static Ref getLocalBranch(Git git, String branchName) throws IOException
{
Ref ref2check = git.getRepository().getRef(branchName);
Ref local = null;
if (ref2check != null && ref2check.getName().startsWith(Constants.R_HEADS))
{
local = ref2check;
}
return local;
}
public static List<Ref> listBranchesWithPrefix(Git git, String prefix) throws GitAPIException
{
List<Ref> branches = newArrayList();
List<Ref> refs = git.branchList().setListMode(null).call();
for (Ref ref : refs)
{
String simpleName = ref.getName().substring(ref.getName().indexOf(Constants.R_HEADS) + Constants.R_HEADS.length());
if (simpleName.startsWith(prefix))
{
branches.add(ref);
}
}
return branches;
}
public static boolean workingTreeIsClean(Git git) throws GitAPIException, IOException
{
List<DiffEntry> branchDiffs = git.diff().call();
if (!branchDiffs.isEmpty())
{
return false;
}
branchDiffs = git.diff().setCached(true).call();
if (!branchDiffs.isEmpty())
{
return false;
}
IndexDiff diffIndex = new IndexDiff(git.getRepository(), Constants.HEAD, new FileTreeIterator(git.getRepository()));
if (diffIndex.diff())
{
return false;
}
return true;
}
public static boolean tagExists(Git git, final String tagName) throws GitAPIException
{
boolean exists = false;
if(Strings.isNullOrEmpty(tagName))
{
return exists;
}
List<Ref> refs = git.tagList().call();
for (Ref ref : refs)
{
String simpleName = ref.getName().substring(ref.getName().indexOf(Constants.R_TAGS) + Constants.R_TAGS.length());
if (simpleName.equals(tagName))
{
exists = true;
break;
}
}
return exists;
}
}