python - 为什么从命令行调用的脚本与从 git 属性调用的脚本的行为不同?

标签 python git gitattributes

下面附有更新的脚本,这些脚本现在正在我的示例文档中运行

为什么以下 python 脚本在通过 git 属性或从命令行调用时执行不同?

我有两个基于 Mercurial zipdoc 功能建模的脚本。我想做的就是在存储上解压缩 docx 文件 (filter.clean) 并在恢复时压缩它们 (filter.smudge)。我有两个脚本运行良好,但是一旦我将它们放入 git 属性,它们就不起作用,我不明白为什么。

我已经通过执行以下操作进行了测试

测试脚本 (git bash)

$ cat original.docx | python ~/Documents/pyscripts/unzip.py > uncompress.docx

$ cat uncompress.docx | python ~/Documents/pyscripts/zip.py > compress.docx

$ md5sum uncompress.docx compress.docx

我可以使用 Microsoft Word 打开未压缩和压缩的文件,没有错误。脚本按预期工作。

测试 Git 属性

  1. 我将clean和scrub都设置为cat,验证了我的文件保存和恢复没有问题。
  2. 我将 clean 设置为python ~/Documents/pyscripts/unzip.py。提交和 checkout 后,文件现在更大(未压缩),但在 MS-Word 中打开时出现错误。此外,md5 与上面的“仅脚本”测试不匹配。尽管文件大小是相同的。
  3. 我将 clean 设置回 cat 并将磨砂设置为 python ~/Documents/pyscripts/zip.py。提交和 checkout 后,文件现在较小(压缩),但在 MS-Word 中打开时再次出错。 md5 再次与“仅脚本”测试不同,但文件大小匹配。
  4. 正如预期的那样,为 python 脚本设置 clean 和 scrap 会产生错误。

我真的迷失了方向,我认为 git Attributes 只是在 stdin 上提供输入并从 stdout 读取它。我已经测试了这两个脚本,可以很好地使用来自 cat 的管道和来自输出的重定向。我知道脚本正在运行 b/c 文件大小按预期更改,但是在文件中的某处引入了一个小更改。

其他引用

我在Win7上使用msgit,上面的所有命令都是在git bash窗口中输入的。

Git Attributes Description

解压缩脚本

import fileinput
import sys
import zipfile

# Set stdin and stdout to binary read/write
if sys.platform == "win32":
    import os, msvcrt
    msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
    msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY)

try:
  from cStringIO import StringIO
except:
  from StringIO import StringIO

# Wrap stdio into a file like object
inString = StringIO(sys.stdin.read())
outString = StringIO()

# Store each member uncompressed
try:
    with zipfile.ZipFile(inString,'r') as inFile:
        outFile = zipfile.ZipFile(outString,'w',zipfile.ZIP_STORED)
        for memberInfo in inFile.infolist():
            member = inFile.read(memberInfo)
            memberInfo.compress_type = 0
            outFile.writestr(memberInfo,member)
        outFile.close()
except zipfile.BadZipfile:
    sys.stdout.write(inString.getvalue())

sys.stdout.write(outString.getvalue())

压缩脚本

import fileinput
import sys
import zipfile

# Set stdin and stdout to binary read/write
if sys.platform == "win32":
    import os, msvcrt
    msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
    msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY)

try:
  from cStringIO import StringIO
except:
  from StringIO import StringIO

# Wrap stdio into a file like object
inString = StringIO(sys.stdin.read())
outString = StringIO()

# Store each member compressed
try:
    with zipfile.ZipFile(inString,'r') as inFile:
        outFile = zipfile.ZipFile(outString,'w',zipfile.ZIP_DEFLATED)
        for memberInfo in inFile.infolist():
            member = inFile.read(memberInfo)
            memberInfo.compress_type = zipfile.ZIP_DEFLATED
            outFile.writestr(memberInfo,member)
        outFile.close()
except zipfile.BadZipfile:
    sys.stdout.write(inString.getvalue())

sys.stdout.write(outString.getvalue())

编辑:格式 编辑 2:更新脚本以在文件处理期间写入内存而不是 stdout。

最佳答案

我发现使用 zipfile.ZipFile() 且目标为 stdout 会导致问题。打开目标为 StringIO() 的 zip 文件,然后最后将完整的 StringIO 文件写入 stdout 就解决了该问题。

我还没有对此进行广泛的测试,有些 .docx 内容可能无法得到很好的处理,但只有时间才能证明一切。我的测试文件现在打开时没有错误,而且由于使用比标准 .docx 格式更高的压缩,工作目录中的 .docx 文件更小。

我已经确认,在对 .docx 文件执行多次编辑和提交后,我可以打开该文件,编辑一行,然后提交,而不会在存储库大小中添加较大的增量。例如,一个 19KB 的文件,在存储库历史记录中进行了 3 次编辑后,在顶部添加了新行,在执行垃圾收集后,存储库中仅创建了 1KB 的增量。。使用 Mercurial 运行相同的测试(尽可能接近)会产生 9.3KB 的增量提交。我不是 Mercurial 专家,我的理解是 Mercurial 没有“gc”命令,因此没有运行任何命令。

关于python - 为什么从命令行调用的脚本与从 git 属性调用的脚本的行为不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18729473/

相关文章:

python - 从给定字符串中删除偶数个连续重复字符

python - 为什么 np.dot 比使用 for 循环求点积快得多

python - 通过基于随机值的过滤,使用列表理解生成 10 个(或更少)均匀分布的随机 float

macos - Github Mac权限问题

git-tag 仅列出那些位于或低于当前 HEAD 的标签

ruby - filter执行时如何通过gitattributes判断被过滤的文件?

python - 由重叠的低位部分和高位部分组成的组合数

git - 向 .gitattributes 添加评论/备注

git - .gitattributes merge 驱动程序未使用

git - 为什么顺序是 git add --all、git commit、然后 git push 跳过文件?