Получение удобочитаемых дисплеев различий в Mercurial в файлах Unicode (MS Windows)

Я пытаюсь сохранить скрипты Windows PowerShell в репозитории Mercurial. Похоже, что редактор PowerShell любит сохранять файлы как UTF-16 Unicode. Это означает, что существует много \0 байтов, которые Mercurial использует, чтобы различать «текстовые» и «двоичные» файлы. Я понимаю, что это не имеет значения для того, как Mercurial хранит данные, но это означает, что он отображает двоичные различия, которые довольно трудно читать. Есть ли способ сообщить Mercurial, что это действительно текстовые файлы? По-видимому, мне нужно было бы убедить Mercurial использовать внешнюю программу сравнения с Unicode для определенных типов файлов.


person Dan Menes    schedule 10.06.2010    source источник
comment
В частности, моя проблема связана со страницей текстовых различий в инструменте фиксации с использованием TortoiseHg, который обычно показывает красивую сводку изменений в выбранном файле, но показывает мусор с файлами UTF-16.   -  person Dan Menes    schedule 10.06.2010
comment
@orad: По состоянию на 22.09.2010 я так и не нашел ответа.   -  person Dan Menes    schedule 22.09.2010
comment
Ответ BOM.py будет работать. Просто скопируйте все это в файл, а затем отредактируйте (или создайте) файл users \ yourname \ Mercurial.ini и под строкой [extension] (добавьте ее, если такой строки нет) добавьте строку с именем = file (например, bom = C: \ path \ to \ the \ bom.py).   -  person Jaykul    schedule 03.07.2011


Ответы (3)


Возможно, это не имеет отношения к вам; прочтите последний абзац, если он не звучит так, как есть.

Я не уверен, что это то, что вам нужно, но мне нужны различия с содержимым 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 (или в ваши users \ username \ mercurial.ini) следующим образом:

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

Обратите внимание, что путь будет разным в Windows и Linux; в моей копии Windows я указал путь как \...\whatever (он находится на USB-диске, где буква диска может измениться). К сожалению, относительные пути берутся относительно текущего рабочего каталога, а не корня репозитория или чего-то подобного, но если вы сохраняете его на своем диске C :, вы можете просто указать полный путь.

В Linux (моя основная среда разработки) это хорошо работает; в командной строке (которую я до сих пор регулярно использую) в целом работает хорошо. Я никогда не пробовал его в PowerShell, но ожидал, что он будет лучше, чем командная строка, в том, что касается поддержки произвольных нулевых байтов в командной строке.

Я не уверен, что вы вообще этого хотите; кстати, вы сказали "двоичные различия", я подозреваю, что вы либо уже имеете это, либо делаете hg diff -a, что дает то же самое. В этом случае все, о чем я могу думать, - это написать другое расширение, которое принимает UTF-16LE и пытается декодировать его в UTF-8. Я не уверен в синтаксисе такого расширения, но могу попробовать.

Изменить: теперь просматривая ртутный источник через commands.py, cmdutil.py, patch.py ​​и mdiff.py, я вижу, что двоичные различия выполняются с кодировкой base85 (patch.b85diff), а не нормальный diff. Я не знал об этом, я думал, что это просто заставило его изменить это. В таком случае, возможно, этот текст все-таки уместен. Жду ответа, чтобы убедиться, что это так!

person Chris Morgan    schedule 14.11.2010
comment
Остерегаться! Хотя это расширение работает для различий в командной строке, у меня были проблемы с повреждением при создании патчей MQ через qnew. - person jwd; 12.06.2012

Я работал над этим, создав новый файл с помощью NotePad ++ и сохранив его как файл PowerShell (с расширением .ps1). NotePad ++ создаст файл как обычный текстовый файл ANSI. После создания я могу открыть файл в редакторе PowerShell и внести необходимые изменения без изменения редактором кодировки файла.

Отказ от ответственности: я столкнулся с этим всего несколько минут назад, поэтому я не уверен, есть ли какие-либо последствия, но пока мои скрипты работают нормально, а мои различия отображаются хорошо.

person Ryan Taylor    schedule 14.11.2010
comment
Преобразование в UTF-8 также работает для файлов .strings в Xcode (по умолчанию genstrings генерирует UTF-16LE) - person ; 23.06.2014

Если мой другой ответ не дает того, что вы хотите, я думаю, что это возможно; хотя я еще не тестировал его в Windows, он хорошо работает в Linux. Он делает потенциально неприятную вещь, оборачивая mercurial.mdiff.unidiff новой функцией, которая преобразует utf-16le в utf-8. Это не повлияет на hg st, но повлияет на hg diff. Одна потенциальная ошибка заключается в том, что спецификация также будет изменена с спецификации UTF-16LE на спецификацию UTF-8.

В любом случае, я думаю, это может быть вам полезно, так что вот оно.

Файл расширения 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

In .hgrc:

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

(Или эквивалентные пути.)

person Chris Morgan    schedule 14.11.2010
comment
К сожалению, этот подход страдает из-за проблемы с памятью: файлы "захлебываются" (ртутным, а не этим расширением), поэтому, если памяти мало, вы можете закончиться. Это требует, чтобы вы установили --config diff.nobinary=True (по личному опыту я знаю, что это испортит патчи mq, поэтому я не рекомендую постоянно держать его включенным), чтобы добраться до оболочки. - person bambams; 05.11.2015
comment
Я бы также рекомендовал if isinstance(a, str): и if isinstance(b, str), потому что при выполнении сравнения, когда в одной версии отсутствуют файлы, в другой есть эти переменные, могут быть NoneType и вызывать сбой расширения mercurial - person Scoopta; 23.08.2017