在Mercurial中获取可读的差异显示在Unicode文件(MS Windows)

我试图在Mercurial存储库中存储一些Windows PowerShell脚本。 看来PowerShell编辑器喜欢将文件保存为UTF-16 Unicode。 这意味着有很多\0字节,这是Mercurial用来区分“文本”和“二进制”文件的。 我知道这对于Mercurial如何存储数据没有任何影响,但是这意味着它会显示二进制差异,这是难以阅读的。 有没有办法告诉Mercurial这些确实是文本文件? 据推测,我需要说服Mercurial使用一个外部Unicode识别diff程序的特定文件types。

这可能与你无关; 阅读最后一段,如果听起来不是这样的话。

我不确定这是否是你所需要的,但是我需要比UTF-16LE更多的内容,而不仅仅是“二进制文件是不同的” – 当我在几个月前搜索了它,我发现了一个线程和讨论它的错误; 这是它的一部分 。 现在我找不到这个迷你扩展的原始源代码(虽然它只是做了那个补丁),但是我得到的是一个扩展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(或您的用户\用户名\ mercurial.ini)像这样:

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

注意路径在Windows和Linux之间会有所不同; 在我的Windows副本上,我把路径作为\...\whatever (它是在一个USB磁盘驱动器号可以更改)。 不幸的是,相对路径是相对于当前的工作目录而不是存储库的根或任何这样的事情,但如果你将它保存在你的C盘上,你可以把完整的路径。

在Linux(我的主要开发环境)中,这个效果很好; 在命令提示符(我仍然使用),它通常运作良好。 我从来没有在PowerShell中尝试过,但是我希望它比Command Prompt更好地支持命令行中的任意空字节。

我不确定这是不是你想要的; 通过你说的“二进制差异”的方式,我怀疑你可能已经有这个或正在做hg diff -a这是实现相同的事情。 在这种情况下,我所能想到的就是编写另一个扩展,它接受UTF-16LE并尝试将其解码为UTF-8。 我不确定这样的扩展的语法,但我可能会尝试。

编辑:现在已经通过commands.py,cmdutil.py,patch.py​​和mdiff.py拖曳mercurial源,我看到二进制差异是用base85编码(patch.b85diff),而不是正常的差异。 我没有意识到这一点,我认为这只是迫使它来分化。 在这种情况下,或许这个文本毕竟相关的。 我等待回应,看看是不是!

我已经解决了这个问题,用NotePad ++创建一个新文件并将其保存为一个PowerShell文件(.ps1扩展名)。 NotePad ++将以纯文本ANSI文件的形式创建该文件。 一旦创建,我可以在PowerShell编辑器中打开文件,并根据需要进行任何更改,而无需编辑器修改文件编码。

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

如果我的其他答案没有做你想做的,我想这个可能; 虽然我还没有在Windows上进行过测试,但它在Linux中运行良好。 它会做一个可能是一件令人讨厌的事情,用一个将utf-16le转换为utf-8的新函数来包装mercurial.mdiff.unidiff 。 这不会影响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 

(或者等同的路径)