hgext.extdiff silently does nothing - mercurial

In trying to get my real differencing engine up, I've trimmed to a very minimal setup, but still have no output and no indication of why nothing appears to happen. (Search of SO and Mercurial site (including the mercurial wiki) for extdiff gave me all the ideas I've tried, though perhaps I haven't tried all.)
I have tried a bash script and a .bat file; I have tried each of the scripts located in the "root" of the E: drive, identified as /cygdrive/e/ or as E:/ I have tried with and without quoting the path to the script. I think I've exhausted the combinations and have yet to get any indications of what (if anything) is running. When invoked directly, FdbCmp.bat behaves as expected; it is in a directory on my $PATH and in the Windows Path environment variable.
Other suggestions? It looks like it is simple enough and should "just work"
mercurial.ini includes
[extdiff]
hgext.extdiff
cmd.fdiff0 = "e:/Program Files/DbCmp/FdbCmp.bat"
opts.fdiff0 = $root --file $local --file $other
FdbCmp.bat:
#echo off
echo FdbCmp.bat testing
echo FdbCmp.bat args: ::%1:: ::%2:: ::%3 ::%4:: ::%5:: ::%6:: ::%7:: ::%8:: ::%9::
hg showconfig | grep extdiff returns the expected results (among a few other lines)
extdiff.cmd.fdiff0="e:/Program Files/DbCmp/FdbCmp.bat"
extdiff.opts.fdiff0=$root --file $local --file $other
extensions.hgext.extdiff=
hg fdiff0 returns with $? = 0 (cygwin bash or CMD.EXE) and no output displayed. I expected the FdbCmp.bat file would have printed something.
hg fdiff0 a b c (where files a, b, c do not exist) returns the following. This is expected, as the files don't exist and Hg reports that.
a: The system cannot find the file specified
b: The system cannot find the file specified
c: The system cannot find the file specified
hg fdiff0 file1 file2 file3 where all files exist returns with no error and no output. This is unexpected - FdbCmp.bat should have been invoked and printed its something.
Just testing the .bat file alone gives the expected results:
$ FdbCmp.bat moo cow oink pig
FdbCmp.bat testing
FdbCmp.bat args: ::moo:: ::cow:: ::oink ::pig:: :::: :::: :::: :::: ::::
hg --version is 2.4.6-35ba170c0f82

A re-read of the extdiff section of the documentation shows that options "will be inserted to the command between the program name and the files/directories to diff", unlike the merge-tools behaviour where options and files may be intermixed as required to build an appropriate comand line. The $local, $root, ... variables do not exist within the context of extdiff; they are merge-tools features that do not apply here.
The relevant mercurial.ini section now is
[extensions]
# enable the extdiff extension
hgext.extdiff =
[extdiff]
# define a jpeg differencing script; no options required
cmd.jpgdiff = HgJpgDiff.bat
# HgJpgDiff.bat is in a directory in my $PATH and contains:
# #rem ... various lines to test if we have been handed directories or files to compare
# #rem ...we only compare files, so this is the only active line
# JpgDiff --file %1 --file %2
[diff-patterns]
**.jpg=jpgdiff
and all works as desired now. Echoing parameters to a file helped to debug; nothing was ever displayed on the screen.
Many thanks.

I suppose, you have to re-read "Extdiff extension" wiki page
Anyway, if you want to use instead of hg diff FILE1 FILE2 something like hg fdiff FILE1 FILE2 for diffing, you have (see differences)
Add to global mercurial.ini (or project's .hgrc)
[extensions]
hgext.extdiff =
(maybe just extdiff =, have to test)
Create new [exdiff] section in file and in this section define new command for external diff and command options (diff with 3 files???), maybe like this (FdbCmp.bat added to PATH)
cmd.fdiff = FdbCmp.bat
opts.fdiff = $0 --file $1 --file $2
for my sample above resuling command
hg fdiff /PATH/TO/ B C
must produce as result under the hood
FdbCmp.bat /PATH/TO/ --file B --file C

Related

Get rid of "nameless" node in mercurial repository

I found a nameless node in my mercurial repository.
On executing the tag listing command "hg tags" as part of the generated output, I find the same node mentioned twice.
The output of hg tags command contains the following duplicate nodes:
xyz_release_tag daa262c10
daa262c10
In one of the entries, the node has a name but the other entry the node does not have a name.
I am in the process of migrating the mercurial repository to git and I am using fast-export to do the conversion.
The presence of this "nameless" node causes errors during the conversion process. Similar issue has been discussed at: https://github.com/frej/fast-export/issues/1.
As a quick workaround, I made a quick change to my local repository cache file. There is a file by name "tags2-visible" that gets created after I run the hg tags command for listing. Once I modify this file to remove the entry for the nameless node, it disappears and the conversion process succeeds.
I am not very sure if this is the right way to do it or if at all there is any other way.
Any thoughts ?
Resulting quickfix:
hg tags # Creates .hg/cache/tags2-visible
# Fix the nameless tag
sed -rie 's/^([^ ]+) $/\1 \1/' .hg/cache/tags2-visible
How I came to the solution:
$ hg tags | tail -3
PRODUCION_18032010 216:3e0a6415bbde
166:809065c08005
PRODUCION 125:d98f65c06bac
$ # Where is the problem?
$ grep -r 809065c08005
.hg/cache/tags2-visible:809065c08005ef2d261f10f72f17ea5fcd1e7540
$ # Add " test" to the end of this line
$ sed -i .hg/cache/tags2-visible -e 's/809065c08005ef2d261f10f72f17ea5fcd1e7540/809065c08005ef2d261f10f72f17ea5fcd1e7540 test/'
$ # Checking the edition
$ grep -r 809065c08005
.hg/cache/tags2-visible:809065c08005ef2d261f10f72f17ea5fcd1e7540 test
$ # Checking the validity of the hack
$ hg tags | tail -3
PRODUCION_18032010 216:3e0a6415bbde
test 166:809065c08005
PRODUCION 125:d98f65c06bac
After editing .hg/cache/tags2-visible adding a label to the branch fast-export worked for me.
Anyone see any problem in editing .hg/cache/tags2-visible in this way?

hg extdiff -p and %~dp0

myprogram.cmd is in PATH;
myprogram.cmd uses %~dp0 to determine the folder it is in;
I have included #echo %~dp0 into myprogram.cmd for debugging;
When I call myprogram.cmd from anywhere, it works perfectly, displaying the folder myprogram.cmd is in;
When I call hg extdiff -p myprogram.cmd, it does not work, displaying something like c:\Users\Username\AppData\Local\Temp\extdiff.3n8op2\.
Here is the related part of hgrc file:
[extensions]
hgext.extdiff =
What do I do wrong? Should not %~dp0 return drive and path of the batch file? What do I use instead? Do I have to apply some special configuration to Mercurial repository? Passing the full path of myprogram.cmd to hg extdiff -p is not an option, unless it is done automatically.
The %~dp0 trick is a big lie. It is not actually a magic variable, it's simply a manipulation of %0 (or whichever var you stick the ~dp in front of). It simply takes whatever string is in that variable and tells you what its drive and path components appear to be. If that string is simply a name like "myprogram", it says "well, filenames without drives and paths are assumed to be in the current directory".
So the %~dp0 trick only works if either:
a) you've launched your script by its full name or
b) you happen to be in the directory where it resides
In this case, you run:
hg extdiff -p myprogram
gets turned into the following call to Windows:
CreateProcess(NULL, "cmd.exe /c myprogram some diff args", ..., "c:/some/temp/path", ...)
which is morally equivalent to opening a shell and running:
C:\>cd c:\some\temp\path
C:\some\temp\path>myprogram some diff args
%0 is myprogram
%~dp0 is C:\some\temp\path
I recommend passing the full program name for your tool like this via your .hgrc:
[extdiff]
myprogram=c:/tools/myprogram.cmd
But be warned, this can get confused by the presence of spaces in your filename, you may need to experiment with quoting.
You can try using %~dp$PATH:0, but you need to always specify the extension. For example, for the following test.cmd:
rem test.cmd
#echo dp0 == %~dp0
#echo dp$PATH:0 == %~dp$PATH:0
these are two sample runs from the d:\hg folder:
$ hg extdiff -p test.cmd
dp0 == c:\Users\estefan\AppData\Local\Temp\extdiff.pamj6n\
dp$PATH:0 == k:\home\Scripts\
$ hg extdiff -p test
dp0 == c:\Users\estefan\AppData\Local\Temp\extdiff.dgp0qz\
dp$PATH:0 ==
From http://ss64.com/nt/syntax-args.html:
%~$PATH:1 Search the PATH environment variable and expand %1 to the fully qualified name of the first match found.

Automatic conversion of specific binary files to text to compare (diff) in Mercurial

I have several -small- binary files added in my Mercurial repository. The files are the "source" files of one of my development tools (report / form / class definitions).
I made a program that dumps this binary files to a text file to allow easy diffs between them. Is there any way to tell Mercurial that certain file extensions need to run this conversion before running the diff program? Or I have to set my conversion program as the main diff tool and run the conversion -or not- and then run the real diff program?
You can (TBT) use ExtDiff extension for pure Mercurial. In case of TortoiseHG
[diff-patterns]
**.ext = difftool
in hgrc plays the game
I ended up with a small batch previous to the diff program:
#echo off
set f1=%1
set f2=%2
::Temporary dir created by hg to copy the snapshot file
set tdir=%~dp1
::Original repository dir
set repo=%~dp2
::Filename extension
set ext=%~x1
::The binary files comes in pairs: scx/sct \ vcx/vct ...
set ex2=%ext:~0,-1%t
::Check if "dumpable" extension
echo %ext% | grep -iE "(vcx|vct|scx|sct|pjx|pjt|frx|frt)" > nul && goto DumpFile
goto diff
:DumpFile
set f1="%tdir%\_Dump1.prg"
set f2="%tdir%\_Dump2.prg"
::Get the pair file from the repository
hg cat %repo%\%~n1%ex2% -o "%~dpn1%ex2%" -R %repo%
::Do the dump, then the diff
MyDumpProgram.exe %1 %f1%
MyDumpProgram.exe %2 %f2%
goto diff
:diff
ExamDiff.exe %f1% %f2%
pause
and then config the batch in %UserProfile%\.hgrc
[extdiff]
cmd.ediff = d:\Utiles\diff2.bat

hg: unknown command 'extdiff''

I can't figure out why my extdiff extension is not working for Mercurial (on a Mac).
this is what my .hgrc file looks like:
[extensions]
fetch=
hgext.extdiff =
[extdiff]
cmd.kdiff3 =
[ui]
merge=kdiff3
[merge-tools]
kdiff3.executable=/Applications/kdiff3.app/Contents/MacOS/kdiff3
kdiff3.args = $base $local $other -o $output
and yet kdiff3 is recognized as a merge tool.. and can be run from the cmd line like "kdiff3". but what i'd like to do is use kdiff3 as a gui tool for comparing diff files.
like this:
hg extdiff -p kdiff3
this seems like the best way of using kdiff3 as a popup gui when using Mercurial.
I am new to this and am not sure if I am doing it right.
Thanks...!
By the way, when I try to run 'hg extdiff'
I get:
hg: unknown command 'extdiff'
'extdiff' is provided by the following extension:
extdiff command to allow external programs to compare revisions
use "hg help extensions" for information on enabling extensions
(even though it is in .hgrc)
Please note that merge-tool and external diff are different tools for different tasks.
For example you can use fmdiff script to use FileMerge for diff and k3diff for merge-tool:
Your .hgrc should be:
[extensions]
# enable external diff program
extdiff =
[extdiff]
cmd.opendiff = fmdiff
opts.opendiff =
[merge-tools]
# Override stock tool location
kdiff3.executable = /Applications/kdiff3.app/Contents/MacOS/kdiff3
# Specify command line
kdiff3.args = $base $local $other -o $output
# Give higher priority
kdiff3.priority = 1
Now you can use
hg opendiff myfile.ext
Please note that 'opendiff' is a custom wrapper name, so you can change it to your likes but it cannot be one of already reserver names.

Mercurial merge strategy per file type

All:
I want to use kdiff to merge all files with a certain suffix (say *.c, *.h) and I want to do two things (turn off premerge and use internal:other) for all files with another suffix (say *.mdl). The purpose of this is to allow me to employ a type of 'clobber merge' for a specific file type (ie: un-mergable files like configurations, auto-generated C, models, etc..)
In my .hgrc I've tried:
[merge-tools]
kdiff3=
clobbermerge=internal:other
clobbermerge.premerge = False
[merge-patterns]
**.c = kdiff3
**.h = kdiff3
**.mdl = clobbermerge
but it still triggers kdiff3 for all files. Thoughts?
An extension of this would be to perform a 'clobber merge' on a directory - but once the syntax is clear for a file suffix, the dir should be easy.
Merge tools can use any executable file. To set up a merge tool which always overwrites $base with $other, you can use the following:
[merge-tools]
clobbermerge.priority = 100
clobbermerge.premerge = False
clobbermerge.args = $other $output
clobbermerge.executable = <copy executable>
When using this strategy on Windows, there is one problem. You cannot simply replace <copy executable> with the copy shell command. For some reason, Mercurial fails to find shell commands in this context. I have not tried this on *nix.
To work around this problem, you can create a distribute a batch file that performs the copy. It simply needs to run: copy %1 %2. Once placed on your PATH, you can set clobbermerge.executable=clobber.bat.
If you have kdiff3 installed (comes with TortoiseHg on Windows), you can get the same results without the external batch file using a configuration like this:
[merge-tools]
clobbermerge.priority = 100
clobbermerge.premerge = False
clobbermerge.args = --auto $base $other $other -o $output
clobbermerge.executable = kdiff3
The key to this configuration is the args field:
--auto: tells kdiff3 not to open the GUI if there are no conflicts
$base $other $other: tells kdiff3 to only use $other
$output: tells kdiff3 the name of the output file
According to this Mercurial MergeToolConfiguration page, you should put the interal:other directly after the match pattern:
[merge-patterns]
**.mdl = internal:other