apidiff.internal.service.git.GitServiceImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of apidiff Show documentation
Show all versions of apidiff Show documentation
A tool to identify API breaking and non-breaking changes between two versions of a Java library
The newest version!
package apidiff.internal.service.git;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.jgit.api.CheckoutCommand;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.diff.DiffEntry;
import org.eclipse.jgit.diff.DiffEntry.ChangeType;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.RepositoryBuilder;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.revwalk.RevWalkUtils;
import org.eclipse.jgit.revwalk.filter.RevFilter;
import org.eclipse.jgit.transport.FetchResult;
import org.eclipse.jgit.transport.TrackingRefUpdate;
import org.eclipse.jgit.treewalk.CanonicalTreeParser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import apidiff.internal.util.UtilTools;
public class GitServiceImpl implements GitService {
private static final String REMOTE_REFS_PREFIX = "refs/remotes/origin/";
private RevFilterCommitValid commitsFilter = new RevFilterCommitValid();
private Logger logger = LoggerFactory.getLogger(GitServiceImpl.class);
private static final Long MINUTE = 60000L; //60.000 miliseconds
private static final Long HOUR = MINUTE * 60;
private static final Long DAY = HOUR * 24;
private static final Long SEVEN_DAYS = DAY * 7; //7 dias em milissegundos.
private class RevFilterCommitValid extends RevFilter {
@Override
public final boolean include(final RevWalk walker, final RevCommit c) {
Long diffTimestamp = 0L;
diffTimestamp = this.calcDiffTimeCommit(c);
if(c.getParentCount() > 1){//merge
logger.info("Merge of the branches deleted. [commitId=" + c.getId().getName() + "]");
return false;
}
//TODO: create other filter to date.
// if(diffTimestamp > SEVEN_DAYS){//old
// logger.info("Old commit old deleted. [commitId=" + c.getId().getName() + "][date=" + getDateCommitFormat(c) + "]");
// return false;
// }
return true;
}
private Long calcDiffTimeCommit(final RevCommit c){
Long timestampNow = Calendar.getInstance().getTimeInMillis();
Long timestampCommit = c.getAuthorIdent().getWhen().getTime();
Calendar calendarCommit = Calendar.getInstance();
calendarCommit.setTime(new Date(timestampCommit));
return Math.abs(timestampCommit - timestampNow);
}
private String getDateCommitFormat(final RevCommit c){
Long timestampCommit = c.getAuthorIdent().getWhen().getTime();
Calendar calendarCommit = Calendar.getInstance();
calendarCommit.setTime(new Date(timestampCommit));
SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy hh:mm:ss");
return format.format(timestampCommit);
}
@Override
public final RevFilter clone() {
return this;
}
@Override
public final boolean requiresCommitBody() {
return false;
}
@Override
public String toString() {
return "RegularCommitsFilter";
}
}
@Override
public Repository openRepositoryAndCloneIfNotExists(String path, String projectName, String cloneUrl) throws Exception {
File folder = new File(UtilTools.getPathProject(path , projectName));
Repository repository = null;
if (folder.exists()) {
this.logger.info(projectName + " exists. Reading properties ... (wait)");
RepositoryBuilder builder = new RepositoryBuilder();
repository = builder
.setGitDir(new File(folder, ".git"))
.readEnvironment()
.findGitDir()
.build();
} else {
this.logger.info("Cloning " + cloneUrl + " in " + cloneUrl + " ... (wait)");
Git git = Git.cloneRepository()
.setDirectory(folder)
.setURI(cloneUrl)
.setCloneAllBranches(true)
.call();
repository = git.getRepository();
}
this.logger.info("Process " + projectName + " finish.");
return repository;
}
@Override
public RevWalk fetchAndCreateNewRevsWalk(Repository repository, String branch) throws Exception {
List currentRemoteRefs = new ArrayList();
for (Ref ref : repository.getAllRefs().values()) {
String refName = ref.getName();
if (refName.startsWith(REMOTE_REFS_PREFIX)) {
currentRemoteRefs.add(ref.getObjectId());
}
}
List newRemoteRefs = this.fetch(repository);
RevWalk walk = new RevWalk(repository);
for (TrackingRefUpdate newRef : newRemoteRefs) {
if (branch == null || newRef.getLocalName().endsWith("/" + branch)) {
walk.markStart(walk.parseCommit(newRef.getNewObjectId()));
}
}
for (ObjectId oldRef : currentRemoteRefs) {
walk.markUninteresting(walk.parseCommit(oldRef));
}
walk.setRevFilter(commitsFilter);
return walk;
}
public RevWalk createAllRevsWalk(Repository repository, String branch) throws Exception {
List currentRemoteRefs = new ArrayList();
for (Ref ref : repository.getAllRefs().values()) {
String refName = ref.getName();
if (refName.startsWith(REMOTE_REFS_PREFIX)) {
if (branch == null || refName.endsWith("/" + branch)) {
currentRemoteRefs.add(ref.getObjectId());
}
}
}
RevWalk walk = new RevWalk(repository);
for (ObjectId newRef : currentRemoteRefs) {
walk.markStart(walk.parseCommit(newRef));
}
walk.setRevFilter(commitsFilter);
return walk;
}
private List fetch(Repository repository) throws Exception {
this.logger.info("Fetching changes of repository " + repository.getDirectory().toString());
try (Git git = new Git(repository)) {
FetchResult result = git.fetch().call();
Collection updates = result.getTrackingRefUpdates();
List remoteRefsChanges = new ArrayList();
for (TrackingRefUpdate update : updates) {
String refName = update.getLocalName();
if (refName.startsWith(REMOTE_REFS_PREFIX)) {
ObjectId newObjectId = update.getNewObjectId();
this.logger.info(refName +" is now at " + newObjectId.getName());
remoteRefsChanges.add(update);
}
}
if (updates.isEmpty()) {
this.logger.info("Nothing changed");
}
return remoteRefsChanges;
}
}
@Override
public Integer countCommits(Repository repository, String branch) throws Exception {
RevWalk walk = new RevWalk(repository);
try {
Ref ref = repository.findRef(REMOTE_REFS_PREFIX + branch);
ObjectId objectId = ref.getObjectId();
RevCommit start = walk.parseCommit(objectId);
walk.setRevFilter(RevFilter.NO_MERGES);
return RevWalkUtils.count(walk, start, null);
} finally {
walk.dispose();
}
}
@Override
public Map> fileTreeDiff(Repository repository, RevCommit commitNew) throws Exception {
Map> mapDiff = new HashMap>();
mapDiff.put(ChangeType.ADD, new ArrayList<>());
mapDiff.put(ChangeType.COPY, new ArrayList<>());
mapDiff.put(ChangeType.DELETE, new ArrayList<>());
mapDiff.put(ChangeType.MODIFY, new ArrayList<>());
mapDiff.put(ChangeType.RENAME, new ArrayList<>());
if(commitNew.getParentCount() == 0){
this.logger.warn("Commit don't have parent [commitId="+commitNew.getId().getName()+"]");
return mapDiff;
}
ObjectId headOld = commitNew.getParent(0).getTree(); //Commit pai no grafo.
ObjectId headNew = commitNew.getTree(); //Commit corrente.
// prepare the two iterators to compute the diff between
ObjectReader reader = repository.newObjectReader();
CanonicalTreeParser treeRepositoryOld = new CanonicalTreeParser();
treeRepositoryOld.reset(reader, headOld);
CanonicalTreeParser treeRepositoryNew = new CanonicalTreeParser();
treeRepositoryNew.reset(reader, headNew);
// finally get the list of changed files
List diffs = new Git(repository).diff()
.setNewTree(treeRepositoryNew)
.setOldTree(treeRepositoryOld)
.setShowNameAndStatusOnly(true)
.call();
for (DiffEntry entry : diffs) {
if(UtilTools.isJavaFile(entry.getOldPath()) || UtilTools.isJavaFile(entry.getNewPath())) {
String pathNew = "/dev/null".equals(entry.getNewPath())?null:entry.getNewPath();
String pathOld = "/dev/null".equals(entry.getOldPath())?null:entry.getOldPath();
GitFile file = new GitFile(pathOld, pathNew, entry.getChangeType());
mapDiff.get(entry.getChangeType()).add(file);
}
}
return mapDiff;
}
@Override
public void checkout(Repository repository, String commitId) throws Exception {
this.logger.info("Checking out {} {} ...", repository.getDirectory().getParent().toString(), commitId);
try (Git git = new Git(repository)) {
CheckoutCommand checkout = git.checkout().setName(commitId);
checkout.call();
}
}
@Override
public RevCommit createRevCommitByCommitId(final Repository repository, final String commitId) throws Exception{
RevWalk walk = new RevWalk(repository);
RevCommit commit = walk.parseCommit(repository.resolve(commitId));
walk.parseCommit(commit.getParent(0));
return commit;
}
}