代码之家  ›  专栏  ›  技术社区  ›  Dan Menes

在Unicode文件(MS Windows)上以Mercurial格式获取可读的差异显示

  •  24
  • Dan Menes  · 技术社区  · 15 年前

    我正试图将一些windows powershell脚本存储在mercurial存储库中。powershell编辑器似乎喜欢将文件保存为utf-16unicode格式。这意味着有很多 \0 字节,这是Mercurial用来区分“文本”和“二进制”文件的。我知道这对Mercurial存储数据的方式没有影响,但它确实意味着它显示二进制差异,这有点难读。有没有办法告诉Mercurial这些真的是文本文件?大概我需要说服mercurial为特定的文件类型使用一个外部的unicode感知diff程序。

    3 回复  |  直到 15 年前
        1
  •  3
  •   Jaykul    14 年前

    这可能与你无关;如果最后一段听起来不像,请阅读它。

    我不确定这是否是你所需要的,但我需要的是utf-16le内容的差异,而不仅仅是“二进制文件是不同的”——几个月前,当我搜索它时,我发现了一个线程和一个bug在讨论它; here's part of it .我现在找不到这个小扩展的原始源代码(尽管它正在做那个补丁所做的事情),但是我得到的是一个扩展, BOM.py 以下内容:

    #!/usr/bin/env python
    
    from mercurial import hg, util
    
    import codecs
    
    boms = [
        codecs.BOM_UTF8,
        codecs.BOM_UTF16_BE, codecs.BOM_UTF16_LE,
        codecs.BOM_UTF32_BE, codecs.BOM_UTF32_LE
        ]
    
    def binary(s):
        if s:
            for bom in boms:
                if s.startswith(bom):
                    return False
            return '\0' in s
        return False
    
    
    def reposetup(ui, repo):
        util.binary = binary
    

    这将加载到.hgrc(或users\username\mercurial.ini)中,如下所示:

    [extensions]
    bom = ~/.hgexts/BOM.py
    

    注意,路径在Windows和Linux之间会有所不同;在我的Windows副本上,我将路径设置为 \...\whatever (它放在U盘上,驱动器号可以更改)。不幸的是,相对路径是相对于当前的工作目录而不是存储库根目录或任何类似的内容,但是如果您将其保存在c:drive中,您可以只放置完整的路径。

    在linux(我的主要开发环境)中,这很好地工作;在command prompt(我仍然经常使用)中,它通常工作得很好。我从未在powershell中尝试过,但我希望它比command prompt更好地支持命令行中的任意空字节。

    我不确定这是否是你想要的;顺便说一句“二进制差异”,我怀疑你可能已经有了这个或者正在做 hg diff -a 这是在实现同样的目标。在这种情况下,我所能想到的就是编写另一个扩展,它采用utf-16le并试图将其解码为utf-8。我不确定这样一个扩展的语法,但我可以试试。

    编辑: 现在通过commands.py、cmdutil.py、patch.py和mdiff.py搜索了Mercurial源代码,我发现二进制diff是用base85编码(patch.b85diff)而不是普通的diff完成的。我不知道,我以为它只是强迫它进行diff。在这种情况下,也许这段文字 毕竟是相关的。我在等待回应,看看是不是!

        2
  •  2
  •   Ryan Taylor    14 年前

    我用notepad++创建了一个新文件,并将其保存为powershell文件(.ps1扩展名)。记事本++将创建一个纯文本ANSI文件。创建后,我可以在powershell编辑器中打开文件,并根据需要进行任何更改,而无需编辑器修改文件编码。

    免责声明:我刚才遇到这个,所以我不确定是否有任何影响,但到目前为止,我的脚本工作正常,我的差异显示良好。

        3
  •  1
  •   Chris Morgan    14 年前

    如果我的另一个答案不符合您的要求,我想这一个可能会;虽然我还没有在windows上测试过它,但它在linux上运行得很好。它在包装上做了一件潜在的坏事 mercurial.mdiff.unidiff 使用一个新函数将utf-16le转换为utf-8。这不会影响 hg st ,但会影响 hg diff .一个潜在的陷阱是bom也将从utf-16le bom更改为utf-8 bom。

    不管怎样,我想这对你可能有用,所以就在这里。

    扩展文件 utf16decodediff.py 以下内容:

    import codecs
    from mercurial import mdiff
    
    unidiff = mdiff.unidiff
    
    def new_unidiff(a, ad, b, bd, fn1, fn2, r=None, opts=mdiff.defaultopts):
        """
        A simple wrapper around mercurial.mdiff.unidiff which first decodes
        UTF-16LE text.
        """
    
        if a.startswith(codecs.BOM_UTF16_LE):
            try:
                # Gets reencoded as utf-8 to be a str rather than a unicode; some
                # extensions may expect a str and may break if it's wrong.
                a = a.decode('utf-16le').encode('utf-8')
            except UnicodeDecodeError:
                pass
    
        if b.startswith(codecs.BOM_UTF16_LE):
            try:
                b = b.decode('utf-16le').encode('utf-8')
            except UnicodeDecodeError:
                pass
    
        return unidiff(a, ad, b, bd, fn1, fn2, r, opts)
    
    mdiff.unidiff = new_unidiff
    

    .hgrc 以下内容:

    [extensions]
    utf16decodediff = ~/.hgexts/utf16decodediff.py
    

    (或等效路径。)