2010-03-05 6 views
7

J'utilise Mercurial (spécifiquement TortoiseHg sous Windows) pour contrôler la version du code VBA. Quiconque a essayé ceci sait que VBA change le cas de chaque variable dans un projet chaque fois qu'une déclaration de cette variable est changée n'importe où dans le projet (indépendamment de la portée). Cela fait du contrôle de version un cauchemar.Différences insensibles à la casse dans Mercurial

Je voudrais ignorer les changements de cas dans mon code source lors de l'exécution des diffs. Quelle est la manière la plus simple de faire ça? (une option pour diff qui me manque, un utilitaire diff externe, autre chose?)

NOTE: Je ne parle pas de 'noms de fichiers insensibles à la casse' (oui, je vous parle Google. ..)

+0

Nous retrouvons mon ami! Avez-vous déjà trouvé une solution, ou peut-être un VCS qui peut faire des diffs insensible à la casse? – RubberDuck

+1

@RubberDuck: Vous m'avez inspiré pour finalement poster l'approche que j'utilise depuis plusieurs années. Je n'ai pas complètement résolu le problème, mais j'ai éliminé une grande partie de la douleur. Fondamentalement, j'ignore les fichiers où les seuls changements sont à l'enveloppe. Si le fichier a des changements légitimes, je suis toujours coincé en voyant le cas changer aussi, mais c'est (beaucoup) mieux que rien. – mwolfe02

Répondre

7

Vous pouvez faire cela en différant pour votre consommation à l'écran en utilisant le ExtDiff Extension.

[extensions] 
    hgext.extdiff = 

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

alors vous exécutez hg mydiff à partir de la ligne de commande. Cela, bien sûr, nécessite que vous ayez un binaire diff installé que ce soit gnu ou autre.

Cependant, cela ne va pas être aussi utile que vous pourriez aimer parce que l'intérieur, bien sûr, Mercurial ne peut ignorer la casse - il prend le hachage cryptographique du contenu de fichiers, et ceux qui ne permettent pas de marge de manœuvre . Donc, si vous obtenez cette configuration, vous allez faire hg mydiff, et ne voir aucun changement, puis faites hg commit et voir les changements partout.

Vous pouvez donc faire en sorte que cela fonctionne à l'écran, mais pas fondamentalement. Une option consisterait à trouver un nettoyeur de code visuel de base, similaire à indent pour les langages de type C, qui normalise les cas de variables et les exécute dans un crochet de validation mercurial. Au moins tout le code entrant dans le contrôle de la source sera cohérent et vous pouvez différencier les révisions avec précision.

+0

Semble comme une sorte de code-nettoyeur sera ma seule option. Merci de votre aide. – mwolfe02

2

Si vous acceptez que votre code soit en minuscules, disons, vous pouvez utiliser le encode/decode hooks pour cela. Il fonctionnerait comme ceci:

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

Cela encode le contenu de fichiers en minuscules chaque fois que vous faites un engagement. Les différences sont également calculées en fonction de la version codée (référentiel) des fichiers.

Considérons un fichier qui contient

hello 

Changement dans votre copie de travail à

Hello World 

donnera une 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 

Remarquez que "H" la capitale et "W" a été ignoré. Je ne connais pas vraiment le code VBA, donc je ne suis pas sûr à 100% que cette solution fonctionne pour vous. Mais j'espère que ça peut être un point de départ. Un inconvénient est que vous devrez définir cette règle de codage pour tous vos référentiels. L'extension reposettings peut vous aider ici.

+0

Cela ne fonctionnerait pas vraiment pour moi dans ce cas, mais c'est un bon conseil que je vais essayer de me rappeler pour l'avenir. Merci pour l'aide. – mwolfe02

2

Voici la solution que j'ai choisie. C'est loin d'être idéal, mais mieux que les autres alternatives que j'ai envisagées.

J'ai créé un script Autohotkey qui effectue les opérations suivantes:

  • Revient fichiers MS Access dans un référentiel avec les changements détectés (à .orig fichiers)
  • lit dans le fichier .orig (celui avec le modifications)
  • lit dans le fichier existant (celui déjà dans le référentiel)
  • convertit le texte des deux fichiers en minuscules
  • compare le contenu de minuscules des fichiers
  • si les fichiers diffèrent encore, le fichier est restauré .orig il peut être archivé dans le serveur
  • si les fichiers sont les mêmes (ils ne diffèrent que dans le cas, le fichier est supprimé .orig parce que nous don Ne tenez pas compte de ces changements)

Pour les fichiers qui ont des modifications réelles que nous nous soucions, je vois encore les changements de cas qui ont été faites aussi bien. Si cela entraîne beaucoup de bruit, j'ouvre le fichier dans un outil de comparaison qui permet des comparaisons insensibles à la casse (par exemple, kdiff).

Ce n'est pas une solution parfaite, mais elle supprime environ 90% de la frustration pour moi.

Voici mon script. Notez que le script inclut un autre script Autohotkey, ConsoleApp.ahk, qui fournit une fonction nommée, ConsoleApp_RunWait(). C'est un script de 3ème partie qui ne fonctionne plus très bien avec AHK 64 bits, donc je ne l'inclue pas dans ma réponse. Toute fonction AHK qui exécute une ligne de commande et renvoie la sortie sous la forme d'une chaîne suffira.

; 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

Merci de confirmer que c'est une approche utile. Je pensais à quelque chose de similaire. – RubberDuck

Questions connexes