github-api/src/main/java/me/brianlong/git/ExtendedGit.java
2020-12-07 13:46:48 -05:00

128 lines
4.3 KiB
Java

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<Ref> 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<Ref> getAllUniqueBranches(String containsCommitish) throws GitAPIException {
ListBranchCommand command = this.branchList().setListMode(ListMode.ALL);
if (containsCommitish != null)
command.setContains(containsCommitish);
List<Ref> branches = command.call();
Set<String> abbrevBranchNames = new HashSet<String>(branches.size());
List<Ref> trimmedBranches = new ArrayList<Ref>(branches.size());
// sort them by local, then remote; keep order the same otherwise
Collections.sort(branches, new Comparator<Ref>() {
@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;
}
}