Регистрозависимые различия в Mercurial - PullRequest
7 голосов
/ 06 марта 2010

Я использую Mercurial (в частности TortoiseHg для Windows) для контроля версий кода VBA. Любой, кто пробовал это, знает, что VBA изменяет регистр каждой переменной в проекте, когда любое объявление этой переменной изменяется в любом месте проекта (независимо от области действия). Это делает контроль версий кошмаром.

Я бы хотел игнорировать изменения регистра в моем исходном коде при выполнении различий . Какой самый простой способ сделать это? (какой-то вариант для diff, который мне не хватает, внешняя утилита diff, что-то еще?)

ПРИМЕЧАНИЕ. Я не говорю о «именах файлов без учета регистра» (да, я говорю с вами, Google ...)

Ответы [ 3 ]

7 голосов
/ 06 марта 2010

Вы можете сделать это при различий для потребления на экране, используя ExtDiff Extension .

  [extensions]
  hgext.extdiff =

  [extdiff]
  # add new command that runs GNU diff(1) in case-insensitive mode
  cmd.mydiff = diff
  opts.mydiff = -i

Тогда вы запустите hg mydiff из командной строки. Это, конечно, требует, чтобы у вас был установлен бинарный файл diff, будь то GNU или другой.

Однако, это не так полезно, как хотелось бы, потому что внутренне, конечно, Mercurial не может игнорировать регистр - он принимает криптографический хэш содержимого файла, а те не дают места для маневра. Поэтому, если вы настроите эту настройку, вы выполните hg mydiff и не увидите никаких изменений, а затем выполните hg commit и увидите изменения повсюду.

Так что вы можете заставить это работать на экране, но не принципиально.

Один из вариантов - найти базовый визуальный очиститель кода, подобный indent для C-подобных языков, который нормализует регистр переменных и запускает его в обработчике mercurial commit. Тогда по крайней мере весь код, входящий в систему контроля версий, будет согласованным, и вы сможете точно различать ревизии.

2 голосов
/ 13 октября 2015

Вот решение, на котором я остановился.Это далеко от идеала, но лучше, чем другие альтернативы, которые я рассмотрел.

Я создал скрипт Autohotkey, который выполняет следующее:

  • возвращает файлы MS Access в хранилище с помощьюобнаруженные изменения (в файлы .orig)
  • читает в файле .orig (тот, что с изменениями)
  • читает в существующем файле (тот, который уже находится в хранилище)
  • преобразует текст обоих файлов в нижний регистр
  • сравнивает содержимое строчных файлов
  • , если файлы все еще различаются, файл .orig восстанавливается, поэтому он может быть передан врепозиторий
  • если файлы одинаковые (т. е. отличаются только в том случае, если файл .orig удален, потому что эти изменения нас не интересуют)

Для файлов, которыеесть реальные изменения, о которых мы заботимся, я все еще вижу изменения в деле, которые были также сделаны.Если это приводит к большому шуму, я открываю файл в инструменте сравнения, который позволяет сравнивать без учета регистра (например, kdiff).

Это не идеальное решение, но оно устраняет около 90% разочарованиядля меня.

Вот мой сценарий.Обратите внимание, что сценарий включает в себя другой сценарий Autohotkey, ConsoleApp.ahk, который предоставляет функцию с именем ConsoleApp_RunWait().Это сторонний скрипт, который больше не очень хорошо работает с 64-битным AHK, поэтому я не включаю его в свой ответ.Любой функции AHK, которая выполняет командную строку и возвращает вывод в виде строки, будет достаточно.

; This script checks an MS Access source directory and reverts all files whose only modifications are to the 
; case of the characters within the file.

#Include %A_ScriptDir%\ConsoleApp.ahk
#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.

; Allow for custom path to hg (support for moving to TortoiseHg 2.0)
IniRead hg, %A_ScriptDir%\LocalSettings\Settings.cfg, TortoiseHg, hg_path, hg

if 0 < 1  ; The left side of a non-expression if-statement is always the name of a variable.
{
    MsgBox Usage:`n`HgIgnoreCase DirectoryWithFilesToScrub
    ExitApp
}

SrcDir = %1%
StringReplace SrcDir, SrcDir, ", , All

StringRight test, SrcDir, 1 ; add trailing slash if necessary
ifnotequal test, \
    SrcDir = %SrcDir%\

RestoreOriginals(SrcDir)
RevertCaseChangeModifiedFiles(SrcDir)

RevertCaseChangeModifiedFiles(SrcDir) {
global hg
    includes =  -I "*.form" -I "*.bas" -I "*.report" -I "*.table"
    cmdline = %hg% revert --all %includes%

    ;Don't revert items that have been removed completely
    Loop 3
    {
        Result := ConsoleApp_RunWait(hg . " status -nrd " . includes, SrcDir)
        If (Result)
            Break
    }
    Loop parse, Result, `n, `r
    {
        if (A_LoopField)
            cmdline = %cmdline% -X "%A_LoopField%"
    }
    Result =
    ;msgbox %cmdline%
    ;revert all modified forms, reports, and code modules
    Loop 3
    {

        Result := ConsoleApp_RunWait(cmdline, SrcDir)
        If (Result)
            Break
    }
    ;MsgBox %Result%

    Loop parse, Result, `n, `r
    {
        StringLeft FileStatus, A_LoopField, 9
        If (FileStatus = "reverting")
        {
            StringMid FName, A_LoopField, 11
            FullPath = %SrcDir%%FName%
            ToolTip Checking %FullPath%
            RestoreIfNotEqual(FullPath, FullPath . ".orig")
        }
    }
    ToolTip
}

RestoreIfNotEqual(FName, FNameOrig) {
    FileRead File1, %FName%
    FileRead File2, %FNameOrig%

    StringLower File1, File1
    StringLower File2, File2
    ;MsgBox %FName%`n%FNameOrig%
    If (File1 = File2)
        FileDelete %FNameOrig%
    Else
        FileMove %FNameOrig%, %FName%, 1
}

RestoreOriginals(SrcDir) {
    Loop %SrcDir%*.orig
    {
        ;MsgBox %A_LoopFileLongPath%`n%NewName%
        NewName := SubStr(A_LoopFileLongPath, 1, -5)
        FileMove %A_LoopFileLongPath%, %NewName%, 1
    }
    while FileExist(SrcDir . "*.orig")
        Sleep 10
}
2 голосов
/ 07 марта 2010

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

[encode]
*.vba = tr A-Z a-z

Это будет кодировать содержимое файла в нижнем регистре, когда вы делаете коммит. Различия также рассчитываются на основе кодированной (репозиториевой) версии файлов.

Рассмотрим файл, содержащий

hello

Изменение его в вашей рабочей копии на

Hello World

даст разность

% hg diff
diff --git a/a.txt b/a.txt
--- a/a.txt
+++ b/a.txt
@@ -1,1 +1,1 @@
-hello
+hello world

Обратите внимание, как заглавные буквы "H" и "W" игнорировались.

Я действительно ничего не знаю о коде VBA, поэтому я не уверен на 100%, что это решение работает для вас. Но я надеюсь, что это может быть отправной точкой.

Один недостаток заключается в том, что вам нужно установить это правило кодирования для всех ваших репозиториев. Здесь может помочь расширение reposettings .

...