GitPython `repo.index.commit()` 生成持久性 git.exe 实例,持有 repo 的句柄

GitPython `repo.index.commit()` spawns persistent git.exe instance, holds handles to repo

我正在尝试使用 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 进程的多个实例,并且每个实例都持有 repo root 文件夹的句柄 newRepo.

单步执行,实际上是对 repo.index.commit() 的调用导致生成 git.exe(s)。

与 gitpython 开发人员合作,我找到了答案:

由于 gitpython 的内部缓存行为,您必须强制进行垃圾回收,并告诉 repo 清除它的缓存。我做的是后者,但是用错了对象。

在清理您的目录之前必须添加以下内容(__exit__()我的 with:/context-manager 子句,在上面的代码中)

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

那些似乎不服从 least-surprise :) 希望 api 可以在未来得到改进。