GitPython `repo.index.commit()` порождает постоянный экземпляр git.exe, содержит дескрипторы для репо

Я пытаюсь использовать GitPython для некоторых манипуляций с репо, но столкнулся с проблемами с моим приложением, с открытыми ручками, где я не ожидал.

Ошибка, вызывающая проблему, кажется, что вызов repo.index.commit() приводит к дескриптору к каталогу (предположительно что-то в .git\). Позже это вызывает другие сбои в том, что пытается сделать мое приложение.

Вот рабочий юнит-тест:

import unittest
import git
import tempfile
import os.path

class Test(unittest.TestCase):

    def testCreateRepo(self):
        with tempfile.TemporaryDirectory(prefix=(__loader__.name) + "_") as mydir:

            # MAKE NEW REPO 
            repo = git.Repo.init(path=os.path.join(mydir, "newRepo"), mkdir=True)
            self.assertTrue(os.path.isdir(os.path.join(repo.working_dir, ".git")), "Failed to make new repo?")

            # MAKE FILE, COMMIT REPO
            testFileName = "testFile.txt"
            open(os.path.join(repo.working_dir, testFileName) , "w").close()
            repo.index.add([testFileName])
            self.assertTrue(repo.is_dirty())

            #### 
            # COMMENTING THIS OUT --> TEST PASSES
            repo.index.commit("added initial test file") 
            self.assertFalse(repo.is_dirty())
            #### 

            # adding this does not affect the handle
            git.cmd.Git.clear_cache()


            print("done") # exception thrown right after this, on __exit__

PermissionError: [WinError 32] Процесс не может получить доступ к файлу, поскольку он используется другим процессом: 'C:\Users\%USER%\AppData\Local\Temp\EXAMPLE_gitpython_v3kbrly_\newRepo'

копаясь немного глубже, кажется, что gitPython порождает несколько экземпляров процессов git.exe, и каждый из них содержит дескриптор корневой папки репозитория newRepo,

  • установите точку останова непосредственно перед ошибкой, используйте sysinternals / handle, чтобы увидеть открытые дескрипторы для newRepo... git.exe (точнее, 4 отдельных PID файла git.exe)
  • используя sysinternals/procxp, я вижу, что все они порождены из eclipse ->python

шаг за шагом, это вызов repo.index.commit(), который на самом деле приводит к появлению git.exe.

1 ответ

Решение

Работая с разработчиками gitpython, я нашел ответ:

Из-за внутреннего поведения кэширования gitpython вы должны принудительно запустить сборку мусора и сказать репо очистить его кеш. Я делал последнее, но не на том объекте.

следующее должно быть добавлено до очистки вашего каталога (__exit__()в мой with:/ выражение context-manager, в приведенном выше коде)

import gc
gc.collect()
repo.git.clear_cache()

Те, кажется, не подчиняются наименьшему удивлению:), надеюсь, API может быть улучшен в будущем.

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