package me.brianlong.git; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.eclipse.jgit.api.CloneCommand; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.ListBranchCommand; import org.eclipse.jgit.api.ListBranchCommand.ListMode; import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.api.errors.InvalidRemoteException; import org.eclipse.jgit.api.errors.TransportException; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.lib.Repository; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class ExtendedGit extends CachedGit { private final Logger logger = LoggerFactory.getLogger(ExtendedGit.class); private final Pattern gitUrlPattern = Pattern.compile("(((ssh|http(s)?)://([^@]+@)?([^:/]+)(:[0-9]+)?/)|git@([^:]+):)([\\w\\.@\\:/\\-~]+)(\\.git)"); public ExtendedGit(Git git) { super(git.getRepository()); } public ExtendedGit(CloneCommand clone) throws TransportException, InvalidRemoteException, GitAPIException { super(clone.call().getRepository()); } public ExtendedGit(Repository repo) { super(repo); } public String getFirstRemoteUrl() throws GitAPIException { return this.remoteList().call().iterator().next().getURIs().iterator().next().toString(); } public String getRepositoryFullyQualifiedName() throws GitAPIException, URISyntaxException { String gitUrl = this.getFirstRemoteUrl(); if (this.logger.isDebugEnabled()) this.logger.debug("Remote URL: " + gitUrl); Matcher matcher = this.gitUrlPattern.matcher(gitUrl); if (!matcher.find()) throw new URISyntaxException(gitUrl, "The Git URL does not match the expected regular expression: " + this.gitUrlPattern.toString()); return matcher.group(9); } /** * This method retrieves all branches, but excludes remote branches that are tracked with a local branch. * @return */ public List getAllUniqueBranches() throws GitAPIException { return this.getAllUniqueBranches(null); } /** * This method retrieves all branches, but excludes remote branches that are tracked with a local branch. * @return */ public List getAllUniqueBranches(String containsCommitish) throws GitAPIException { ListBranchCommand command = this.branchList().setListMode(ListMode.ALL); if (containsCommitish != null) command.setContains(containsCommitish); List branches = command.call(); Set abbrevBranchNames = new HashSet(branches.size()); List trimmedBranches = new ArrayList(branches.size()); // sort them by local, then remote; keep order the same otherwise Collections.sort(branches, new Comparator() { @Override public int compare(Ref o1, Ref o2) { if (o1 == null) return -1; else if (o2 == null) return 1; else { boolean o1local = o1.getName().startsWith(Constants.R_HEADS); boolean o2local = o2.getName().startsWith(Constants.R_HEADS); if (o1local && o2local) return 0; else if (o1local) return -1; else if (o2local) return 1; else return 0; } } }); for (Ref branch : branches) { String fqBranchName = branch.getName(); String abbrevBranchName = null; if (fqBranchName.startsWith(Constants.R_REMOTES)) { if (this.logger.isDebugEnabled()) this.logger.debug("Ref is a remote branch: " + fqBranchName); abbrevBranchName = this.getRepository().shortenRemoteBranchName(fqBranchName); } else if (fqBranchName.startsWith(Constants.R_HEADS)) { if (this.logger.isDebugEnabled()) this.logger.debug("Ref is a local branch: " + fqBranchName); abbrevBranchName = Repository.shortenRefName(fqBranchName); } else { if (this.logger.isDebugEnabled()) this.logger.debug("Ref is not a local or remote branch: " + fqBranchName); } if (abbrevBranchName != null) { if (abbrevBranchNames.contains(abbrevBranchName)) { if (this.logger.isDebugEnabled()) this.logger.debug("Branch already found; ignoring ..."); } else { abbrevBranchNames.add(abbrevBranchName); trimmedBranches.add(branch); } } } return trimmedBranches; } }