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 может быть улучшен в будущем.