Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to "cat" a file in JGit?

Tags:

java

git

jgit

A while back I was looking for an embeddable distributed version control system in Java, and I think I have found it in JGit, which is a pure Java implementation of git. However, there is not much in the way of sample code or tutorials.

How can I use JGit to retrieve the HEAD version of a certain file (just like svn cat or hg cat whould do)?

I suppose this involves some rev-tree-walking and am looking for a code sample.

like image 724
Thilo Avatar asked Nov 06 '09 03:11

Thilo


3 Answers

Unfortunately Thilo's answer does not work with the latest JGit API. Here is the solution I found:

File repoDir = new File("test-git");
// open the repository
Repository repository = new Repository(repoDir);
// find the HEAD
ObjectId lastCommitId = repository.resolve(Constants.HEAD);
// now we have to get the commit
RevWalk revWalk = new RevWalk(repository);
RevCommit commit = revWalk.parseCommit(lastCommitId);
// and using commit's tree find the path
RevTree tree = commit.getTree();
TreeWalk treeWalk = new TreeWalk(repository);
treeWalk.addTree(tree);
treeWalk.setRecursive(true);
treeWalk.setFilter(PathFilter.create(path));
if (!treeWalk.next()) {
  return null;
}
ObjectId objectId = treeWalk.getObjectId(0);
ObjectLoader loader = repository.open(objectId);

// and then one can use either
InputStream in = loader.openStream()
// or
loader.copyTo(out)

I wish it was simpler.

like image 138
morisil Avatar answered Oct 16 '22 19:10

morisil


Here's a simpler version of @morisil's answer, using some of the concepts from @directed laugh's and tested with JGit 2.2.0:

private String fetchBlob(String revSpec, String path) throws MissingObjectException, IncorrectObjectTypeException,
        IOException {

    // Resolve the revision specification
    final ObjectId id = this.repo.resolve(revSpec);

    // Makes it simpler to release the allocated resources in one go
    ObjectReader reader = this.repo.newObjectReader();

    try {
        // Get the commit object for that revision
        RevWalk walk = new RevWalk(reader);
        RevCommit commit = walk.parseCommit(id);

        // Get the revision's file tree
        RevTree tree = commit.getTree();
        // .. and narrow it down to the single file's path
        TreeWalk treewalk = TreeWalk.forPath(reader, path, tree);

        if (treewalk != null) {
            // use the blob id to read the file's data
            byte[] data = reader.open(treewalk.getObjectId(0)).getBytes();
            return new String(data, "utf-8");
        } else {
            return "";
        }
    } finally {
        reader.close();
    }
}

repo is a Repository object as created in the other answers.

like image 40
creinig Avatar answered Oct 16 '22 18:10

creinig


I followed @Thilo's and @morisil's answer to get this, compatible with JGit 1.2.0:

File repoDir = new File("test-git/.git");
// open the repository
Repository repo = new Repository(repoDir);
// find the HEAD
Commit head = repo.mapCommit(Constants.HEAD);
// retrieve the tree in HEAD
Tree tree = head.getTree();

// 1.2.0 api version here
// find a file (as a TreeEntry, which contains the blob object id)
TreeWalk treewalk = TreeWalk.forPath(repo, "b/test.txt", tree);
// use the blob id to read the file's data
byte[] data = repo.open(treewalk.getObjectId(0)).getBytes();

I didn't test the Java version but it should work. It translates from

(.getBytes (.open repo (.getObjectId (TreeWalk/forPath repo "b/test.txt" tree) 0)))

in clojure (following the same setup as the top section), which does work.

like image 12
directed laugh Avatar answered Oct 16 '22 19:10

directed laugh