【问题标题】:Uncompress OpenOffice files for better storage in version control解压缩 OpenOffice 文件以更好地存储版本控制
【发布时间】:2010-11-01 18:56:00
【问题描述】:

我听说过有关 OpenOffice (ODF) 文件如何成为 XML 和其他数据的压缩 zip 文件的讨论。因此,对文件进行微小的更改可能会完全更改数据,因此增量压缩在版本控制系统中效果不佳。

我已经对 OpenOffice 文件进行了基本测试,将其解压缩,然后以零压缩重新压缩。我使用 Linux zip 实用程序进行测试。 OpenOffice 仍然会愉快地打开它。

所以我想知道是否值得在我提交版本控制之前开发一个小实用程序来在 ODF 文件上运行。对这个想法有什么想法吗?可能有更好的选择?

其次,实现这个小实用程序的好方法是什么?调用 zip 的 Bash shell(可能仅限 Linux)? Python?你能想到什么陷阱吗?显然我不想意外损坏文件,并且有几种可能发生的方式。

我能想到的可能的陷阱:

  • 磁盘空间不足
  • 其他一些阻止写入文件或临时文件的权限问题
  • ODF 文档已加密(可能应该不理会这些;加密可能还会导致大文件更改,从而阻止有效的 delta 压缩)

【问题讨论】:

    标签: version-control openoffice.org


    【解决方案1】:

    首先,您要使用的版本控制系统应该支持挂钩,这些挂钩被调用以将文件从存储库中的版本转换为工作区中的版本,例如 Git 中来自 gitattributes 的 clean / smudge 过滤器。

    其次,您可以找到这样的过滤器,而不是自己编写一个,例如 rezip from "Management of opendocument (openoffice.org) files in git" thread on git mailing list(但请参阅“Followup: management of OO files - warning about "rezip" approach”中的警告),

    您也可以在“Tracking OpenOffice files/other compressed files with Git”线程中浏览答案,或尝试在“[PATCH 2/2] Add keyword unexpansion support to convert.c”线程中找到答案。

    希望有帮助

    【讨论】:

    • 很棒的信息。我目前对 Subversion 和 Mercurial 最感兴趣。我不认为 Subversion 具有干净/涂抹类型的功能。不知道 Mercurial - 我对此比较陌生。
    【解决方案2】:

    您可以考虑以 FODT 格式存储文档 - 平面 XML 格式。
    这是相对较新的替代解决方案。

    文档只是解压缩后存储的。

    更多信息请访问https://wiki.documentfoundation.org/Libreoffice_and_subversion

    【讨论】:

    • 对文档使用 *.fodt 和 *.fods 格式是将 libreoffice calc 和 writer 文件保存在版本控制中的最简单方法。不需要任何实用程序或花哨的提交钩子,纯文本版本控制的好处都在那里。
    【解决方案3】:

    我稍微修改了Craig McQueen's answer 中的python 程序。变化包括:

    • 实际上检查了 testZip 的返回(根据文档,看起来原始程序很乐意通过 checkzip 步骤处理损坏的 zip 文件)。

    • 重写 for 循环以检查已解压缩文件是否为单个 if 语句。

    这是新程序:

    #!/usr/bin/python
    # Note, written for Python 2.6
    
    import sys
    import shutil
    import zipfile
    
    # Get a single command-line argument containing filename
    commandlineFileName = sys.argv[1]
    
    backupFileName = commandlineFileName + ".bak"
    inFileName = backupFileName
    outFileName = commandlineFileName
    checkFilename = commandlineFileName
    
    # Check input file
    # First, check it is valid (not corrupted)
    checkZipFile = zipfile.ZipFile(checkFilename)
    
    if checkZipFile.testzip() is not None:
        raise Exception("Zip file is corrupted")
    
    # Second, check that it's not already uncompressed
    if all(f.compress_type==zipfile.ZIP_STORED for f in checkZipFile.infolist()):
        raise Exception("File is already uncompressed")
    
    checkZipFile.close()
    
    # Copy to "backup" file and use that as the input
    shutil.copy(commandlineFileName, backupFileName)
    inputZipFile = zipfile.ZipFile(inFileName)
    
    outputZipFile = zipfile.ZipFile(outFileName, "w", zipfile.ZIP_STORED)
    
    # Copy each input file's data to output, making sure it's uncompressed
    for fileObject in inputZipFile.infolist():
        fileData = inputZipFile.read(fileObject)
        outFileObject = fileObject
        outFileObject.compress_type = zipfile.ZIP_STORED
        outputZipFile.writestr(outFileObject, fileData)
    
    outputZipFile.close()
    

    【讨论】:

      【解决方案4】:

      这是我偶然发现的另一个程序:store_zippies_uncompressed,作者是 Mirko Friedenhagen。

      wiki 还展示了如何将其与 Mercurial 集成。

      【讨论】:

        【解决方案5】:

        这是我整理的 Python 脚本。到目前为止,它的测试很少。我已经在 Python 2.6 中完成了基本测试。但总的来说,我更喜欢 Python 的想法,因为如果发生任何错误,它应该异常中止,而 bash 脚本可能不会。

        这首先检查输入文件是否有效且尚未解压缩。然后它将输入文件复制到扩展名为“.bak”的“备份”文件中。然后它解压缩原始文件,覆盖它。

        我确定有些事情我忽略了。请随时提供反馈。

        
        #!/usr/bin/python
        # Note, written for Python 2.6
        
        import sys
        import shutil
        import zipfile
        
        # Get a single command-line argument containing filename
        commandlineFileName = sys.argv[1]
        
        backupFileName = commandlineFileName + ".bak"
        inFileName = backupFileName
        outFileName = commandlineFileName
        checkFilename = commandlineFileName
        
        # Check input file
        # First, check it is valid (not corrupted)
        checkZipFile = zipfile.ZipFile(checkFilename)
        checkZipFile.testzip()
        
        # Second, check that it's not already uncompressed
        isCompressed = False
        for fileObject in checkZipFile.infolist():
            if fileObject.compress_type != zipfile.ZIP_STORED:
                isCompressed = True
        if isCompressed == False:
            raise Exception("File is already uncompressed")
        
        checkZipFile.close()
        
        # Copy to "backup" file and use that as the input
        shutil.copy(commandlineFileName, backupFileName)
        inputZipFile = zipfile.ZipFile(inFileName)
        
        outputZipFile = zipfile.ZipFile(outFileName, "w", zipfile.ZIP_STORED)
        
        # Copy each input file's data to output, making sure it's uncompressed
        for fileObject in inputZipFile.infolist():
            fileData = inputZipFile.read(fileObject)
            outFileObject = fileObject
            outFileObject.compress_type = zipfile.ZIP_STORED
            outputZipFile.writestr(outFileObject, fileData)
        
        outputZipFile.close()
        
        

        这是Mercurial repository in BitBucket

        【讨论】:

          【解决方案6】:

          如果您不需要节省存储空间,而只是希望能够对存储在您的版本控制系统中的 OpenOffice.org 文件进行比较,您可以使用 oodiff page 上的说明,其中介绍了如何使 oodiff git 和 mercurial 下 OpenDocument 格式的默认差异。 (它也提到了SVN,但我已经很久没有经常使用SVN了,我不确定这些是说明还是限制。)

          (我使用 Mirko Friedenhagen's page 找到了这个(上面由 Craig McQueen 引用))

          【讨论】:

            猜你喜欢
            • 2011-04-15
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-02-25
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多