GitRetriever.java
package org.docascode.api.retrieve;
import org.docascode.api.core.errors.DocAsCodeException;
import org.eclipse.jgit.api.DiffCommand;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.diff.DiffEntry;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectLoader;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevTree;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.treewalk.CanonicalTreeParser;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.jgit.treewalk.filter.PathFilter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class GitRetriever {
private RevCommit commit;
public GitRetriever setCommit(RevCommit commit){
this.commit = commit;
return this;
}
private Repository repo;
public GitRetriever setRepository(Repository repo){
this.repo = repo;
return this;
}
private String path;
public GitRetriever setPath(String path){
this.path = path;
return this;
}
private File toDir;
public GitRetriever toDir(File toDir){
this.toDir = toDir;
return this;
}
public File call() throws DocAsCodeException {
try (ObjectReader reader = repo.newObjectReader();
Git git = Git.open(repo.getWorkTree())
) {
DiffCommand diff = git.diff();
RevWalk revWalk = new RevWalk(repo);
RevTree oldTree = revWalk.parseTree(commit.getTree().getId());
CanonicalTreeParser oldTreeParser = new CanonicalTreeParser();
oldTreeParser.reset(reader,oldTree.getId());
RevCommit headCommit = revWalk.parseCommit(repo.resolve("HEAD"));
RevTree headTree = revWalk.parseTree(headCommit.getTree().getId());
CanonicalTreeParser headTreeParser = new CanonicalTreeParser();
oldTreeParser.reset(reader,headTree.getId());
DiffEntry diffEntry = diff.setOldTree(oldTreeParser)
.setPathFilter(PathFilter.create(path))
.setNewTree(headTreeParser)
.call()
.get(0);
RevTree tree = commit.getTree();
TreeWalk treeWalk = new TreeWalk(repo);
treeWalk.addTree(tree);
treeWalk.setRecursive(true);
treeWalk.setFilter(PathFilter.create(diffEntry.getOldPath()));
if (!treeWalk.next()) {
return null;
}
ObjectId objectId = treeWalk.getObjectId(0);
ObjectLoader loader = repo.open(objectId);
if (!toDir.mkdirs()){
throw new DocAsCodeException(
String.format("Failed to create directory '%s'.",toDir.getAbsolutePath()));
}
File file = new File(toDir,
diffEntry.getOldPath());
if (!file.exists() && !file.createNewFile()){
throw new DocAsCodeException(
String.format("Failed to create file '%s'.",file.getAbsolutePath()));
}
OutputStream out = new FileOutputStream(file);
loader.copyTo(out);
out.close();
return file;
} catch (IOException | GitAPIException e) {
throw new DocAsCodeException(
String.format(
"Unable to retrieve %s from %s",
path,
commit.getId()
),e);
}
}
}