2010-03-05 10 views
7

Estoy usando Mercurial (específicamente TortoiseHg en Windows) para hacer control de versiones del código VBA. Cualquiera que haya probado esto sabe que VBA cambia el caso de cada variable en un proyecto cada vez que se cambia cualquier declaración de esa variable en cualquier parte del proyecto (independientemente del alcance). Hace que el control de versiones sea una pesadilla.Diferencias insensibles a mayúsculas en Mercurial

Me gustaría ignorar los cambios de mayúsculas en mi código fuente al realizar diffs. ¿Cuál es la forma más fácil de hacer esto? (¿alguna opción para diff que me falta, una utilidad de diferencia externa, algo más?)

NOTA: No estoy hablando de lidiar con 'nombres de archivo insensibles a mayúsculas y minúsculas' (sí, estoy hablando con Google. ..)

+0

¡Nos encontramos de nuevo amigo mío! ¿Alguna vez encontró una solución, o quizás un VCS que puede hacer diffs insensibles a mayúsculas y minúsculas? – RubberDuck

+1

@RubberDuck: Me inspiró para finalmente publicar el enfoque que he estado usando durante los últimos años. No he resuelto el problema por completo, pero he eliminado gran parte del dolor. Básicamente, ignoro los archivos donde los únicos cambios son en la carcasa. Si el archivo tiene cambios legítimos, todavía estoy atascado viendo los cambios del caso también, pero es (mucho) mejor que nada. – mwolfe02

Respuesta

7

Puede hacer eso cuando difiere para su consumo en pantalla usando ExtDiff Extension.

[extensions] 
    hgext.extdiff = 

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

Entonces que había corrido hg mydiff desde la línea de comandos. Eso, por supuesto, requiere que tengas instalado un diff binario ya sea de GNU u otro.

Sin embargo, eso no va a ser tan útil como te gustaría porque internamente, por supuesto, Mercurial no puede ignorar el caso; está tomando el hash criptográfico del contenido del archivo, y no permite el margen de maniobra . Entonces, si obtiene esta configuración, hará hg mydiff, y no verá cambios, y luego haga hg commit y vea los cambios por todos lados.

Para que pueda hacer esto en la pantalla, pero no fundamentalmente.

Una opción sería encontrar un limpiador de código visual básico, similar a indent para lenguajes tipo C, que normaliza el caso variable y ejecuta eso en un enlace mercurial commit. Entonces, al menos, todo el código que entrará en el control de la fuente será coherente y podrá diferir entre las revisiones con precisión.

+0

Suena como un tipo de limpiador de código será mi única opción. Gracias por tu ayuda. – mwolfe02

2

Si está de acuerdo con tener su código en minúsculas, por ejemplo, puede emplear el encode/decode hooks para esto. Que funcionaría así:

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

Esto codificar el contenido del archivo en minúsculas Cada vez que hacemos una confirmación. Los diffs también se calculan en función de la versión codificada (repositorio) de los archivos.

Considere un archivo que contiene

hello 

Cambio en su copia de trabajo a

Hello World 

dará un diff de

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

Note como la capital "H" y "W" ha sido ignorado.

Realmente no sé nada sobre el código VBA, por lo que no estoy 100% seguro de que esta solución funcione para usted. Pero espero que pueda ser un punto de partida.

Un inconveniente es que tendrá que establecer esta regla de codificación para todos sus repositorios. La extensión reposettings puede ayudarlo aquí.

+0

Eso realmente no funcionaría para mí en este caso, pero es un gran consejo que intentaré recordar para el futuro. Gracias por la ayuda. – mwolfe02

2

Aquí está la solución que he establecido. Está lejos de ser ideal, pero mejor que las otras alternativas que he considerado.

creé un script de AutoHotkey que hace lo siguiente:

  • revierte archivos de MS Access en un repositorio con los cambios detectados (a .orig archivos)
  • lee en el archivo .orig (el que tiene el cambios)
  • lee en el archivo existente (del que ya está en el repositorio)
  • convierte el texto de ambos ficheros a minúsculas
  • compara el contenido minúsculas de los archivos
  • si los archivos aún difieren, el archivo .orig se restaura para que se pueda enviar al repositorio
  • si los archivos son los mismos (es decir, se diferencian solo en el caso, el archivo .orig se elimina porque no lo hacemos 't se preocupan por esos cambios)

Para los archivos que tienen cambios reales que nos importan, aún veo los cambios de casos que se realizaron. Si eso resulta en mucho ruido, abro el archivo en una herramienta de comparación que permite comparaciones insensibles a mayúsculas y minúsculas (por ejemplo, kdiff).

No es una solución perfecta, pero elimina aproximadamente el 90% de la frustración para mí.

Aquí está mi script. Tenga en cuenta que el script incluye otro script de Autohotkey, ConsoleApp.ahk, que proporciona una función llamada, ConsoleApp_RunWait(). Este es un script de terceros que ya no funciona muy bien con AHK de 64 bits, por lo que no lo incluyo como parte de mi respuesta. Cualquier función AHK que ejecute una línea de comando y devuelva el resultado como una cadena será suficiente.

; 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 
} 
+0

Gracias por confirmar que este es un enfoque útil. Estaba pensando en algo similar. – RubberDuck

Cuestiones relacionadas