package com.beijunyi.parallelgit.utils;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import com.beijunyi.parallelgit.utils.exceptions.NoSuchCommitException;
import org.eclipse.jgit.dircache.DirCache;
import org.eclipse.jgit.lib.*;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.revwalk.RevWalkUtils;
import org.eclipse.jgit.treewalk.filter.AndTreeFilter;
import org.eclipse.jgit.treewalk.filter.PathFilterGroup;
import org.eclipse.jgit.treewalk.filter.TreeFilter;
import static com.beijunyi.parallelgit.utils.TreeUtils.normalizeNodePath;
import static java.util.Collections.unmodifiableList;
import static org.eclipse.jgit.treewalk.filter.TreeFilter.ANY_DIFF;
public final class CommitUtils {
@Nonnull
public static String getDefaultCommitName(RevCommit commit) {
return commit.getId().abbreviate(7).name() + " " + commit.getShortMessage();
}
@Nonnull
public static RevCommit getCommit(AnyObjectId commitId, ObjectReader reader) throws IOException {
try(RevWalk revWalk = new RevWalk(reader)) {
return revWalk.parseCommit(commitId);
}
}
@Nonnull
public static RevCommit getCommit(AnyObjectId commitId, Repository repo) throws IOException {
try(ObjectReader reader = repo.newObjectReader()) {
return getCommit(commitId, reader);
}
}
@Nonnull
public static RevCommit getCommit(Ref ref, ObjectReader reader) throws IOException {
return getCommit(ref.getObjectId(), reader);
}
@Nonnull
public static RevCommit getCommit(Ref ref, Repository repo) throws IOException {
try(ObjectReader reader = repo.newObjectReader()) {
return getCommit(ref, reader);
}
}
@Nonnull
public static RevCommit getCommit(String id, Repository repo) throws IOException {
ObjectId commitId = repo.resolve(id);
if(commitId == null)
throw new NoSuchCommitException(id);
return getCommit(commitId, repo);
}
public static boolean exists(String name, Repository repo) throws IOException {
ObjectId obj = repo.resolve(name);
if(obj == null)
return false;
try(RevWalk rw = new RevWalk(repo)) {
return rw.lookupCommit(obj) != null;
}
}
@Nonnull
public static List<RevCommit> getHistory(AnyObjectId start, int skip, int limit, ObjectReader reader) throws IOException {
return getHistory(start, skip, limit, null, reader);
}
@Nonnull
public static List<RevCommit> getHistory(AnyObjectId start, ObjectReader reader) throws IOException {
return getHistory(start, 0, Integer.MAX_VALUE, reader);
}
@Nonnull
public static List<RevCommit> getHistory(AnyObjectId start, Repository repo) throws IOException {
try(ObjectReader reader = repo.newObjectReader()) {
return getHistory(start, reader);
}
}
@Nonnull
public static List<RevCommit> getFileRevisions(String path, AnyObjectId start, int skip, int limit, ObjectReader reader) throws IOException {
path = normalizeNodePath(path);
TreeFilter filter = AndTreeFilter.create(PathFilterGroup.createFromStrings(path), ANY_DIFF);
return getHistory(start, skip, limit, filter, reader);
}
@Nonnull
public static List<RevCommit> getFileRevisions(String path, AnyObjectId start, ObjectReader reader) throws IOException {
return getFileRevisions(path, start, 0, Integer.MAX_VALUE, reader);
}
@Nonnull
public static List<RevCommit> getFileRevisions(String file, AnyObjectId start, Repository repo) throws IOException {
try(ObjectReader reader = repo.newObjectReader()) {
return getFileRevisions(file, start, reader);
}
}
@Nonnull
public static List<RevCommit> getFileRevisions(String file, String start, Repository repo) throws IOException {
ObjectId id = repo.resolve(start);
return id != null ? getFileRevisions(file, id, repo) : Collections.<RevCommit>emptyList();
}
@Nullable
public static RevCommit getLatestFileRevision(String path, AnyObjectId start, ObjectReader reader) throws IOException {
List<RevCommit> commits = getFileRevisions(path, start, 0, 1, reader);
if(commits.isEmpty()) return null;
return commits.get(0);
}
@Nullable
public static RevCommit getLatestFileRevision(String path, AnyObjectId start, Repository repo) throws IOException {
try(ObjectReader reader = repo.newObjectReader()) {
return getLatestFileRevision(path, start, reader);
}
}
@Nullable
public static RevCommit getLatestFileRevision(String path, String start, Repository repo) throws IOException {
ObjectId id = repo.resolve(start);
return id != null ? getLatestFileRevision(path, id, repo) : null;
}
public static boolean isMergedInto(AnyObjectId sourceHead, AnyObjectId masterHead, ObjectReader reader) throws IOException {
try(RevWalk rw = new RevWalk(reader)) {
return rw.isMergedInto(rw.lookupCommit(sourceHead), rw.lookupCommit(masterHead));
}
}
public static boolean isMergedInto(AnyObjectId sourceHead, AnyObjectId masterHead, Repository repo) throws IOException {
try(ObjectReader reader = repo.newObjectReader()) {
return isMergedInto(sourceHead, masterHead, reader);
}
}
public static boolean isMergedInto(String source, String master, Repository repo) throws IOException {
return isMergedInto(repo.resolve(source), repo.resolve(master), repo);
}
@Nonnull
public static List<RevCommit> listUnmergedCommits(AnyObjectId sourceHead, AnyObjectId masterHead, ObjectReader reader) throws IOException {
try(RevWalk rw = new RevWalk(reader)) {
return unmodifiableList(RevWalkUtils.find(rw, rw.lookupCommit(sourceHead), rw.lookupCommit(masterHead)));
}
}
@Nonnull
public static List<RevCommit> listUnmergedCommits(AnyObjectId sourceHead, AnyObjectId masterHead, Repository repo) throws IOException {
try(ObjectReader reader = repo.newObjectReader()) {
return listUnmergedCommits(sourceHead, masterHead, reader);
}
}
@Nonnull
public static List<RevCommit> listUnmergedCommits(String source, String master, Repository repo) throws IOException {
return listUnmergedCommits(repo.resolve(source), repo.resolve(master), repo);
}
@Nonnull
public static RevCommit createCommit(String message, AnyObjectId treeId, PersonIdent author, PersonIdent committer, List<? extends AnyObjectId> parents, Repository repo) throws IOException {
try(ObjectInserter inserter = repo.newObjectInserter()) {
AnyObjectId commitId = insertCommit(message, treeId, author, committer, parents, inserter);
inserter.flush();
return CommitUtils.getCommit(commitId, repo);
}
}
@Nonnull
public static RevCommit createCommit(String message, AnyObjectId treeId, PersonIdent committer, @Nullable AnyObjectId parent, Repository repo) throws IOException {
return createCommit(message, treeId, committer, committer, toParentList(parent), repo);
}
@Nonnull
public static RevCommit createCommit(String message, AnyObjectId treeId, @Nullable AnyObjectId parent, Repository repo) throws IOException {
return createCommit(message, treeId, new PersonIdent(repo), parent, repo);
}
@Nonnull
public static RevCommit createCommit(String message, DirCache cache, PersonIdent author, PersonIdent committer, List<? extends AnyObjectId> parents, Repository repo) throws IOException {
try(ObjectInserter inserter = repo.newObjectInserter()) {
AnyObjectId commitId = insertCommit(message, cache.writeTree(inserter), author, committer, parents, inserter);
inserter.flush();
return CommitUtils.getCommit(commitId, repo);
}
}
@Nonnull
public static RevCommit createCommit(String message, DirCache cache, PersonIdent committer, @Nullable AnyObjectId parent, Repository repo) throws IOException {
return createCommit(message, cache, committer, committer, toParentList(parent), repo);
}
@Nonnull
public static RevCommit createCommit(String message, DirCache cache, @Nullable AnyObjectId parent, Repository repo) throws IOException {
return createCommit(message, cache, new PersonIdent(repo), parent, repo);
}
@Nonnull
private static ObjectId insertCommit(String message, AnyObjectId treeId, PersonIdent author, PersonIdent committer, List<? extends AnyObjectId> parents, ObjectInserter inserter) throws IOException {
CommitBuilder builder = new CommitBuilder();
builder.setCommitter(committer);
builder.setAuthor(author);
builder.setMessage(message);
builder.setTreeId(treeId);
builder.setParentIds(parents);
return inserter.insert(builder);
}
@Nonnull
private static List<? extends AnyObjectId> toParentList(@Nullable AnyObjectId parent) {
return parent != null ? Collections.singletonList(parent) : Collections.<AnyObjectId>emptyList();
}
@Nonnull
private static List<RevCommit> getHistory(AnyObjectId start, int skip, int limit, @Nullable TreeFilter filter, ObjectReader reader) throws IOException {
List<RevCommit> commits;
try(RevWalk rw = new RevWalk(reader)) {
rw.markStart(CommitUtils.getCommit(start, reader));
if(filter != null)
rw.setTreeFilter(filter);
commits = toCommitList(rw, skip, limit);
}
return commits;
}
@Nonnull
private static List<RevCommit> toCommitList(RevWalk rw, int skip, int limit) {
List<RevCommit> commits = new ArrayList<>();
long max = (long) limit + skip;
long count = 0;
for(RevCommit commit : rw) {
if(count >= skip && count < max)
commits.add(commit);
if(count++ >= max)
break;
}
return unmodifiableList(commits);
}
}