package com.link_intersystems.gitdirstat.domain.walk;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashSet;
import org.apache.commons.collections4.Predicate;
import org.apache.commons.collections4.functors.UniquePredicate;
import org.eclipse.jgit.lib.AnyObjectId;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevSort;
import org.eclipse.jgit.revwalk.RevWalk;
import com.link_intersystems.gitdirstat.domain.Commit;
import com.link_intersystems.gitdirstat.domain.CommitRange;
import com.link_intersystems.gitdirstat.domain.GitRepository;
public class CommitWalker implements Iterable<Commit> {
private GitRepository gitRepository;
private Collection<CommitRange> commitRanges = new LinkedHashSet<CommitRange>();
private RevSort[] revSorts = new RevSort[0];
private Collection<CommitIterator> iterators = new ArrayList<CommitIterator>();
public CommitWalker(GitRepository gitRepository) {
this.gitRepository = gitRepository;
}
private RevWalk createRevWalk() {
ObjectReader objectReader = gitRepository.getObjectReader();
RevWalk revWalk = new RevWalk(objectReader);
applyCommitRanges(revWalk);
applyRevSorts(revWalk);
return revWalk;
}
private void applyCommitRanges(RevWalk revWalk) {
try {
for (CommitRange commitRange : commitRanges) {
AnyObjectId fromInclusive = commitRange.getToInclusive();
RevCommit revCommit;
revCommit = revWalk.parseCommit(fromInclusive);
revWalk.markStart(revCommit);
}
} catch (IOException e) {
throw new RuntimeException("Can't create RevWalk instance", e);
}
}
private void applyRevSorts(RevWalk revWalk) {
for (int i = 0; i < revSorts.length; i++) {
RevSort revSort = revSorts[i];
if (i == 0) {
revWalk.sort(revSort);
} else {
revWalk.sort(revSort, true);
}
}
}
@Override
public Iterator<Commit> iterator() {
RevWalk revWalk = createRevWalk();
CommitIterator commitIterator = new CommitIterator(revWalk,
gitRepository);
iterators.add(commitIterator);
return commitIterator;
}
public void close() {
for (CommitIterator commitIterator : iterators) {
commitIterator.close();
}
}
private static class CommitIterator implements Iterator<Commit> {
private Iterator<RevCommit> revCommitIterator;
private GitRepository gitRepository;
private Predicate<Object> uniquePredicate;
private RevWalk revWalk;
public CommitIterator(RevWalk revWalk, GitRepository gitRepository) {
this.revWalk = revWalk;
this.revCommitIterator = revWalk.iterator();
this.gitRepository = gitRepository;
uniquePredicate = UniquePredicate.uniquePredicate();
}
@Override
public boolean hasNext() {
boolean hasNext = revCommitIterator.hasNext();
if (!hasNext) {
close();
}
return hasNext;
}
@Override
public Commit next() {
RevCommit revCommit = revCommitIterator.next();
if (!uniquePredicate.evaluate(revCommit)) {
System.out.println(revCommit);
}
Commit commit = gitRepository.getCommit(revCommit);
return commit;
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
public void close() {
revWalk.release();
}
}
public void setCommitRanges(Collection<CommitRange> commitRanges)
throws IOException {
this.commitRanges.clear();
this.commitRanges.addAll(commitRanges);
}
public void sort(RevSort... revSorts) {
if (revSorts == null) {
revSorts = new RevSort[0];
}
this.revSorts = revSorts;
}
public int getWalkCount() {
Iterator<Commit> iterator = iterator();
int total = 0;
while (iterator.hasNext()) {
total++;
iterator.next();
}
return total;
}
}