hgmerge
author Radoslaw Szkodzinski <astralstorm@gorzow.mm.pl>
Mon, 06 Feb 2006 17:32:06 -0600
changeset 1700 e2f91e0acbb8
parent 1699 83e8cd97b9f9
child 1701 4ba8fe499df2
permissions -rwxr-xr-x
hgmerge: add cleanup functions This patch adds functions cleanup, success and failure. The last two of these should be used instead of exit. Current code was changed to use them. It also moves $HGTMP to the top of the file (it's used in the cleanup function), changes the comment and removes now unneeded trap in the diff+patch merge.

#!/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
MERGE=merge
DIFF3=gdiff3
DIFF=gdiff
PATCH=gpatch

type $MERGE >/dev/null 2>&1 || MERGE=
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=

# find optional visual utilities
FILEMERGE='/Developer/Applications/Utilities/FileMerge.app/Contents/MacOS/FileMerge'
KDIFF3=kdiff3
TKDIFF=tkdiff

type $FILEMERGE >/dev/null 2>&1 || FILEMERGE=
type $KDIFF3    >/dev/null 2>&1 || KDIFF3=
type $TKDIFF    >/dev/null 2>&1 || TKDIFF=

# temporary directory for diff+patch merge
HGTMP="${TMPDIR-/tmp}/hgmerge.$RANDOM.$RANDOM.$RANDOM.$$"

# put all your required cleanup here
cleanup() {
    rm -f "$LOCAL.orig"
    rm -rf "$HGTMP"
}

# functions concerning program exit
success() {
    cleanup
    exit 0
}

failure() {
    echo "merge failed" 1>&2
    cp "$LOCAL.orig" "$LOCAL"
    cleanup
    exit 1
}

# Clean up when interrupted
trap "failure" 1 2 3 6 15 # HUP INT QUIT ABRT TERM

# Back up our file
cp "$LOCAL" "$LOCAL.orig"

# Attempt to do a non-interactive merge
if [ -n "$MERGE" ]; then
    $MERGE "$LOCAL" "$BASE" "$OTHER" 2> /dev/null && success
    cp "$LOCAL.orig" "$LOCAL"
elif [ -n "$DIFF3" ]; then
    echo $DIFF3 -m "$LOCAL.orig" "$BASE" "$OTHER"
    $DIFF3 -m "$LOCAL.orig" "$BASE" "$OTHER" > "$LOCAL" && success
    if [ $? -eq 2 ]; then
        echo "$DIFF3 failed! Exiting." 1>&2
        cp "$LOCAL.orig" "$LOCAL"
        failure
    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

if [ -n "$FILEMERGE" ]; 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"
        failure
    fi
    if ! test "$LOCAL" -ef "$LOCAL.link"
    then
        rm "$LOCAL.orig" "$LOCAL.link"
        success
    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"
                success
            else
                failure
            fi
        done
        failure
    fi
fi

if [ -n "$DISPLAY" ]; then
    # try using kdiff3, which is fairly nice
    if [ -n "$KDIFF3" ]; then
	$KDIFF3 --auto "$BASE" "$LOCAL" "$OTHER" -o "$LOCAL" || failure
	success
    fi

    # try using tkdiff, which is a bit less sophisticated
    if [ -n "$TKDIFF" ]; then
	$TKDIFF "$LOCAL" "$OTHER" -a "$BASE" -o "$LOCAL" || failure
	success
    fi
fi

# Attempt to do a merge with $EDITOR
if [ -n "$MERGE" ]; then
    echo "conflicts detected in $LOCAL"
    $MERGE "$LOCAL" "$BASE" "$OTHER" 2>/dev/null || $EDITOR "$LOCAL"
    success
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"
                failure ;;
        esac
        success
    }
fi

# attempt to manually merge with diff and patch
if [ -n "$DIFF" -a -n "$PATCH" ]; then

    (umask 077 && mkdir "$HGTMP") || {
	echo "Could not create temporary directory $HGTMP" 1>&2
	failure
    }

    $DIFF -u "$BASE" "$OTHER" > "$HGTMP/diff" || :
    if $PATCH "$LOCAL" < "$HGTMP/diff"; then
	success
    else
	# If rejects are empty after using the editor, merge was ok
	$EDITOR "$LOCAL" "$LOCAL.rej" && test -s "$LOCAL.rej" || success
    fi
    failure
fi

echo "hgmerge: unable to find merge, tkdiff, kdiff3, or diff+patch!"
failure