Я пытаюсь создать InMemoryGitRepository с нуля. В конечном счете, я хотел бы попробовать собственный DFSRepository в качестве git-бэкэнда, но для начала я поигрался с реализацией InMemoryRepository по умолчанию. Я знаю, как клонировать существующий репозиторий в InMemoryRepository, как уже упоминалось здесь, но мне сложно создать репозиторий с нуля и добавить файл. Я пробую следующее
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();
}
Однако я получаю следующую ошибку:
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)
Поскольку это репозиторий InMemory, я не должен устанавливать индексный файл или файл рабочего дерева, но похоже, что именно об этом говорится в сообщении об ошибке. Что мне не хватает?




По умолчанию статический вложенный класс InMemoryRepository.Builder создает пустой репозиторий. Это тоже доставило мне немало головной боли, но если вы вызовете repo.isBare(), вы увидите, что он на самом деле возвращает true, даже если setBare() не вызывается во время сборки.
Вы можете использовать Git.init(), чтобы создать новый непустой репозиторий и применить настройки из возвращенного InitCommand.
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();
}
}
В своем предыдущем ответе я сосредоточился на создании тестового репозитория и забыл о требованиях к памяти. InMemoryRepository может хранить репо, прочитанное из файловой системы или полученное с удаленного компьютера. Если ваша цель — просто протестировать некоторые вещи, вы можете написать тестовый класс, который устанавливает и удаляет репозиторий в вашей файловой системе в начале и конце цикла тестирования. Тестовый класс, основанный на вашем коде, может выглядеть так:
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();
}
}
AFAIK, вы не можете инициализировать непустой InMemoryRepository. Однако с помощью низкоуровневых API ObjectInserter, TreeFormatter, CommitBuilder и др. вы сможете фиксировать содержимое в базовом репозитории. Давным-давно я писал об этом здесь: codeaffine.com/2014/10/20/git-internals
@Joyjit Я обновил свой ответ. Извините, но в своем предыдущем ответе я забыл о требованиях к памяти.
Спасибо, теперь я понимаю основную причину, но с вашим решением я получаю FileRepository с каталогом .git, записанным в файловой системе. Нет ли способа создать InMemoryRepository с нуля и добавить/зафиксировать в нем файлы, не прибегая к файловой системе?