##// END OF EJS Templates
Safer version of FileMerge merge
Brendan Cully -
r1664:4338e33c default
parent child Browse files
Show More
@@ -1,120 +1,143 b''
1 1 #!/bin/sh
2 2 #
3 3 # hgmerge - default merge helper for Mercurial
4 4 #
5 5 # This tries to find a way to do three-way merge on the current system.
6 6 # The result ought to end up in $1.
7 7
8 8 set -e # bail out quickly on failure
9 9
10 10 LOCAL="$1"
11 11 BASE="$2"
12 12 OTHER="$3"
13 13
14 14 if [ -z "$EDITOR" ]; then
15 15 EDITOR="vi"
16 16 fi
17 17
18 18 # find decent versions of our utilities, insisting on the GNU versions where we
19 19 # need to
20 20 DIFF3=gdiff3
21 21 DIFF=gdiff
22 22 PATCH=gpatch
23 23
24 24 type $DIFF3 >/dev/null 2>&1 || DIFF3=diff3
25 25 type $DIFF >/dev/null 2>&1 || DIFF=diff
26 26 type $PATCH >/dev/null 2>&1 || PATCH=patch
27 27 $DIFF3 --version >/dev/null 2>&1 || DIFF3=
28 28
29 29 # Back up our file
30 30 cp "$LOCAL" "$LOCAL.orig"
31 31
32 32 # Attempt to do a non-interactive merge
33 33 if type merge > /dev/null 2>&1; then
34 34 merge "$LOCAL" "$BASE" "$OTHER" 2> /dev/null && exit 0
35 35 cp "$LOCAL.orig" "$LOCAL"
36 36 elif [ -n "$DIFF3" ]; then
37 37 echo $DIFF3 -m "$LOCAL.orig" "$BASE" "$OTHER"
38 38 $DIFF3 -m "$LOCAL.orig" "$BASE" "$OTHER" > "$LOCAL" && exit 0
39 39 if [ $? -eq 2 ]; then
40 40 echo "$DIFF3 failed! Exiting." 1>&2
41 41 cp "$LOCAL.orig" "$LOCAL"
42 42 exit 1
43 43 fi
44 44 cp "$LOCAL.orig" "$LOCAL"
45 45 fi
46 46
47 # on MacOS X try opendiff
48 # (uses FileMerge.app, shipped with Apple's developer tools)
49 if type opendiff > /dev/null 2>&1; then
50 opendiff "$LOCAL.orig" "$OTHER" -ancestor "$BASE" -merge "$LOCAL" || exit 1
51 # prevent $OTHER from being removed too early
52 # can surely be done in a more elegant way
53 sleep 1
54 exit 0
47 # on MacOS X try FileMerge.app, shipped with Apple's developer tools
48 # TODO: make proper temp files. foo.orig and foo.link are dangerous
49 FILEMERGE='/Developer/Applications/Utilities/FileMerge.app/Contents/MacOS/FileMerge'
50 if type "$FILEMERGE" > /dev/null 2>&1; then
51 cp "$LOCAL.orig" "$LOCAL"
52 ln "$LOCAL" "$LOCAL.link"
53 # filemerge prefers the right by default
54 if ! "$FILEMERGE" -left "$OTHER" -right "$LOCAL" -ancestor "$BASE" -merge "$LOCAL"
55 then
56 echo "FileMerge failed to launch"
57 exit 1
58 fi
59 if ! test "$LOCAL" -ef "$LOCAL.link"
60 then
61 rm "$LOCAL.orig" "$LOCAL.link"
62 exit 0
63 else
64 rm "$LOCAL.link"
65 echo "$LOCAL is unchanged. Was the merge successful?"
66 select answer in yes no
67 do
68 if test "$answer" == "yes"
69 then
70 rm "$LOCAL.orig"
71 exit 0
72 else
73 exit 1
74 fi
75 done
76 exit 1
77 fi
55 78 fi
56 79
57 80 if [ -n "$DISPLAY" ]; then
58 81 # try using kdiff3, which is fairly nice
59 82 if type kdiff3 > /dev/null 2>&1; then
60 83 kdiff3 --auto "$BASE" "$LOCAL" "$OTHER" -o "$LOCAL" || exit 1
61 84 exit 0
62 85 fi
63 86
64 87 # try using tkdiff, which is a bit less sophisticated
65 88 if type tkdiff > /dev/null 2>&1; then
66 89 tkdiff "$LOCAL" "$OTHER" -a "$BASE" -o "$LOCAL" || exit 1
67 90 exit 0
68 91 fi
69 92 fi
70 93
71 94 # Attempt to do a merge with $EDITOR
72 95 if type merge > /dev/null 2>&1; then
73 96 echo "conflicts detected in $LOCAL"
74 97 merge "$LOCAL" "$BASE" "$OTHER" 2>/dev/null || $EDITOR "$LOCAL"
75 98 exit 0
76 99 fi
77 100
78 101 if [ -n "$DIFF3" ]; then
79 102 echo "conflicts detected in $LOCAL"
80 103 $DIFF3 -m "$LOCAL.orig" "$BASE" "$OTHER" > "$LOCAL" || {
81 104 case $? in
82 105 1)
83 106 $EDITOR "$LOCAL" ;;
84 107 2) echo "$DIFF3 failed! Exiting." 1>&2
85 108 cp "$LOCAL.orig" "$LOCAL"
86 109 exit 1 ;;
87 110 esac
88 111 exit 0
89 112 }
90 113 fi
91 114
92 115 HGTMP=""
93 116 cleanup_exit() {
94 117 rm -rf "$HGTMP"
95 118 }
96 119
97 120 # attempt to manually merge with diff and patch
98 121 if [ -n "$DIFF" -a -n "$PATCH" ]; then
99 122 # Remove temporary files even if we get interrupted
100 123 trap "cleanup_exit" 0 # normal exit
101 124 trap "exit 1" 1 2 3 6 15 # HUP INT QUIT ABRT TERM
102 125
103 126 HGTMP="${TMPDIR-/tmp}/hgmerge.$RANDOM.$RANDOM.$RANDOM.$$"
104 127 (umask 077 && mkdir "$HGTMP") || {
105 128 echo "Could not create temporary directory! Exiting." 1>&2
106 129 exit 1
107 130 }
108 131
109 132 $DIFF -u "$BASE" "$OTHER" > "$HGTMP/diff" || :
110 133 if $PATCH "$LOCAL" < "$HGTMP/diff"; then
111 134 exit 0
112 135 else
113 136 # If rejects are empty after using the editor, merge was ok
114 137 $EDITOR "$LOCAL" "$LOCAL.rej" && test -s "$LOCAL.rej" || exit 0
115 138 fi
116 139 exit 1
117 140 fi
118 141
119 142 echo "hgmerge: unable to find merge, tkdiff, kdiff3, or diff+patch!"
120 143 exit 1
General Comments 0
You need to be logged in to leave comments. Login now