I am trying to create an InMemoryGitRepository
from scratch. Ultimately, I would like to try a custom DFSRepository
as git backend, but to begin with I was playing around with the default implementation of InMemoryRepository
. I know how to clone an existing repo into InMemoryRepository
as mentioned here but I am having a tough time on how to create the repo from scratch and add a file. I am trying the following
private static void initInMemoryGit() throws IOException, GitAPIException {
DfsRepositoryDescription repoDesc = new DfsRepositoryDescription("test");
//InMemoryRepository repo = new InMemoryRepository(repoDesc);
InMemoryRepository repo = new InMemoryRepository.Builder().setRepositoryDescription(repoDesc)
.setInitialBranch("master")
.build();
repo.create();
Git git = new Git(repo);
File textFile = new File("/tmp/TestGitRepository", "test.txt");
Files.write(textFile.toPath(), "hi".getBytes());
git.add().addFilepattern(textFile.getName()).call();
git.commit().setMessage("hi").call();
}
However, I am getting the following error:
Exception in thread "main" org.eclipse.jgit.errors.NoWorkTreeException: Bare Repository has neither a working tree, nor an index
at org.eclipse.jgit.lib.Repository.getIndexFile(Repository.java:1200)
at org.eclipse.jgit.dircache.DirCache.lock(DirCache.java:259)
at org.eclipse.jgit.lib.Repository.lockDirCache(Repository.java:1282)
at org.eclipse.jgit.api.AddCommand.call(AddCommand.java:122)
at oracle.bi.versioncontrol.jgit.JGitVersionInMemory.initInMemoryGit(JGitVersionInMemory.java:114)
at oracle.bi.versioncontrol.jgit.JGitVersionInMemory.main(JGitVersionInMemory.java:51)
Since it is an InMemory Repo, I am not supposed to set the Index File or Working Tree File, but looks like that's what the error message is saying. What am I missing?
By default, the static nested class InMemoryRepository.Builder
builds a bare repository. It gave me quite of a headache too, but if you invoke repo.isBare()
, you can see that it actually returns true even if setBare()
isn't called during the build.
You could use Git.init()
to create a new non-bare repository, and apply your configurations from the InitCommand
returned.
public static void initInMemoryGit() throws IOException, GitAPIException {
File textFile = new File("./tmp/TestGitRepository/test.txt");
try (Git git = Git.init().setInitialBranch("master").setDirectory(new File("./tmp/TestGitRepository")).call()) {
git.add().addFilepattern(textFile.getName()).call();
git.commit().setMessage("hi").call();
}
}
In my previous response I was focused on creating a test repository and forgot about the in memory requirement. An InMemoryRepository
can hold a repo read from the file system or pulled from a remote. If your goal is to just test some things, you could write a test class that sets up and tears down the repo on your file system at the beginning and end of the test cycle. A test class based on your code could look like this:
public class TestGit {
private static Git git;
@BeforeAll
public static void setup() throws GitAPIException {
git = Git.init().setInitialBranch("master").setDirectory(new File("./tmp/TestGitRepository")).call();
}
@Test
public void testCommit() throws GitAPIException {
File textFile = new File("./tmp/TestGitRepository/test.txt");
git.add().addFilepattern(textFile.getName()).call();
git.commit().setMessage("hi").call();
List<RevCommit> commits = StreamSupport.stream(git.log().setMaxCount(1).call().spliterator(), false).toList();
RevCommit commit = commits.get(0);
Assertions.assertEquals(commit.getFullMessage(), "hi");
}
@AfterAll
public static void tearDown() throws IOException {
git.close();
deleteDirectory(new File("./tmp/TestGitRepository/.git"));
}
private static boolean deleteDirectory(File dir) {
File[] files = dir.listFiles();
if (files != null) {
for (File file : files) {
deleteDirectory(file);
}
}
return dir.delete();
}
}