Issue #209 resolved

Tortoisehg 2.0 - No external merge/diff tool

Johannes Rudolph
created an issue

Since I upgraded to tortoise hg 2.0 external diff/merge using DiffMerge does no longer work. The configuration utility correctly displays I have configured it as my merge tool, however I am unable to select diffmerge in the Resolve Conflicts window.

Here is my configuration if that helps: {{{

!ini

Generated by TortoiseHg setting dialog

[diff] git = True

[extensions] fold = bookmarks = progress = extdiff = rebase = mq =

[ui] username = Johannes Rudolph merge = diffmerge

[extdiff] cmd.diffmerge = c:\Programme\SourceGear\DiffMerge\DiffMerge.exe

[tortoisehg] vdiff = diffmerge ui.language = en

[merge-tools] diffmerge.executable = c:\Program Files(x86)\SourceGear\DiffMerge\DiffMerge.exe diffmerge.args = --result=$output -t1="Local Version" -t2=$output -t3="Other Version" --caption=$output $local $base $other diffmerge.binary = False diffmerge.symlinks = False diffmerge.gui = True diffmerge.premerge = True }}}

Comments (22)

  1. Steve Borho
    • changed status to open

    the extdiff configuration is superfluous these days.

    What do you mean you can't select it? Does it not appear in the drop box, or does it not launch?

  2. Steve Borho

    TortoiseHg's merge-tools configuration is better than yours:

    diffmerge.regkey=Software\SourceGear\SourceGear DiffMerge\
    diffmerge.regname=Location
    diffmerge.priority=-7
    diffmerge.args=-nosplash -merge -title1=local -title2=merged -title3=other $local $base $other -result=$output
    diffmerge.checkchanged=True
    diffmerge.gui=True
    diffmerge.diffargs=--nosplash --title1='$plabel1' --title2='$clabel' $parent $child
    diffmerge.diff3args=--nosplash --title1='$plabel1' --title2='$clabel' --title3='$plabel2' $parent1 $child $parent2
    diffmerge.dirdiff=True
    

    It's looking in the registry for the install location, so it won't get hung up on localized locations of %ProgramFiles%.

  3. Johannes Rudolph reporter

    I'm using Diffmerge and TortoiseHg for very long now, my config is from the days that autodetect didn't work properly. Strange enough, I have uninstalled THG, purged all Mercurial.ini and it seems the installer doesn't automatically configure DiffMerge for me.

    Where does THG look in the registry? HKCU or HKLM? It appears my DiffMerge installation might not have properly populated the registry key. Either that or DiffMerge or THG are not correctly handling x64 registry virtualization (I'm running win7 x64).

  4. Steve Borho

    which installer doesn't automatically configure DiffMerge?

    All we do is ship with a configuration that tries to find it. If newer versions have changed their registry configuration, we need to update our own config. Can you peek at how DiffMerge is configured in the registry?

  5. Steve Borho

    oh.. there's the problem. 2.0 installs as a native 64bit application on x64 machines, and Mercurial does not know to search in Wow6432Node.

    This needs to get fixed in Mercurial.

  6. Johannes Rudolph reporter

    Ok, glad I could help you tracking this down. Why does putting in Wow6432Node in MergeTools.rc not help though? In the interim, I exported the key from Wow6432 and imported it into the root. That fixed the symptom at least.

  7. Adrian Buehlmann

    Steve is on the core mercurial development team (aka crew), so he can push a change for this himself :-)

    We briefly discussed possible remedies on IRC channel #mercurial. Initially, Steve favored hacking something into mercurial.util.lookup_reg, which I think is on a too low level (IMHO we should stay x64 / x86 ignorant on that level).

    Maybe we could instead introduce a "regkeyalt" keyword, which could be used as:

    diffmerge.regkey=Software\SourceGear\SourceGear DiffMerge\
    diffmerge.regkeyalt=Software\Wow6432Node\SourceGear\SourceGear DiffMerge\
    diffmerge.regname=Location
    diffmerge.priority=-7
    diffmerge.args=-nosplash -merge -title1=local -title2=merged -title3=other $local $base $other -result=$output
    diffmerge.checkchanged=True
    diffmerge.gui=True
    diffmerge.diffargs=--nosplash --title1='$plabel1' --title2='$clabel' $parent $child
    diffmerge.diff3args=--nosplash --title1='$plabel1' --title2='$clabel' --title3='$plabel2' $parent1 $child $parent2
    diffmerge.dirdiff=True
    

    If .regkey doesn't find anything, mercurial should then look again using .regkeyalt.

    Maybe something like:

    diff --git a/mercurial/filemerge.py b/mercurial/filemerge.py
    --- a/mercurial/filemerge.py
    +++ b/mercurial/filemerge.py
    @@ -26,12 +26,13 @@ def _findtool(ui, tool):
         if tool in _internal:
             return tool
         k = _toolstr(ui, tool, "regkey")
    -    if k:
    +    while k:
             p = util.lookup_reg(k, _toolstr(ui, tool, "regname"))
             if p:
                 p = util.find_exe(p + _toolstr(ui, tool, "regappend"))
                 if p:
                     return p
    +        k = _toolstr(ui, tool, "regkeyalt")
         return util.find_exe(_toolstr(ui, tool, "executable", tool))
    
     def _picktool(repo, ui, path, binary, symlink):
    
  8. Adrian Buehlmann

    Or even better without an endless loop:

    diff --git a/mercurial/filemerge.py b/mercurial/filemerge.py
    --- a/mercurial/filemerge.py
    +++ b/mercurial/filemerge.py
    @@ -26,12 +26,17 @@ def _findtool(ui, tool):
         if tool in _internal:
             return tool
         k = _toolstr(ui, tool, "regkey")
    -    if k:
    +    n = 0
    +    while k:
             p = util.lookup_reg(k, _toolstr(ui, tool, "regname"))
             if p:
                 p = util.find_exe(p + _toolstr(ui, tool, "regappend"))
                 if p:
                     return p
    +        if n > 0:
    +            break
    +        k = _toolstr(ui, tool, "regkeyalt")
    +        n += 1
         return util.find_exe(_toolstr(ui, tool, "executable", tool))
    
     def _picktool(repo, ui, path, binary, symlink):
    
  9. Johannes Rudolph reporter

    two things are strange about that though: If I explicitly specify Wow6432Node the lookup also fails and if I use the Mercurial.ini I posted above it doesn't work too.

    As for the second issue, I guess this is propbably due to conflicting cmd.diffmerge configurations.

  10. Adrian Buehlmann

    Gah. Fails if first k is None.

    Third attempt at a patch:

    diff --git a/mercurial/filemerge.py b/mercurial/filemerge.py
    --- a/mercurial/filemerge.py
    +++ b/mercurial/filemerge.py
    @@ -25,8 +25,10 @@ _internal = ['internal:' + s
     def _findtool(ui, tool):
         if tool in _internal:
             return tool
    -    k = _toolstr(ui, tool, "regkey")
    -    if k:
    +    for kn in ("regkey", "regkeyalt"):
    +        k = _toolstr(ui, tool, kn)
    +        if not k:
    +            continue
             p = util.lookup_reg(k, _toolstr(ui, tool, "regname"))
             if p:
                 p = util.find_exe(p + _toolstr(ui, tool, "regappend"))
    
  11. Adrian Buehlmann

    Ok. I'm installing DiffMerge here (Windows 7 x64) and having a look if that Wow6432Node trick really works or not (Johannes says he can't get it to work, but I think it should work).

  12. Adrian Buehlmann

    I've edited C:\Program Files\TortoiseHg\hgrc.d\MergeTools.rc to contain

    ;diffmerge.regkey=Software\SourceGear\SourceGear DiffMerge\
    diffmerge.regkey=Software\Wow6432Node\SourceGear\SourceGear DiffMerge\
    

    I can select the DiffMerge tool in the resolve dialog and it starts fine.

    DiffMerge version installed here is 3.3.0 (185131)

    Relevant registry as installed by DiffMerge is (exported with RegEdit):

    Windows Registry Editor Version 5.00
    
    [HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\SourceGear]
    
    [HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\SourceGear\SourceGear DiffMerge]
    "Location"="C:\\Program Files (x86)\\SourceGear\\DiffMerge\\\\DiffMerge.exe"
    "InstallDir"="C:\\Program Files (x86)\\SourceGear\\DiffMerge\\"
    

    So here, the Wow6432Node trick does work.

  13. Adrian Buehlmann

    Very good, thanks for reporting. So we know we are on a track that works.

    I'm wondering if anything evil happens (I hope not) if we try to read the registry from HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node on a x86.

    I'll try poking at a Windows XP x86 I have in a VM here and see what happens.

  14. Steve Borho

    mergetools: add alternate registry keys for x86 apps on x64 (fixes #209)

    I've confirmed this works for DiffMerge and KDiff3 and the workarounds were not necessary for Araxis Merge (64 bit app) or Beyond Compare (installs keys under HKCU). This patch depends on a Mercurial change to be effective.

    d03d26dcfee6

  15. Log in to comment