4

I am trying to add submodules support to a project of mine, however I seem to be unable to use JGit to read specific commits or to log, while commandline git can do this just fine, despite the detached head that the submodule is in (as far as by design of how submodules work).

I have code like this, with "fuse-jna" being the submodule:

    FileRepositoryBuilder builder = new FileRepositoryBuilder();
    Repository repository = builder.setGitDir(new File("fuse-jna/.git"))
      .readEnvironment() // scan environment GIT_* variables
      .findGitDir() // scan up the file system tree
      .build();

    ObjectId lastCommitId = repository.resolve("39c1c4b78ff751b0b9e28f4fb35148a1acd6646f");

    Iterable<RevCommit> commits = new Git(repository).log().add(lastCommitId).call();
    for(RevCommit commit : commits) {
        System.out.println("Commit: " + commit.getId());
    }

with this I get:

org.eclipse.jgit.errors.MissingObjectException: Missing commit 39c1c4b78ff751b0b9e28f4fb35148a1acd6646f
at org.eclipse.jgit.internal.storage.file.WindowCursor.open(WindowCursor.java:149)
at org.eclipse.jgit.revwalk.RevWalk.getCachedBytes(RevWalk.java:883)
at org.eclipse.jgit.revwalk.RevCommit.parseHeaders(RevCommit.java:145)
at org.eclipse.jgit.revwalk.RevWalk.markStart(RevWalk.java:279)
at org.eclipse.jgit.api.LogCommand.add(LogCommand.java:330)
at org.eclipse.jgit.api.LogCommand.add(LogCommand.java:189)
at org.dstadler.jgitfs.util.JGitHelperTest.testGitLinkRepository(JGitHelperTest.java:638)

However on the commandline in the "fuse-jna" directory

git diff 39c1c4b78ff751b0b9e28f4fb35148a1acd6646f~

works just fine, so it is possible to do this.

Is there some other way how to do this with JGit? Or is support for submodules not fully there yet?

centic
  • 15,565
  • 9
  • 68
  • 125
  • FYI, also using the internal ".git/modules/fuse-jna/.git" does not work. Furthermore "repository.getAllRefs()" returns an empty list as well, so no refs are found at all here... – centic Sep 28 '14 at 22:07
  • I don't know how JGit works, but regarding submodules, they are basically repositories of their own. On the commandline you can also only see their commits when you're inside the submodule's directory. With JGit, are you trying it from the submodule's directory or the main repository's directory? – gitaarik Sep 28 '14 at 22:15
  • In the code listd in the question I was trying to open the submodule-repository like a normal Git repository, but this seems to not be what JGit requires here, see my self-answer below. – centic Sep 28 '14 at 22:43

1 Answers1

2

Seems the trick is to not open the repository of the submodule like a normal Git repository, but use the JGit class SubmoduleWalk and the parent-repository to do this!

The following did work for me after playing around with it some more:

     Repository subRepo = SubmoduleWalk.getSubmoduleRepository(repository, "fuse-jna");
centic
  • 15,565
  • 9
  • 68
  • 125
  • 1
    While `SubmoduleWalk.getSubmoduleRepository`works just fine, I'd like to clarify _why_ the `FileRepositoryBuilder` approach failed: the `setGitDir()` call specified a *relative path* (to the applications' work dir). If that was changed to `setGitDir( new File( parentRepo.getWorkTree(), "fuse-jna/.git" ) )` the sub-repository would also be found. If you take a look at `getSubmoduleRepository()` you'll find that similar code is used there. – Rüdiger Herrmann Sep 29 '14 at 08:16
  • 1
    Thanks a lot for the additional explanation, seems I did not read up enough on the repository builder classes here, the details seem to be hidden in the code a bit and setGitDir() worked for all my other use-cases so far whereas setWorkTree() is likely a better choice for most cases... – centic Sep 29 '14 at 12:31
  • I would still recommend to [prefer setGitDir() over setWorkDir](http://www.codeaffine.com/2014/09/22/access-git-repository-with-jgit/). The mistake in the code snippet of your question is to use a relative path ("fuse-jna/.git") instead of an absolute ("/path/to/parent-repo/fuse-jna/.git"). A relative path is interpreted relative to your **program's working directory** (not to confuse with the repository work dir) and wouldn't work with setWorkDir() either. – Rüdiger Herrmann Sep 29 '14 at 13:22
  • Hmm, in my case program working dir and git repository directory were identical as I used the git repository of the project itself for testing it, so based on this it should have worked with both setGitDir() and setWorkDir() with relative paths as well! I'll do some more tests later to see where the actual difference is. – centic Sep 29 '14 at 14:03
  • 1
    Actually, using `setGitDir()` does not work, as illustrated on https://github.com/centic9/jgit-cookbook/issues/81 - the problem is that `findGitDir()` only performs the discovery if the `gitDir` property is not already set. – Vlad Jul 19 '21 at 10:30