Size: 2764
Comment: Added emacs 'emerge' command
|
Size: 4159
Comment: emacsclient script not working.
|
Deletions are marked like this. | Additions are marked like this. |
Line 1: | Line 1: |
== Using Emacs as a merger program == | #pragma section-numbers 3 == Using Emacs as a merge program == |
Line 3: | Line 4: |
[[http://www.gnu.org/software/emacs/|Emacs]] is bundled with an elisp program called Ediff which purpose is to help developers to visually apply patches. One of the various ediff commands is well suited to three way merging and can be used as a [[MergeProgram|merger program]] with [[Mercurial]]. | [[http://www.gnu.org/software/emacs/|Emacs]] is bundled with an elisp program called Ediff whose purpose is to help developers to visually apply patches. One of the ediff commands is well-suited to three-way merging and can be used as a [[MergeProgram|merge program]] with [[Mercurial]]. |
Line 5: | Line 6: |
As of Mercurial 1.0, you can configure Emacs as a merge tool (see MergeToolConfiguration): | <<TableOfContents>> === Mercurial 1.0 and later === Add the following to your ~/.hgrc file (see MergeToolConfiguration): |
Line 7: | Line 12: |
[ui] merge = emacs [merge-tools] |
|
Line 10: | Line 19: |
If you want to use the plain emerge tool in emacs, the following line works instead: | If you want to use the plain emerge tool in emacs, the following line works instead in the merge-tools section: |
Line 15: | Line 24: |
=== Mercurial 0.9.5 and earlier: Wrap Emacs+Ediff call in a script === | |
Line 16: | Line 26: |
=== Wrapping Emacs+Ediff call in a script (Mercurial 0.9.5 and earlier) === So to use [[http://www.gnu.org/software/emacs/|Emacs]] as [[Mercurial]] merger program, dump the following content into a file in your PATH (don't forget to turn on the execute bit): |
Dump the following content into a file in your PATH (don't forget to turn on the execute bit): |
Line 72: | Line 80: |
=== How the script works === | ===== How the script works ===== |
Line 76: | Line 84: |
=== Enabling the script usage === | ===== Enabling the script usage ===== |
Line 82: | Line 90: |
}}} === All Mercurial versions: using emacsclient === You may want to use 'emacsclient' to reuse an already running Emacs session. However, emacsclient does not relay errors from the server process properly (it always exits with status 0), so hg has no way to know if an error occured, '''and will happily commit the merge, possibly without you ever noticing something is amiss'''. As a workaround until [[http://debbugs.gnu.org/cgi/bugreport.cgi?bug=6963|Emacs Bug #6963]] is resolved, you'll need a wrapper script like the one below to supply the error handling. (save it as e. g. 'emacsclient-merge' and configure it like this) {{{ [ui] merge = emacsclient-merge }}} {{{ #!/bin/bash if [ $# -lt 1 ]; then echo 1>&2 "Usage: $0 local other base output" exit 1 fi local=$1 other=$2 base=$3 output=$4 OUTPUT=`emacsclient --no-wait --eval "(ediff-merge-with-ancestor \"$local\" \"$other\" \"$base\" nil \"$output\")" 2>&1` echo $OUTPUT | grep -v "Ediff Control Panel" if echo "$OUTPUT" | grep -q '^*ERROR*'; then exit 1 fi }}} Q (28 Jun, 2011): This currently does not work. Seems that others are having the same problem (https://identi.ca/notice/71698204). The error message is: *ERROR*: The merge buffer file ~/path must not be a directory |
Using Emacs as a merge program
Emacs is bundled with an elisp program called Ediff whose purpose is to help developers to visually apply patches. One of the ediff commands is well-suited to three-way merging and can be used as a merge program with Mercurial.
Contents
Mercurial 1.0 and later
Add the following to your ~/.hgrc file (see MergeToolConfiguration):
[ui] merge = emacs [merge-tools] emacs.args = -q --eval "(ediff-merge-with-ancestor \"$local\" \"$other\" \"$base\" nil \"$output\")"
If you want to use the plain emerge tool in emacs, the following line works instead in the merge-tools section:
emacs.args = -q --eval "(emerge-files-with-ancestor nil \"$local\" \"$other\" \"$base\" \"$output\" nil 'kill-emacs)"
Mercurial 0.9.5 and earlier: Wrap Emacs+Ediff call in a script
Dump the following content into a file in your PATH (don't forget to turn on the execute bit):
#!/bin/sh set -e # bail out quickly on failure LOCAL="$1" BASE="$2" OTHER="$3" BACKUP="$LOCAL.orig" Restore () { cp "$BACKUP" "$LOCAL" } ExitOK () { exit $? } # Back up our file cp "$LOCAL" "$BACKUP" # Attempt to do a non-interactive merge if which merge > /dev/null 2>&1 ; then if merge "$LOCAL" "$BASE" "$OTHER" 2> /dev/null; then # success! ExitOK fi Restore elif which diff3 > /dev/null 2>&1 ; then if diff3 -m "$BACKUP" "$BASE" "$OTHER" > "$LOCAL" ; then # success ExitOK fi Restore fi if emacs -q --no-site-file --eval "(ediff-merge-with-ancestor \"$BACKUP\" \"$OTHER\" \"$BASE\" nil \"$LOCAL\")" then ExitOK fi echo "emacs-merge: failed to merge files" exit 1 # End of file
Considering Mercurial is now able to premerge before running the merge tool and even does it by default (see hgrc(5)), I feel that attempts of merge with merge and diff3 are not needed anymore.
0.1. How the script works
This script tries first to automatically merge the files using the RCS merge program or the diff3 program. If the automatic merger fails merging the files because of a conflict or, neither merge nor diff3 are available on the system, then emacs is launched to let the developer resolve the conflicts.
0.2. Enabling the script usage
Don't forget to add an entry in your hgrc file (either ~/.hgrc or the local working copy .hg/hgrc) to point Mercurial at your merge command (let's call it emacs-merge)
[ui] merge = emacs-merge
All Mercurial versions: using emacsclient
You may want to use 'emacsclient' to reuse an already running Emacs session. However, emacsclient does not relay errors from the server process properly (it always exits with status 0), so hg has no way to know if an error occured, and will happily commit the merge, possibly without you ever noticing something is amiss.
As a workaround until Emacs Bug #6963 is resolved, you'll need a wrapper script like the one below to supply the error handling.
(save it as e. g. 'emacsclient-merge' and configure it like this)
[ui] merge = emacsclient-merge
#!/bin/bash if [ $# -lt 1 ]; then echo 1>&2 "Usage: $0 local other base output" exit 1 fi local=$1 other=$2 base=$3 output=$4 OUTPUT=`emacsclient --no-wait --eval "(ediff-merge-with-ancestor \"$local\" \"$other\" \"$base\" nil \"$output\")" 2>&1` echo $OUTPUT | grep -v "Ediff Control Panel" if echo "$OUTPUT" | grep -q '^*ERROR*'; then exit 1 fi
Q (28 Jun, 2011): This currently does not work. Seems that others are having the same problem (https://identi.ca/notice/71698204). The error message is: *ERROR*: The merge buffer file ~/path must not be a directory