Инициализируйте InMemoryRepository с помощью Jgit с нуля

Я пытаюсь создать 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, я не должен устанавливать индексный файл или файл рабочего дерева, но похоже, что именно об этом говорится в сообщении об ошибке. Что мне не хватает?

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
0
74
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

По умолчанию статический вложенный класс 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();
    }
}

Спасибо, теперь я понимаю основную причину, но с вашим решением я получаю FileRepository с каталогом .git, записанным в файловой системе. Нет ли способа создать InMemoryRepository с нуля и добавить/зафиксировать в нем файлы, не прибегая к файловой системе?

Joyjit 06.05.2024 23:21

AFAIK, вы не можете инициализировать непустой InMemoryRepository. Однако с помощью низкоуровневых API ObjectInserter, TreeFormatter, CommitBuilder и др. вы сможете фиксировать содержимое в базовом репозитории. Давным-давно я писал об этом здесь: codeaffine.com/2014/10/20/git-internals

Rüdiger Herrmann 07.05.2024 09:57

@Joyjit Я обновил свой ответ. Извините, но в своем предыдущем ответе я забыл о требованиях к памяти.

dani-vta 07.05.2024 10:48

Другие вопросы по теме