package com.github.qwazer.mavenplugins.gitlog;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.lib.*;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevObject;
import org.eclipse.jgit.revwalk.RevWalk;
import java.io.IOException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Util methods for work with GIT repo
* @author ar
* @since Date: 04.05.2015
*/
public class GitLogUtil {
public static Repository openRepository() throws NoGitRepositoryException, IOException {
Repository repository = null;
try {
repository = new RepositoryBuilder().findGitDir().build();
} catch (IllegalArgumentException iae) {
throw new NoGitRepositoryException();
}
return repository;
}
public static Set<String> loadVersionTagList(Repository repository, String versionTagNamePattern) {
Set<String> versionTagList = new HashSet<String>();
if (versionTagNamePattern != null) {
versionTagList = new HashSet<String>();
for (String tagName : repository.getTags().keySet()) {
if (tagName.matches(versionTagNamePattern)) {
versionTagList.add(tagName);
}
}
} else {
versionTagList = repository.getTags().keySet();
}
return versionTagList;
}
protected static RevCommit resolveCommitIdByTagName(Repository repository, String tagName) throws IOException, GitAPIException {
if (tagName == null || tagName.isEmpty()) return null;
RevCommit revCommit = null;
Map<String, Ref> tagMap = repository.getTags();
Ref ref = tagMap.get(tagName);
if (ref != null) {
RevWalk walk = new RevWalk(repository);
//some reduce memory effors as described in jgit user guide
walk.setRetainBody(false);
ObjectId from;
from = repository.resolve("refs/heads/master");
if (from == null) {
Git git = new Git(repository);
String lastTagName = git.describe().call();
from = repository.resolve("refs/tags/" + lastTagName);
}
ObjectId to = repository.resolve("refs/remotes/origin/master");
if (from==null){
throw new IllegalStateException("cannot determinate start commit");
}
walk.markStart(walk.parseCommit(from));
walk.markUninteresting(walk.parseCommit(to));
try {
RevObject revObject = walk.parseAny(ref.getObjectId());
if (revObject != null) {
revCommit = walk.parseCommit(revObject.getId());
}
} finally {
walk.close();
}
}
return revCommit;
}
public static Set<String> extractJiraIssues(Repository repository,
String sinceTagName,
String untilTagName,
String pattern) throws IOException, GitAPIException {
Git git = new Git(repository);
RevCommit startCommitId = resolveCommitIdByTagName(repository, sinceTagName);
if (startCommitId == null) {
throw new IOException("cannot resolveCommitIdByTagName by " + sinceTagName);
}
ObjectId endCommitId = resolveCommitIdByTagName(repository, untilTagName);
if (endCommitId == null) {
endCommitId = repository.resolve(Constants.HEAD);
}
Iterable<RevCommit> commits = git.log().addRange(startCommitId, endCommitId).call();
return extractJiraIssues(pattern, commits);
}
public static LinkedHashMap<String, Set<String>> extractJiraIssuesByVersion(Repository repository,
List<String> versionTagList,
String pattern) throws IOException, GitAPIException {
LinkedHashMap<String, Set<String>> linkedHashMap = new LinkedHashMap<String, Set<String>>();
int lenght = versionTagList.size();
for (int i = 0; i < lenght; i++) {
String sinceTagName = versionTagList.get(i);
String untilTagName = i + 1 > lenght - 1 ? null : versionTagList.get(i + 1);
linkedHashMap.put(versionTagList.get(i), extractJiraIssues(repository, sinceTagName, untilTagName, pattern));
}
return linkedHashMap;
}
private static Set<String> extractJiraIssues(String pattern, Iterable<RevCommit> commits) {
HashSet jiraIssues = new LinkedHashSet(); //preserve insertion order
for (RevCommit commit : commits) {
jiraIssues.addAll(extractJiraIssuesFromString(commit.getFullMessage(), pattern));
}
return jiraIssues;
}
protected static List<String> extractJiraIssuesFromString(String s, String jiraIssuePattern) {
Pattern p = Pattern.compile(jiraIssuePattern);
Matcher m = p.matcher(s);
List<String> list = new ArrayList<String>();
while (m.find()) {
list.add(m.group(0));
}
return list;
}
}