#!/bin/sh # # hgmerge - default merge helper for Mercurial # # This tries to find a way to do three-way merge on the current system. # The result ought to end up in $1. set -e # bail out quickly on failure LOCAL="$1" BASE="$2" OTHER="$3" if [ -z "$EDITOR" ]; then EDITOR="vi" fi # find decent versions of our utilities, insisting on the GNU versions where we # need to DIFF3=gdiff3 DIFF=gdiff PATCH=gpatch type $DIFF3 >/dev/null 2>&1 || DIFF3=diff3 type $DIFF >/dev/null 2>&1 || DIFF=diff type $PATCH >/dev/null 2>&1 || PATCH=patch $DIFF3 --version >/dev/null 2>&1 || DIFF3= # Back up our file cp "$LOCAL" "$LOCAL.orig" # Attempt to do a non-interactive merge if type merge > /dev/null 2>&1; then merge "$LOCAL" "$BASE" "$OTHER" 2> /dev/null && exit 0 cp "$LOCAL.orig" "$LOCAL" elif [ -n "$DIFF3" ]; then echo $DIFF3 -m "$LOCAL.orig" "$BASE" "$OTHER" $DIFF3 -m "$LOCAL.orig" "$BASE" "$OTHER" > "$LOCAL" && exit 0 if [ $? -eq 2 ]; then echo "$DIFF3 failed! Exiting." 1>&2 cp "$LOCAL.orig" "$LOCAL" exit 1 fi cp "$LOCAL.orig" "$LOCAL" fi # on MacOS X try FileMerge.app, shipped with Apple's developer tools # TODO: make proper temp files. foo.orig and foo.link are dangerous FILEMERGE='/Developer/Applications/Utilities/FileMerge.app/Contents/MacOS/FileMerge' if type "$FILEMERGE" > /dev/null 2>&1; then cp "$LOCAL.orig" "$LOCAL" ln "$LOCAL" "$LOCAL.link" # filemerge prefers the right by default if ! "$FILEMERGE" -left "$OTHER" -right "$LOCAL" -ancestor "$BASE" -merge "$LOCAL" then echo "FileMerge failed to launch" exit 1 fi if ! test "$LOCAL" -ef "$LOCAL.link" then rm "$LOCAL.orig" "$LOCAL.link" exit 0 else rm "$LOCAL.link" echo "$LOCAL is unchanged. Was the merge successful?" select answer in yes no do if test "$answer" == "yes" then rm "$LOCAL.orig" exit 0 else exit 1 fi done exit 1 fi fi if [ -n "$DISPLAY" ]; then # try using kdiff3, which is fairly nice if type kdiff3 > /dev/null 2>&1; then kdiff3 --auto "$BASE" "$LOCAL" "$OTHER" -o "$LOCAL" || exit 1 exit 0 fi # try using tkdiff, which is a bit less sophisticated if type tkdiff > /dev/null 2>&1; then tkdiff "$LOCAL" "$OTHER" -a "$BASE" -o "$LOCAL" || exit 1 exit 0 fi fi # Attempt to do a merge with $EDITOR if type merge > /dev/null 2>&1; then echo "conflicts detected in $LOCAL" merge "$LOCAL" "$BASE" "$OTHER" 2>/dev/null || $EDITOR "$LOCAL" exit 0 fi if [ -n "$DIFF3" ]; then echo "conflicts detected in $LOCAL" $DIFF3 -m "$LOCAL.orig" "$BASE" "$OTHER" > "$LOCAL" || { case $? in 1) $EDITOR "$LOCAL" ;; 2) echo "$DIFF3 failed! Exiting." 1>&2 cp "$LOCAL.orig" "$LOCAL" exit 1 ;; esac exit 0 } fi HGTMP="" cleanup_exit() { rm -rf "$HGTMP" } # attempt to manually merge with diff and patch if [ -n "$DIFF" -a -n "$PATCH" ]; then # Remove temporary files even if we get interrupted trap "cleanup_exit" 0 # normal exit trap "exit 1" 1 2 3 6 15 # HUP INT QUIT ABRT TERM HGTMP="${TMPDIR-/tmp}/hgmerge.$RANDOM.$RANDOM.$RANDOM.$$" (umask 077 && mkdir "$HGTMP") || { echo "Could not create temporary directory! Exiting." 1>&2 exit 1 } $DIFF -u "$BASE" "$OTHER" > "$HGTMP/diff" || : if $PATCH "$LOCAL" < "$HGTMP/diff"; then exit 0 else # If rejects are empty after using the editor, merge was ok $EDITOR "$LOCAL" "$LOCAL.rej" && test -s "$LOCAL.rej" || exit 0 fi exit 1 fi echo "hgmerge: unable to find merge, tkdiff, kdiff3, or diff+patch!" exit 1