5

我正在开发一个将在 git repo 中添加和更新文件的程序。由于我无法确定我正在使用的文件当前是否在 repo 中,我需要检查它的存在 - 这个操作似乎比我想象的要难。

'in' 比较似乎不适用于 gitpython 中树的非根级别。前任。

>>> repo = Repo(path)
>>> hct = repo.head.commit.tree
>>>> 'A' in hct['documents']
False
>>> hct['documents']['A']
<git.Tree "8c74cba527a814a3700a96d8b168715684013857">

所以我想知道,人们如何在尝试处理给定文件之前检查给定文件是否在 git 树中?尝试访问不在树中的文件的对象将引发 KeyError,因此我可以尝试捕获。但这感觉像是在例行存在检查中使用异常处理很糟糕。

我错过了一些非常明显的事情吗?如何使用 gitpython(或 Python 中的任何库/方法)检查​​提交树中是否存在文件?

自我回答

好的,我在Tree 类中四处挖掘,看看 __contains__ 做了什么。事实证明,在子文件夹中搜索时,必须使用来自 repo 根目录的完整相对路径来检查文件是否存在。所以我上面所做的检查的工作版本是:

>>> 'documents/A' in hct['documents']
True
4

3 回答 3

4

EricP 的答案有一个错误。这是一个固定版本:

def fileInRepo(repo, filePath):
    '''
    repo is a gitPython Repo object
    filePath is the full path to the file from the repository root
    returns true if file is found in the repo at the specified path, false otherwise
    '''
    pathdir = os.path.dirname(filePath)

    # Build up reference to desired repo path
    rsub = repo.head.commit.tree

    for path_element in pathdir.split(os.path.sep):

        # If dir on file path is not in repo, neither is file. 
        try : 
            rsub = rsub[path_element]

        except KeyError : 

            return False

    return(filePath in rsub)

用法:

file_found = fileInRepo(repo, 'documents/A')

这与 EricP 的代码非常相似,但会处理包含文件的文件夹不在 repo 中的情况。在这种情况下, EricP 的函数会引发 a KeyError。此函数返回False.

(我提出编辑 EricP 的代码但被拒绝了。)

于 2014-09-21T16:07:25.497 回答
2

扩展 Bill 的解决方案,这是一个确定文件是否在 repo 中的函数:

def fileInRepo(repo,path_to_file):
    '''
    repo is a gitPython Repo object
    path_to_file is the full path to the file from the repository root
    returns true if file is found in the repo at the specified path, false otherwise
    '''
    pathdir = os.path.dirname(path_to_file)

    # Build up reference to desired repo path
    rsub = repo.head.commit.tree
    for path_element in pathdir.split(os.path.sep):
        rsub = rsub[path_element]
    return(path_to_file in rsub)

示例用法:

file_found = fileInRepo(repo, 'documents/A')
于 2013-01-16T17:46:29.547 回答
0

如果你想省略 catch 尝试,你可以检查对象是否在 repo 中:

def fileInRepo(repo, path_to_file):
    dir_path = os.path.dirname(path_to_file)
    rsub = repo.head.commit.tree
    path_elements = dir_path.split(os.path.sep)
    for el_id, element in enumerate(path_elements):
        sub_path = os.path.join(*path_elements[:el_id + 1])
        if sub_path in rsub:
            rsub = rsub[element]
        else:
            return False
    return path_to_file in rsub

或者您可以遍历 repo 中的所有项目,但它肯定会更慢:

def isFileInRepo(repo, path_to_file):
    rsub = repo.head.commit.tree
    for element in rsub.traverse():
        if element.path == path_to_file:
            return True
    return False
于 2020-06-14T22:10:01.567 回答