Python 德威治备忘单:如何复制;git ls文件;?

Python 德威治备忘单:如何复制;git ls文件;?,python,git,dulwich,git-ls-files,Python,Git,Dulwich,Git Ls Files,亲爱的社区成员: 我正在开发一个代码分析系统,希望用Dulwich模块替换对CLI Git应用程序的调用。作为第一步,我需要将“git ls files”命令替换为等效的Dulwich命令。我是这样做的: import os import stat import subprocess from tempfile import TemporaryDirectory from dulwich import porcelain from dulwich.repo import Repo from d

亲爱的社区成员:

我正在开发一个代码分析系统,希望用Dulwich模块替换对CLI Git应用程序的调用。作为第一步,我需要将“git ls files”命令替换为等效的Dulwich命令。我是这样做的:

import os
import stat
import subprocess
from tempfile import TemporaryDirectory

from dulwich import porcelain
from dulwich.repo import Repo
from dulwich.objects import Commit, Tree

def _flatten_git_tree(r, object_sha, prefix=b'', sep=b'/'):

    result=[]

    git_object=r.get_object(object_sha)

    if git_object.type_name==b'tree':

        for item in git_object.iteritems():
            if stat.S_ISREG(item.mode):
                result.append(sep.join([prefix, item.path]))
            if stat.S_ISDIR(item.mode):
                result.extend(_flatten_git_tree(r, item.sha, prefix+sep+item.path, sep))

    if git_object.type_name==b'commit':

        result.extend(_flatten_git_tree(r, git_object.tree, prefix, sep))

    return result

def _run_git_cmd(git_arguments):

    return subprocess.Popen(git_arguments, stdout=subprocess.PIPE).communicate()[0]

with TemporaryDirectory() as temp_dir:

    git_clone_url=r"https://github.com/dulwich/dulwich.git"
    repo=porcelain.clone(git_clone_url, temp_dir, checkout=True)
    dulwich_ls_files=_flatten_git_tree(repo, repo.head())

    git_ls_files=_run_git_cmd(['git', '-C', os.path.join(temp_dir, 'dulwich'), 'ls-files'])
    git_ls_files=git_ls_files.decode('utf-8').splitlines()

assert len(dulwich_ls_files)==len(git_ls_files)
快速断言显示输出不同。原因可能是什么

在@jelmer的帮助下回答我自己的问题。问题的原因就在我评论的那一行。现在输出匹配

import os
import subprocess
from tempfile import TemporaryDirectory

from dulwich import porcelain
from dulwich.repo import Repo

def _run_git_cmd(git_arguments):

    return subprocess.Popen(git_arguments, stdout=subprocess.PIPE).communicate()[0]

with TemporaryDirectory() as temp_dir:

    git_clone_url=r"https://github.com/dulwich/dulwich.git"
    repo=porcelain.clone(git_clone_url, temp_dir)
    dulwich_ls_files=[path.decode('utf-8') for path in sorted(repo.open_index())]

    #git_ls_files=_run_git_cmd(['git', '-C', os.path.join(temp_dir, 'dulwich'), 'ls-files'])
    git_ls_files=_run_git_cmd(['git', '-C', temp_dir, 'ls-files'])
    git_ls_files=git_ls_files.decode('utf-8').splitlines()

print(len(dulwich_ls_files), len(git_ls_files))
大概是这样的:

from dulwich.repo import Repo
r = Repo('.')
index = r.open_index()
for path in sorted(index):
    print(path)

您能否显示
dulwich_ls_文件
git_ls_文件
以便我们进行比较?我不确定您在这里看到了什么区别,但总体策略是错误的:
git ls文件
在读取提交或树时读取索引。(
git ls files
也可以读取工作树,具体取决于您如何称呼它。)嗨@torek,谢谢您指出我的错误。你能提供一个德威治方法来解决这个问题吗?还有一点:据我所知,因为我对克隆的回购协议没有做任何更改,所以索引与工作树相匹配。我错了吗?@Wladd:我不熟悉德威治,所以我不知道如何让它通读索引内容。此时索引和工作树应该匹配,这是正确的。我的评论更像是一个重要的旁注。顺便说一句,还有两种模式需要检查:符号链接的S_iFlk,以及一种根本不是统计模式的160000,表示子模块(尽管这里没有任何有用的方法)。感谢@jelmer提供的优雅解决方案。在我的问题的答案中添加了它。