15 EDITOR="vi" |
15 EDITOR="vi" |
16 fi |
16 fi |
17 |
17 |
18 # find decent versions of our utilities, insisting on the GNU versions where we |
18 # find decent versions of our utilities, insisting on the GNU versions where we |
19 # need to |
19 # need to |
20 MERGE=merge |
20 MERGE="merge" |
21 DIFF3=gdiff3 |
21 DIFF3="gdiff3" |
22 DIFF=gdiff |
22 DIFF="gdiff" |
23 PATCH=gpatch |
23 PATCH="gpatch" |
24 |
24 |
25 type $MERGE >/dev/null 2>&1 || MERGE= |
25 type "$MERGE" >/dev/null 2>&1 || MERGE= |
26 type $DIFF3 >/dev/null 2>&1 || DIFF3=diff3 |
26 type "$DIFF3" >/dev/null 2>&1 || DIFF3="diff3" |
27 type $DIFF >/dev/null 2>&1 || DIFF=diff |
|
28 type $PATCH >/dev/null 2>&1 || PATCH=patch |
|
29 $DIFF3 --version >/dev/null 2>&1 || DIFF3= |
27 $DIFF3 --version >/dev/null 2>&1 || DIFF3= |
|
28 type "$DIFF" >/dev/null 2>&1 || DIFF="diff" |
|
29 type "$DIFF" >/dev/null 2>&1 || DIFF= |
|
30 type "$PATCH" >/dev/null 2>&1 || PATCH="patch" |
|
31 type "$PATCH" >/dev/null 2>&1 || PATCH= |
30 |
32 |
31 # find optional visual utilities |
33 # find optional visual utilities |
32 FILEMERGE='/Developer/Applications/Utilities/FileMerge.app/Contents/MacOS/FileMerge' |
34 FILEMERGE="/Developer/Applications/Utilities/FileMerge.app/Contents/MacOS/FileMerge" |
33 KDIFF3=kdiff3 |
35 KDIFF3="kdiff3" |
34 TKDIFF=tkdiff |
36 TKDIFF="tkdiff" |
|
37 MELD="meld" |
35 |
38 |
36 type $FILEMERGE >/dev/null 2>&1 || FILEMERGE= |
39 type "$FILEMERGE" >/dev/null 2>&1 || FILEMERGE= |
37 type $KDIFF3 >/dev/null 2>&1 || KDIFF3= |
40 type "$KDIFF3" >/dev/null 2>&1 || KDIFF3= |
38 type $TKDIFF >/dev/null 2>&1 || TKDIFF= |
41 type "$TKDIFF" >/dev/null 2>&1 || TKDIFF= |
|
42 type "$MELD" >/dev/null 2>&1 || MELD= |
39 |
43 |
40 # random part of names |
44 # random part of names |
41 RAND="$RANDOM.$RANDOM.$RANDOM.$$" |
45 RAND="$RANDOM$RANDOM" |
42 |
46 |
43 # temporary directory for diff+patch merge |
47 # temporary directory for diff+patch merge |
44 HGTMP="${TMPDIR-/tmp}/hgmerge.$RAND" |
48 HGTMP="${TMPDIR-/tmp}/hgmerge.$RAND" |
45 |
49 |
46 # backup file |
50 # backup file |
66 mv "$BACKUP" "$LOCAL" |
70 mv "$BACKUP" "$LOCAL" |
67 cleanup |
71 cleanup |
68 exit 1 |
72 exit 1 |
69 } |
73 } |
70 |
74 |
|
75 # Ask if the merge was successful |
|
76 ask_if_merged() { |
|
77 while true; do |
|
78 echo "$LOCAL seems unchanged." |
|
79 echo "Was the merge successful? [y/n]" |
|
80 read answer |
|
81 case "$answer" in |
|
82 y*|Y*) success;; |
|
83 n*|N*) failure;; |
|
84 esac |
|
85 done |
|
86 } |
|
87 |
71 # Clean up when interrupted |
88 # Clean up when interrupted |
72 trap "failure" 1 2 3 6 15 # HUP INT QUIT ABRT TERM |
89 trap "failure" 1 2 3 6 15 # HUP INT QUIT ABRT TERM |
73 |
90 |
74 # Back up our file (and try hard to keep the mtime unchanged) |
91 # Back up our file (and try hard to keep the mtime unchanged) |
75 mv "$LOCAL" "$BACKUP" |
92 mv "$LOCAL" "$BACKUP" |
76 cp "$BACKUP" "$LOCAL" |
93 cp "$BACKUP" "$LOCAL" |
77 |
94 |
78 # Attempt to do a non-interactive merge |
95 # Attempt to do a non-interactive merge |
79 if [ -n "$MERGE" ]; then |
96 if [ -n "$MERGE" -o -n "$DIFF3" ]; then |
80 $MERGE "$LOCAL" "$BASE" "$OTHER" 2> /dev/null && success |
97 if [ -n "$MERGE" ]; then |
81 cp "$BACKUP" "$LOCAL" |
98 $MERGE "$LOCAL" "$BASE" "$OTHER" 2> /dev/null && success |
82 elif [ -n "$DIFF3" ]; then |
99 elif [ -n "$DIFF3" ]; then |
83 echo $DIFF3 -m "$BACKUP" "$BASE" "$OTHER" |
100 $DIFF3 -m "$BACKUP" "$BASE" "$OTHER" > "$LOCAL" && success |
84 $DIFF3 -m "$BACKUP" "$BASE" "$OTHER" > "$LOCAL" && success |
101 fi |
85 if [ $? -eq 2 ]; then |
102 if [ $? -gt 1 ]; then |
86 echo "$DIFF3 failed! Exiting." 1>&2 |
103 echo "automatic merge failed! Exiting." 1>&2 |
87 cp "$BACKUP" "$LOCAL" |
|
88 failure |
104 failure |
89 fi |
105 fi |
90 cp "$BACKUP" "$LOCAL" |
|
91 fi |
106 fi |
92 |
107 |
93 # on MacOS X try FileMerge.app, shipped with Apple's developer tools |
108 # on MacOS X try FileMerge.app, shipped with Apple's developer tools |
94 if [ -n "$FILEMERGE" ]; then |
109 if [ -n "$FILEMERGE" ]; then |
95 cp "$BACKUP" "$LOCAL" |
110 cp "$BACKUP" "$LOCAL" |
96 cp "$BACKUP" "$CHGTEST" |
111 cp "$BACKUP" "$CHGTEST" |
97 # filemerge prefers the right by default |
112 # filemerge prefers the right by default |
98 $FILEMERGE -left "$OTHER" -right "$LOCAL" -ancestor "$BASE" -merge "$LOCAL" |
113 $FILEMERGE -left "$OTHER" -right "$LOCAL" -ancestor "$BASE" -merge "$LOCAL" |
99 [ $? -ne 0 ] && echo "FileMerge failed to launch" && failure |
114 [ $? -ne 0 ] && echo "FileMerge failed to launch" && failure |
100 if test "$LOCAL" -nt "$CHGTEST" |
115 test "$LOCAL" -nt "$CHGTEST" && success || ask_if_merged |
101 then |
|
102 success |
|
103 else |
|
104 echo "$LOCAL seems unchanged. Was the merge successful?" |
|
105 select answer in yes no |
|
106 do |
|
107 test "$answer" == "yes" && success || failure |
|
108 done |
|
109 fi |
|
110 failure |
|
111 fi |
116 fi |
112 |
117 |
113 if [ -n "$DISPLAY" ]; then |
118 if [ -n "$DISPLAY" ]; then |
114 # try using kdiff3, which is fairly nice |
119 # try using kdiff3, which is fairly nice |
115 if [ -n "$KDIFF3" ]; then |
120 if [ -n "$KDIFF3" ]; then |
116 $KDIFF3 --auto "$BASE" "$LOCAL" "$OTHER" -o "$LOCAL" || failure |
121 $KDIFF3 --auto "$BASE" "$BACKUP" "$OTHER" -o "$LOCAL" || failure |
117 success |
122 success |
118 fi |
123 fi |
119 |
124 |
120 # try using tkdiff, which is a bit less sophisticated |
125 # try using tkdiff, which is a bit less sophisticated |
121 if [ -n "$TKDIFF" ]; then |
126 if [ -n "$TKDIFF" ]; then |
122 $TKDIFF "$LOCAL" "$OTHER" -a "$BASE" -o "$LOCAL" || failure |
127 $TKDIFF "$BACKUP" "$OTHER" -a "$BASE" -o "$LOCAL" || failure |
123 success |
128 success |
|
129 fi |
|
130 |
|
131 if [ -n "$MELD" ]; then |
|
132 cp "$BACKUP" "$CHGTEST" |
|
133 # protect our feet - meld allows us to save to the left file |
|
134 cp "$BACKUP" "$LOCAL.tmp.$RAND" |
|
135 # Meld doesn't have automatic merging, so to reduce intervention |
|
136 # use the file with conflicts |
|
137 $MELD "$LOCAL.tmp.$RAND" "$LOCAL" "$OTHER" || failure |
|
138 # Also it doesn't return good error code |
|
139 test "$LOCAL" -nt "$CHGTEST" && success || ask_if_merged |
124 fi |
140 fi |
125 fi |
141 fi |
126 |
142 |
127 # Attempt to do a merge with $EDITOR |
143 # Attempt to do a merge with $EDITOR |
128 if [ -n "$MERGE" ]; then |
144 if [ -n "$MERGE" -o -n "$DIFF3" ]; then |
129 echo "conflicts detected in $LOCAL" |
145 echo "conflicts detected in $LOCAL" |
130 $MERGE "$LOCAL" "$BASE" "$OTHER" 2>/dev/null || $EDITOR "$LOCAL" |
146 cp "$BACKUP" "$CHGTEST" |
131 success |
147 $EDITOR "$LOCAL" || failure |
132 fi |
148 # Some editors do not return meaningful error codes |
133 |
149 # Do not take any chances |
134 if [ -n "$DIFF3" ]; then |
150 test "$LOCAL" -nt "$CHGTEST" && success || ask_if_merged |
135 echo "conflicts detected in $LOCAL" |
|
136 $DIFF3 -m "$BACKUP" "$BASE" "$OTHER" > "$LOCAL" || { |
|
137 case $? in |
|
138 1) |
|
139 $EDITOR "$LOCAL" ;; |
|
140 2) echo "$DIFF3 failed! Exiting." 1>&2 |
|
141 cp "$BACKUP" "$LOCAL" |
|
142 failure ;; |
|
143 esac |
|
144 success |
|
145 } |
|
146 fi |
151 fi |
147 |
152 |
148 # attempt to manually merge with diff and patch |
153 # attempt to manually merge with diff and patch |
149 if [ -n "$DIFF" -a -n "$PATCH" ]; then |
154 if [ -n "$DIFF" -a -n "$PATCH" ]; then |
150 |
155 |
151 (umask 077 && mkdir "$HGTMP") || { |
156 (umask 077 && mkdir "$HGTMP") || { |
152 echo "Could not create temporary directory $HGTMP" 1>&2 |
157 echo "Could not create temporary directory $HGTMP" 1>&2 |
153 failure |
158 failure |
154 } |
159 } |
155 |
160 |
156 $DIFF -u "$BASE" "$OTHER" > "$HGTMP/diff" || : |
161 $DIFF -u "$BASE" "$OTHER" > "$HGTMP/diff" || : |
157 if $PATCH "$LOCAL" < "$HGTMP/diff"; then |
162 if $PATCH "$LOCAL" < "$HGTMP/diff"; then |
158 success |
163 success |
159 else |
164 else |
160 # If rejects are empty after using the editor, merge was ok |
165 # If rejects are empty after using the editor, merge was ok |
161 $EDITOR "$LOCAL" "$LOCAL.rej" && test -s "$LOCAL.rej" || success |
166 $EDITOR "$LOCAL" "$LOCAL.rej" || failure |
|
167 test -s "$LOCAL.rej" || success |
162 fi |
168 fi |
163 failure |
169 failure |
164 fi |
170 fi |
165 |
171 |
166 echo "hgmerge: unable to find merge, tkdiff, kdiff3, or diff+patch!" |
172 echo |
|
173 echo "hgmerge: unable to find any merge utility!" |
|
174 echo "supported programs:" |
|
175 echo "merge, FileMerge, tkdiff, kdiff3, meld, diff+patch" |
|
176 echo |
167 failure |
177 failure |