为什么脚本的行为与命令行vs git属性不同?

时间:2013-09-10 22:01:25

标签: python git gitattributes

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

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

我所拥有的是两个基于mercurial zipdoc功能建模的脚本。我试图做的就是在商店(filter.clean)上解压缩docx文件并在恢复(filter.smudge)上压缩它们。我有两个脚本运行良好,但一旦我将它们放入git属性,它们就无法工作,我不明白为什么。

我已经通过以下方式进行了测试

测试脚本(git bash)

  

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

     

$ cat uncompress.docx |蟒蛇   〜/ Documents / pyscripts / zip.py> compress.docx

     

$ md5sum uncompress.docx compress.docx

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

测试Git属性

  1. 我将它们设置为干净并擦洗到 cat ,验证我的文件保存并恢复没有问题。
  2. 我将clean设置为 python~ / Documents / pyscripts / unzip.py 。提交和签出后,文件现在变大(未压缩)但在MS-Word中打开时出错。此外,md5与上面的“仅脚本”测试不匹配。虽然文件大小相同。
  3. 我设置干净回到 cat 并将scrub设置为 python~ / Documents / pyscripts / zip.py 。提交和签出后,文件现在变小(压缩),但在MS-Word中打开时再次出错。同样,md5与“仅脚本”测试不同,但文件大小匹配。
  4. 设置clean和scrub到python脚本会产生错误,如预期的那样。
  5. 我真的迷失在这里,我认为git属性只是在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。

1 个答案:

答案 0 :(得分:1)

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

我没有对此进行过广泛的测试,但有些.docx内容可能无法很好地处理,但只有时间会证明。我的测试文件现在打开时没有出错,作为奖励,由于使用比标准.docx格式更高的压缩,工作目录中的.docx文件更小。

我已经确认在对.docx文件执行多次编辑和提交后,我可以打开文件,编辑一行,并提交一个添加到repo大小的大增量。例如,在repo历史记录中的3个先前编辑之后,在顶部添加了新行后,19KB文件在执行垃圾收集后在repo 中创建了仅1KB的增量。使用Mercurial运行相同的测试(尽可能接近)导致9.3KB增量提交。我不是Mercurial专家,我的理解是mercurial没有“gc”命令所以没有运行。