Case Insensitive Differences in Mercurial

I am using Mercurial (specifically TortoiseHg for Windows) to control versioning of VBA code. Anyone who has tried this knows that VBA changes the case of each variable in the entire project whenever any declaration of this variable changes anywhere in the project (regardless of scope). This makes version control a nightmare.

I would like to ignore changes in my source code when running diffs . What is the easiest way to do this? (some option for diff that I'm missing, an external diff utility, something else?)

NOTE. I'm not talking about dealing with "case insensitive file names" (yes, I'm talking to you Google ...)

+7
mercurial diff tortoisehg
source share
3 answers

You can do this when you differ for use on the screen with the ExtDiff Extension .

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

Then you run hg mydiff from the command line. This, of course, requires that you have the diff binary installed. This is / gnu or something else.

However, it will not be as useful as you would like, because internally, of course, Mercurial cannot ignore the case - it takes a cryptographic hash of the contents of the file, and this does not allow the use of space for maneuver. Therefore, if you get this setting, you will make hg mydiff and you will not see any changes, then execute hg commit and see the changes everywhere.

So, you can do this work on the screen, but not fundamentally.

One option is to find a visual base code cleaner similar to indent for C-type languages, which normalizes the variable case and launches it in the hook using mercurial commit. Then, at least, all the code going to the original control will be consistent, and you can accurately distinguish between revisions.

+7
source share

If you are ok with your code in all lower case, say, then you can use encode / decode hooks for this, It will work as follows:

 [encode] *.vba = tr AZ az 

This will encode the contents of the file in lowercase whenever you commit. Differentials are also calculated based on the encoded (repository) version of the files.

Consider a file containing

 hello 

Change it in your working copy to

 Hello World 

will give a difference

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

Note that capital “H” and “W” were ignored.

I don't know anything about VBA code, so I'm not 100% sure that this solution works for you. But I hope this can be a starting point.

One of the drawbacks is that you need to set this encoding rule for all of your repositories. The reposettings extension can help you here.

+2
source share

Here is the solution I settled on. This is far from ideal, but better than the other alternatives I have reviewed.

I created an Autohotkey script that does the following:

  • returns MS Access files to the repository with the detected changes (to .orig files)
  • read in .orig file (the one who has the changes)
  • read in an existing file (already in the repository)
  • converts the text of both files to lowercase
  • compares the contents of lowercase files
  • If the files are still different, the .orig file is restored, so it can be attached to the repository
  • if the files are the same (that is, they differ only if the .orig file is deleted, because we do not care about these changes)

For files that have real changes that we care about, I still see the case changes that were made. If this leads to a lot of noise, I open the file in a comparison tool that allows case-insensitive comparisons (e.g. kdiff).

This is not an ideal solution, but it eliminates about 90% of frustration for me.

Here is my script. Note that the script includes another Autohotkey script, ConsoleApp.ahk, which provides a function called ConsoleApp_RunWait() . This is a third-party script that no longer works with 64-bit AHK, so I do not include it as part of my answer. Any AHK function that executes the command line and returns the result as a string will suffice.

 ; 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
source share

All Articles