$ "$TESTDIR/hghave" system-sh || exit 80 test merge-tools configuration - mostly exercising filemerge.py $ unset HGMERGE # make sure HGMERGE doesn't interfere with the test $ hg init revision 0 $ echo "revision 0" > f $ echo "space" >> f $ hg commit -Am "revision 0" adding f revision 1 $ echo "revision 1" > f $ echo "space" >> f $ hg commit -Am "revision 1" $ hg update 0 > /dev/null revision 2 $ echo "revision 2" > f $ echo "space" >> f $ hg commit -Am "revision 2" created new head $ hg update 0 > /dev/null revision 3 - simple to merge $ echo "revision 3" >> f $ hg commit -Am "revision 3" created new head $ echo "[merge-tools]" > .hg/hgrc $ beforemerge() { > cat .hg/hgrc > echo "# hg update -C 1" > hg update -C 1 > /dev/null > } $ aftermerge() { > echo "# cat f" > cat f > echo "# hg stat" > hg stat > rm -f f.orig > } $ domerge() { > beforemerge > echo "# hg merge $*" > hg merge $* > aftermerge > } Tool selection default is internal merge: $ beforemerge [merge-tools] # hg update -C 1 hg merge -r 2 override $PATH to ensure hgmerge not visible; use $PYTHON in case we're running from a devel copy, not a temp installation $ PATH="$BINDIR" $PYTHON "$BINDIR"/hg merge -r 2 merging f warning: conflicts during merge. merging f incomplete! (edit conflicts, then use 'hg resolve --mark') 0 files updated, 0 files merged, 0 files removed, 1 files unresolved use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon [1] $ aftermerge # cat f <<<<<<< local revision 1 ======= revision 2 >>>>>>> other space # hg stat M f ? f.orig simplest hgrc using false for merge: $ echo "false.whatever=" >> .hg/hgrc $ domerge -r 2 [merge-tools] false.whatever= # hg update -C 1 # hg merge -r 2 merging f merging f failed! 0 files updated, 0 files merged, 0 files removed, 1 files unresolved use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon # cat f revision 1 space # hg stat M f ? f.orig true with higher .priority gets precedence: $ echo "true.priority=1" >> .hg/hgrc $ domerge -r 2 [merge-tools] false.whatever= true.priority=1 # hg update -C 1 # hg merge -r 2 merging f 0 files updated, 1 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) # cat f revision 1 space # hg stat M f unless lowered on command line: $ domerge -r 2 --config merge-tools.true.priority=-7 [merge-tools] false.whatever= true.priority=1 # hg update -C 1 # hg merge -r 2 --config merge-tools.true.priority=-7 merging f merging f failed! 0 files updated, 0 files merged, 0 files removed, 1 files unresolved use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon # cat f revision 1 space # hg stat M f ? f.orig or false set higher on command line: $ domerge -r 2 --config merge-tools.false.priority=117 [merge-tools] false.whatever= true.priority=1 # hg update -C 1 # hg merge -r 2 --config merge-tools.false.priority=117 merging f merging f failed! 0 files updated, 0 files merged, 0 files removed, 1 files unresolved use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon # cat f revision 1 space # hg stat M f ? f.orig or true.executable not found in PATH: $ domerge -r 2 --config merge-tools.true.executable=nonexistingmergetool [merge-tools] false.whatever= true.priority=1 # hg update -C 1 # hg merge -r 2 --config merge-tools.true.executable=nonexistingmergetool merging f merging f failed! 0 files updated, 0 files merged, 0 files removed, 1 files unresolved use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon # cat f revision 1 space # hg stat M f ? f.orig or true.executable with bogus path: $ domerge -r 2 --config merge-tools.true.executable=/nonexisting/mergetool [merge-tools] false.whatever= true.priority=1 # hg update -C 1 # hg merge -r 2 --config merge-tools.true.executable=/nonexisting/mergetool merging f merging f failed! 0 files updated, 0 files merged, 0 files removed, 1 files unresolved use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon # cat f revision 1 space # hg stat M f ? f.orig but true.executable set to cat found in PATH works: $ echo "true.executable=cat" >> .hg/hgrc $ domerge -r 2 [merge-tools] false.whatever= true.priority=1 true.executable=cat # hg update -C 1 # hg merge -r 2 merging f revision 1 space revision 0 space revision 2 space 0 files updated, 1 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) # cat f revision 1 space # hg stat M f and true.executable set to cat with path works: $ domerge -r 2 --config merge-tools.true.executable=cat [merge-tools] false.whatever= true.priority=1 true.executable=cat # hg update -C 1 # hg merge -r 2 --config merge-tools.true.executable=cat merging f revision 1 space revision 0 space revision 2 space 0 files updated, 1 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) # cat f revision 1 space # hg stat M f environment variables in true.executable are handled: $ cat > $HGTMP/merge.sh < #!/bin/sh > echo 'custom merge tool' > EOF $ chmod +x $HGTMP/merge.sh $ domerge -r 2 --config merge-tools.true.executable='$HGTMP/merge.sh' [merge-tools] false.whatever= true.priority=1 true.executable=cat # hg update -C 1 # hg merge -r 2 --config merge-tools.true.executable=$HGTMP/merge.sh merging f custom merge tool 0 files updated, 1 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) # cat f revision 1 space # hg stat M f Tool selection and merge-patterns merge-patterns specifies new tool false: $ domerge -r 2 --config merge-patterns.f=false [merge-tools] false.whatever= true.priority=1 true.executable=cat # hg update -C 1 # hg merge -r 2 --config merge-patterns.f=false merging f merging f failed! 0 files updated, 0 files merged, 0 files removed, 1 files unresolved use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon # cat f revision 1 space # hg stat M f ? f.orig merge-patterns specifies executable not found in PATH and gets warning: $ domerge -r 2 --config merge-patterns.f=true --config merge-tools.true.executable=nonexistingmergetool [merge-tools] false.whatever= true.priority=1 true.executable=cat # hg update -C 1 # hg merge -r 2 --config merge-patterns.f=true --config merge-tools.true.executable=nonexistingmergetool couldn't find merge tool true specified for f merging f merging f failed! 0 files updated, 0 files merged, 0 files removed, 1 files unresolved use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon # cat f revision 1 space # hg stat M f ? f.orig merge-patterns specifies executable with bogus path and gets warning: $ domerge -r 2 --config merge-patterns.f=true --config merge-tools.true.executable=/nonexisting/mergetool [merge-tools] false.whatever= true.priority=1 true.executable=cat # hg update -C 1 # hg merge -r 2 --config merge-patterns.f=true --config merge-tools.true.executable=/nonexisting/mergetool couldn't find merge tool true specified for f merging f merging f failed! 0 files updated, 0 files merged, 0 files removed, 1 files unresolved use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon # cat f revision 1 space # hg stat M f ? f.orig ui.merge overrules priority ui.merge specifies false: $ domerge -r 2 --config ui.merge=false [merge-tools] false.whatever= true.priority=1 true.executable=cat # hg update -C 1 # hg merge -r 2 --config ui.merge=false merging f merging f failed! 0 files updated, 0 files merged, 0 files removed, 1 files unresolved use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon # cat f revision 1 space # hg stat M f ? f.orig ui.merge specifies internal:fail: $ domerge -r 2 --config ui.merge=internal:fail [merge-tools] false.whatever= true.priority=1 true.executable=cat # hg update -C 1 # hg merge -r 2 --config ui.merge=internal:fail 0 files updated, 0 files merged, 0 files removed, 1 files unresolved use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon # cat f revision 1 space # hg stat M f ui.merge specifies internal:local: $ domerge -r 2 --config ui.merge=internal:local [merge-tools] false.whatever= true.priority=1 true.executable=cat # hg update -C 1 # hg merge -r 2 --config ui.merge=internal:local 0 files updated, 1 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) # cat f revision 1 space # hg stat M f ui.merge specifies internal:other: $ domerge -r 2 --config ui.merge=internal:other [merge-tools] false.whatever= true.priority=1 true.executable=cat # hg update -C 1 # hg merge -r 2 --config ui.merge=internal:other 0 files updated, 1 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) # cat f revision 2 space # hg stat M f ui.merge specifies internal:prompt: $ domerge -r 2 --config ui.merge=internal:prompt [merge-tools] false.whatever= true.priority=1 true.executable=cat # hg update -C 1 # hg merge -r 2 --config ui.merge=internal:prompt no tool found to merge f keep (l)ocal or take (o)ther? l 0 files updated, 1 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) # cat f revision 1 space # hg stat M f ui.merge specifies internal:dump: $ domerge -r 2 --config ui.merge=internal:dump [merge-tools] false.whatever= true.priority=1 true.executable=cat # hg update -C 1 # hg merge -r 2 --config ui.merge=internal:dump merging f 0 files updated, 0 files merged, 0 files removed, 1 files unresolved use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon # cat f revision 1 space # hg stat M f ? f.base ? f.local ? f.orig ? f.other f.base: $ cat f.base revision 0 space f.local: $ cat f.local revision 1 space f.other: $ cat f.other revision 2 space $ rm f.base f.local f.other ui.merge specifies internal:other but is overruled by pattern for false: $ domerge -r 2 --config ui.merge=internal:other --config merge-patterns.f=false [merge-tools] false.whatever= true.priority=1 true.executable=cat # hg update -C 1 # hg merge -r 2 --config ui.merge=internal:other --config merge-patterns.f=false merging f merging f failed! 0 files updated, 0 files merged, 0 files removed, 1 files unresolved use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon # cat f revision 1 space # hg stat M f ? f.orig Premerge ui.merge specifies internal:other but is overruled by --tool=false $ domerge -r 2 --config ui.merge=internal:other --tool=false [merge-tools] false.whatever= true.priority=1 true.executable=cat # hg update -C 1 # hg merge -r 2 --config ui.merge=internal:other --tool=false merging f merging f failed! 0 files updated, 0 files merged, 0 files removed, 1 files unresolved use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon # cat f revision 1 space # hg stat M f ? f.orig HGMERGE specifies internal:other but is overruled by --tool=false $ HGMERGE=internal:other ; export HGMERGE $ domerge -r 2 --tool=false [merge-tools] false.whatever= true.priority=1 true.executable=cat # hg update -C 1 # hg merge -r 2 --tool=false merging f merging f failed! 0 files updated, 0 files merged, 0 files removed, 1 files unresolved use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon # cat f revision 1 space # hg stat M f ? f.orig $ unset HGMERGE # make sure HGMERGE doesn't interfere with remaining tests Default is silent simplemerge: $ domerge -r 3 [merge-tools] false.whatever= true.priority=1 true.executable=cat # hg update -C 1 # hg merge -r 3 merging f 0 files updated, 1 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) # cat f revision 1 space revision 3 # hg stat M f .premerge=True is same: $ domerge -r 3 --config merge-tools.true.premerge=True [merge-tools] false.whatever= true.priority=1 true.executable=cat # hg update -C 1 # hg merge -r 3 --config merge-tools.true.premerge=True merging f 0 files updated, 1 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) # cat f revision 1 space revision 3 # hg stat M f .premerge=False executes merge-tool: $ domerge -r 3 --config merge-tools.true.premerge=False [merge-tools] false.whatever= true.priority=1 true.executable=cat # hg update -C 1 # hg merge -r 3 --config merge-tools.true.premerge=False merging f revision 1 space revision 0 space revision 0 space revision 3 0 files updated, 1 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) # cat f revision 1 space # hg stat M f Tool execution set tools.args explicit to include $base $local $other $output: $ beforemerge [merge-tools] false.whatever= true.priority=1 true.executable=cat # hg update -C 1 $ hg merge -r 2 --config merge-tools.true.executable=head --config merge-tools.true.args='$base $local $other $output' \ > | sed 's,==> .* <==,==> ... <==,g' merging f ==> ... <== revision 0 space ==> ... <== revision 1 space ==> ... <== revision 2 space ==> ... <== revision 1 space 0 files updated, 1 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) $ aftermerge # cat f revision 1 space # hg stat M f Merge with "echo mergeresult > $local": $ beforemerge [merge-tools] false.whatever= true.priority=1 true.executable=cat # hg update -C 1 $ hg merge -r 2 --config merge-tools.true.executable=echo --config merge-tools.true.args='mergeresult > $local' merging f 0 files updated, 1 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) $ aftermerge # cat f mergeresult # hg stat M f - and $local is the file f: $ beforemerge [merge-tools] false.whatever= true.priority=1 true.executable=cat # hg update -C 1 $ hg merge -r 2 --config merge-tools.true.executable=echo --config merge-tools.true.args='mergeresult > f' merging f 0 files updated, 1 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) $ aftermerge # cat f mergeresult # hg stat M f Merge with "echo mergeresult > $output" - the variable is a bit magic: $ beforemerge [merge-tools] false.whatever= true.priority=1 true.executable=cat # hg update -C 1 $ hg merge -r 2 --config merge-tools.true.executable=echo --config merge-tools.true.args='mergeresult > $output' merging f 0 files updated, 1 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) $ aftermerge # cat f mergeresult # hg stat M f Merge using tool with a path that must be quoted: $ beforemerge [merge-tools] false.whatever= true.priority=1 true.executable=cat # hg update -C 1 $ cat < 'my merge tool' > #!/bin/sh > cat "\$1" "\$2" "\$3" > "\$4" > EOF $ chmod +x 'my merge tool' $ hg merge -r 2 --config merge-tools.true.executable='./my merge tool' --config merge-tools.true.args='$base $local $other $output' merging f 0 files updated, 1 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) $ rm -f 'my merge tool' $ aftermerge # cat f revision 0 space revision 1 space revision 2 space # hg stat M f Merge post-processing cat is a bad merge-tool and doesn't change: $ domerge -y -r 2 --config merge-tools.true.checkchanged=1 [merge-tools] false.whatever= true.priority=1 true.executable=cat # hg update -C 1 # hg merge -y -r 2 --config merge-tools.true.checkchanged=1 merging f revision 1 space revision 0 space revision 2 space output file f appears unchanged was merge successful (yn)? n merging f failed! 0 files updated, 0 files merged, 0 files removed, 1 files unresolved use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon # cat f revision 1 space # hg stat M f ? f.orig