I've managed to get to grips with the basics of jGit file in terms of connecting to a repos and adding, commiting, and even looping of the commit messages for the files.
File gitDir = new File("/Users/myname/Sites/helloworld/.git");
RepositoryBuilder builder = new RepositoryBuilder();
Repository repository;
repository = builder.setGitDir(gitDir).readEnvironment()
.findGitDir().build();
Git git = new Git(repository);
RevWalk walk = new RevWalk(repository);
RevCommit commit = null;
// Add all files
// AddCommand add = git.add();
// add.addFilepattern(".").call();
// Commit them
// CommitCommand commit = git.commit();
// commit.setMessage("Commiting from java").call();
Iterable<RevCommit> logs = git.log().call();
Iterator<RevCommit> i = logs.iterator();
while (i.hasNext()) {
commit = walk.parseCommit( i.next() );
System.out.println( commit.getFullMessage() );
}
What I want to do next is be able to get all the commit message for a single file and then be able revert the single file back to a specific reference/point in time.
Here is how to find the changes of a commit based on all parent commits
var tree = new TreeWalk(repository)
tree.addTree(commit.getTree)
commit.getParents foreach {
parent => tree.addTree(parent.getTree)
}
tree.setFilter(TreeFilter.ANY_DIFF)
(scala code)
Note that TreeFilter.ANY_DIFF works for a single tree walker and will return all elements available in a root commit.
You would then have to iterate over the tree to see if your file is in the given delta (this is quite easy).
while (tree.next)
if (tree.getDepth == cleanPath.size) {
// we are at the right level, do what you want
} else {
if (tree.isSubtree &&
name == cleanPath(tree.getDepth)) {
tree.enterSubtree
}
}
}
(cleanPath is the pure in repo path, split by '/')
Now wrap that code into a RevWalk.next loop and you'll get the commits and files altered by the commit.
You may want to use a different filter than ANY_DIFF, because ANY_DIFF is true if one tree differs. This is a bit counter-intuitive in case of a merge where the blob didn't change compared to all parent trees. So here is the core of an ALL_DIFF, that will only show elements that differ from all parent trees:
override def include(walker: TreeWalk): Boolean = {
val n = walker.getTreeCount();
if (n == 1) {
return true;
}
val m = walker.getRawMode(0)
var i = 1
while (i < n) {
if (walker.getRawMode(i) == m && walker.idEqual(i, 0)) {
return false
}
i += 1
}
true
}
(scala code, derived from AnyDiffFilter)