ru.concerteza.util.buildnumber.BuildNumberExtractor Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jgit-buildnumber-ant-task Show documentation
Show all versions of jgit-buildnumber-ant-task Show documentation
Ant task, extracts buildnumbers from project's Git repository without Git command line tool
package ru.concerteza.util.buildnumber;
import org.eclipse.jgit.lib.Constants;
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.storage.file.FileRepository;
import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
/**
* Extracts buildnumber fields from git repository. Put it here, not in common module, because we don't want
* any ant task dependencies except jgit and ant
*
* @author alexey
* Date: 11/16/11
* @see BuildNumber
*/
public class BuildNumberExtractor {
private static final String EMPTY_STRING = "";
/**
* @param repoDirectory directory to start searching git root from, should contain '.git' directory
* or be a subdirectory of such directory
* @return extracted buildnumber object
* @throws IOException
*/
public static BuildNumber extract(File repoDirectory) throws IOException {
if(!(repoDirectory.exists() && repoDirectory.isDirectory())) throw new IOException(
"Invalid repository directory provided: " + repoDirectory.getAbsolutePath());
// open repo, jgit has some problems with not canonical paths
File canonicalRepo = repoDirectory.getCanonicalFile();
FileRepository repo = new FileRepositoryBuilder().findGitDir(canonicalRepo).build();
// extract HEAD revision
ObjectId revisionObject = repo.resolve(Constants.HEAD);
if (null == revisionObject) throw new IOException("Cannot read current revision from repository: " + repo);
String revision = revisionObject.name();
// extract current branch
String branch = readCurrentBranch(repo, revision);
// extract current tag
String tag = readCurrentTag(repo, revision);
// extract current parent
String parent = readCurrentParent(repo, revision);
// count total commits
int commitsCount = countCommits(repo, revisionObject);
return new BuildNumber(revision, branch, tag, parent, commitsCount);
}
private static String readCurrentBranch(FileRepository repo, String revision) throws IOException {
String branch = repo.getBranch();
// should not happen
if (null == branch) return EMPTY_STRING;
if (revision.equals(branch)) return EMPTY_STRING;
return branch;
}
private static String readCurrentTag(FileRepository repo, String revision) {
Map tagMap = loadTagsMap(repo);
String tag = tagMap.get(revision);
if (null == tag) return EMPTY_STRING;
return tag;
}
private static String readCurrentParent(FileRepository repo, String revision) throws IOException {
ObjectId rev = repo.resolve(revision);
if (null == rev) return EMPTY_STRING;
RevCommit commit = new RevWalk(repo).parseCommit(rev);
RevCommit[] parents = commit.getParents();
if (null == parents || parents.length == 0) return EMPTY_STRING;
String parentsFormat = null;
for (RevCommit p : parents) {
String sha1 = p.getId().name();
if (null == parentsFormat) {
parentsFormat = sha1;
} else {
parentsFormat += ";" + sha1;
}
}
return parentsFormat;
}
// sha1 -> tag name
private static Map loadTagsMap(FileRepository repo) {
Map refMap = repo.getTags();
Map res = new HashMap(refMap.size());
for (Map.Entry en : refMap.entrySet()) {
String sha1 = extractPeeledSha1(repo, en.getValue());
String existed = res.get(sha1);
final String value;
if (null == existed) {
value = en.getKey();
} else {
value = existed + ";" + en.getKey();
}
res.put(sha1, value);
}
return res;
}
// search for sha1 corresponding to annotated tag
private static String extractPeeledSha1(FileRepository repo, Ref ref) {
Ref peeled = repo.peel(ref);
ObjectId oid = peeled.getPeeledObjectId();
return null != oid ? oid.name() : peeled.getObjectId().name();
}
// takes about 1 sec to count 69939 in intellijidea repo
private static int countCommits(FileRepository repo, ObjectId revision) throws IOException {
RevWalk walk = new RevWalk(repo);
walk.setRetainBody(false);
RevCommit head = walk.parseCommit(revision);
walk.markStart(head);
int res = 0;
for (RevCommit commit : walk) res += 1;
return res;
}
}