mergetool--lib: Make style consistent with git
[git/git.git] / git-mergetool--lib.sh
CommitLineData
02e51243 1#!/bin/sh
21d0ba7e
DA
2# git-mergetool--lib is a library for common merge tool functions
3diff_mode() {
4 test "$TOOL_MODE" = diff
5}
6
7merge_mode() {
8 test "$TOOL_MODE" = merge
9}
10
11translate_merge_tool_path () {
47d65924 12 case "$1" in
aa03f604
SS
13 araxis)
14 echo compare
47d65924 15 ;;
ffe6dc08
SS
16 bc3)
17 echo bcompare
47d65924
DA
18 ;;
19 emerge)
20 echo emacs
21 ;;
aa03f604
SS
22 gvimdiff|gvimdiff2)
23 echo gvim
24 ;;
25 vimdiff|vimdiff2)
26 echo vim
b6f0621a 27 ;;
47d65924
DA
28 *)
29 echo "$1"
30 ;;
31 esac
21d0ba7e
DA
32}
33
34check_unchanged () {
240dc3e8
DA
35 if test "$MERGED" -nt "$BACKUP"
36 then
21d0ba7e
DA
37 status=0
38 else
240dc3e8
DA
39 while true
40 do
21d0ba7e
DA
41 echo "$MERGED seems unchanged."
42 printf "Was the merge successful? [y/n] "
af314714 43 read answer
21d0ba7e
DA
44 case "$answer" in
45 y*|Y*) status=0; break ;;
46 n*|N*) status=1; break ;;
47 esac
48 done
49 fi
50}
51
52valid_tool () {
53 case "$1" in
ffe6dc08 54 araxis | bc3 | diffuse | ecmerge | emerge | gvimdiff | gvimdiff2 | \
aa03f604 55 kdiff3 | meld | opendiff | p4merge | tkdiff | vimdiff | vimdiff2 | xxdiff)
21d0ba7e 56 ;; # happy
aa03f604 57 kompare)
240dc3e8
DA
58 if ! diff_mode
59 then
21d0ba7e
DA
60 return 1
61 fi
62 ;;
aa03f604 63 tortoisemerge)
240dc3e8
DA
64 if ! merge_mode
65 then
21d0ba7e
DA
66 return 1
67 fi
68 ;;
69 *)
240dc3e8
DA
70 if test -z "$(get_merge_tool_cmd "$1")"
71 then
21d0ba7e
DA
72 return 1
73 fi
74 ;;
75 esac
76}
77
78get_merge_tool_cmd () {
47d65924 79 # Prints the custom command for a merge tool
240dc3e8
DA
80 if test -n "$1"
81 then
47d65924
DA
82 merge_tool="$1"
83 else
84 merge_tool="$(get_merge_tool)"
85 fi
240dc3e8
DA
86 if diff_mode
87 then
47d65924 88 echo "$(git config difftool.$merge_tool.cmd ||
285c6cbf 89 git config mergetool.$merge_tool.cmd)"
47d65924
DA
90 else
91 echo "$(git config mergetool.$merge_tool.cmd)"
92 fi
21d0ba7e
DA
93}
94
95run_merge_tool () {
f9ad901f
DA
96 # If GIT_PREFIX is empty then we cannot use it in tools
97 # that expect to be able to chdir() to its value.
98 GIT_PREFIX=${GIT_PREFIX:-.}
99 export GIT_PREFIX
100
47d65924 101 merge_tool_path="$(get_merge_tool_path "$1")" || exit
21d0ba7e
DA
102 base_present="$2"
103 status=0
104
105 case "$1" in
aa03f604 106 araxis)
240dc3e8
DA
107 if merge_mode
108 then
aa03f604 109 touch "$BACKUP"
240dc3e8
DA
110 if $base_present
111 then
aa03f604
SS
112 "$merge_tool_path" -wait -merge -3 -a1 \
113 "$BASE" "$LOCAL" "$REMOTE" "$MERGED" \
114 >/dev/null 2>&1
21d0ba7e 115 else
aa03f604
SS
116 "$merge_tool_path" -wait -2 \
117 "$LOCAL" "$REMOTE" "$MERGED" \
118 >/dev/null 2>&1
21d0ba7e 119 fi
aa03f604 120 check_unchanged
21d0ba7e 121 else
aa03f604
SS
122 "$merge_tool_path" -wait -2 "$LOCAL" "$REMOTE" \
123 >/dev/null 2>&1
21d0ba7e
DA
124 fi
125 ;;
ffe6dc08 126 bc3)
240dc3e8
DA
127 if merge_mode
128 then
ffe6dc08 129 touch "$BACKUP"
240dc3e8
DA
130 if $base_present
131 then
ffe6dc08
SS
132 "$merge_tool_path" "$LOCAL" "$REMOTE" "$BASE" \
133 -mergeoutput="$MERGED"
21d0ba7e 134 else
ffe6dc08
SS
135 "$merge_tool_path" "$LOCAL" "$REMOTE" \
136 -mergeoutput="$MERGED"
21d0ba7e 137 fi
ffe6dc08 138 check_unchanged
21d0ba7e
DA
139 else
140 "$merge_tool_path" "$LOCAL" "$REMOTE"
141 fi
142 ;;
aa03f604 143 diffuse)
240dc3e8
DA
144 if merge_mode
145 then
aa03f604 146 touch "$BACKUP"
240dc3e8
DA
147 if $base_present
148 then
aa03f604
SS
149 "$merge_tool_path" \
150 "$LOCAL" "$MERGED" "$REMOTE" \
151 "$BASE" | cat
c8998b48 152 else
21d0ba7e 153 "$merge_tool_path" \
aa03f604 154 "$LOCAL" "$MERGED" "$REMOTE" | cat
c8998b48
SC
155 fi
156 check_unchanged
157 else
aa03f604 158 "$merge_tool_path" "$LOCAL" "$REMOTE" | cat
c8998b48
SC
159 fi
160 ;;
aa03f604 161 ecmerge)
240dc3e8
DA
162 if merge_mode
163 then
21d0ba7e 164 touch "$BACKUP"
240dc3e8
DA
165 if $base_present
166 then
aa03f604
SS
167 "$merge_tool_path" "$BASE" "$LOCAL" "$REMOTE" \
168 --default --mode=merge3 --to="$MERGED"
c8998b48 169 else
aa03f604
SS
170 "$merge_tool_path" "$LOCAL" "$REMOTE" \
171 --default --mode=merge2 --to="$MERGED"
c8998b48 172 fi
21d0ba7e
DA
173 check_unchanged
174 else
aa03f604
SS
175 "$merge_tool_path" --default --mode=diff2 \
176 "$LOCAL" "$REMOTE"
21d0ba7e
DA
177 fi
178 ;;
aa03f604 179 emerge)
240dc3e8
DA
180 if merge_mode
181 then
182 if $base_present
183 then
21d0ba7e 184 "$merge_tool_path" \
aa03f604
SS
185 -f emerge-files-with-ancestor-command \
186 "$LOCAL" "$REMOTE" "$BASE" \
187 "$(basename "$MERGED")"
21d0ba7e
DA
188 else
189 "$merge_tool_path" \
aa03f604
SS
190 -f emerge-files-command \
191 "$LOCAL" "$REMOTE" \
192 "$(basename "$MERGED")"
21d0ba7e 193 fi
aa03f604 194 status=$?
21d0ba7e 195 else
aa03f604
SS
196 "$merge_tool_path" -f emerge-files-command \
197 "$LOCAL" "$REMOTE"
21d0ba7e
DA
198 fi
199 ;;
aa03f604 200 gvimdiff|vimdiff)
240dc3e8
DA
201 if merge_mode
202 then
21d0ba7e 203 touch "$BACKUP"
240dc3e8
DA
204 if $base_present
205 then
829ef383
DM
206 "$merge_tool_path" -f -d -c "wincmd J" \
207 "$MERGED" "$LOCAL" "$BASE" "$REMOTE"
208 else
209 "$merge_tool_path" -f -d -c "wincmd l" \
210 "$LOCAL" "$MERGED" "$REMOTE"
211 fi
21d0ba7e
DA
212 check_unchanged
213 else
853c0ffe 214 "$merge_tool_path" -R -f -d -c "wincmd l" \
f9ad901f 215 -c 'cd $GIT_PREFIX' \
21d0ba7e
DA
216 "$LOCAL" "$REMOTE"
217 fi
218 ;;
aa03f604 219 gvimdiff2|vimdiff2)
240dc3e8
DA
220 if merge_mode
221 then
00086690
DM
222 touch "$BACKUP"
223 "$merge_tool_path" -f -d -c "wincmd l" \
224 "$LOCAL" "$MERGED" "$REMOTE"
225 check_unchanged
226 else
853c0ffe 227 "$merge_tool_path" -R -f -d -c "wincmd l" \
f9ad901f 228 -c 'cd $GIT_PREFIX' \
00086690
DM
229 "$LOCAL" "$REMOTE"
230 fi
231 ;;
aa03f604 232 kdiff3)
240dc3e8
DA
233 if merge_mode
234 then
235 if $base_present
236 then
237 "$merge_tool_path" --auto \
aa03f604
SS
238 --L1 "$MERGED (Base)" \
239 --L2 "$MERGED (Local)" \
240 --L3 "$MERGED (Remote)" \
241 -o "$MERGED" \
242 "$BASE" "$LOCAL" "$REMOTE" \
240dc3e8 243 >/dev/null 2>&1
21d0ba7e 244 else
240dc3e8 245 "$merge_tool_path" --auto \
aa03f604
SS
246 --L1 "$MERGED (Local)" \
247 --L2 "$MERGED (Remote)" \
248 -o "$MERGED" \
249 "$LOCAL" "$REMOTE" \
240dc3e8 250 >/dev/null 2>&1
21d0ba7e 251 fi
aa03f604
SS
252 status=$?
253 else
240dc3e8 254 "$merge_tool_path" --auto \
aa03f604
SS
255 --L1 "$MERGED (A)" \
256 --L2 "$MERGED (B)" "$LOCAL" "$REMOTE" \
240dc3e8 257 >/dev/null 2>&1
aa03f604
SS
258 fi
259 ;;
260 kompare)
261 "$merge_tool_path" "$LOCAL" "$REMOTE"
262 ;;
263 meld)
240dc3e8
DA
264 if merge_mode
265 then
aa03f604
SS
266 touch "$BACKUP"
267 "$merge_tool_path" "$LOCAL" "$MERGED" "$REMOTE"
21d0ba7e
DA
268 check_unchanged
269 else
aa03f604 270 "$merge_tool_path" "$LOCAL" "$REMOTE"
21d0ba7e
DA
271 fi
272 ;;
273 opendiff)
240dc3e8
DA
274 if merge_mode
275 then
21d0ba7e 276 touch "$BACKUP"
240dc3e8
DA
277 if $base_present
278 then
21d0ba7e
DA
279 "$merge_tool_path" "$LOCAL" "$REMOTE" \
280 -ancestor "$BASE" \
281 -merge "$MERGED" | cat
282 else
283 "$merge_tool_path" "$LOCAL" "$REMOTE" \
284 -merge "$MERGED" | cat
285 fi
286 check_unchanged
287 else
288 "$merge_tool_path" "$LOCAL" "$REMOTE" | cat
289 fi
290 ;;
aa03f604 291 p4merge)
240dc3e8
DA
292 if merge_mode
293 then
0a0ec7bd
CJ
294 touch "$BACKUP"
295 $base_present || >"$BASE"
296 "$merge_tool_path" "$BASE" "$LOCAL" "$REMOTE" "$MERGED"
21d0ba7e
DA
297 check_unchanged
298 else
aa03f604 299 "$merge_tool_path" "$LOCAL" "$REMOTE"
21d0ba7e
DA
300 fi
301 ;;
aa03f604 302 tkdiff)
240dc3e8
DA
303 if merge_mode
304 then
305 if $base_present
306 then
aa03f604
SS
307 "$merge_tool_path" -a "$BASE" \
308 -o "$MERGED" "$LOCAL" "$REMOTE"
21d0ba7e
DA
309 else
310 "$merge_tool_path" \
aa03f604 311 -o "$MERGED" "$LOCAL" "$REMOTE"
21d0ba7e
DA
312 fi
313 status=$?
314 else
aa03f604 315 "$merge_tool_path" "$LOCAL" "$REMOTE"
21d0ba7e
DA
316 fi
317 ;;
318 tortoisemerge)
240dc3e8
DA
319 if $base_present
320 then
21d0ba7e
DA
321 touch "$BACKUP"
322 "$merge_tool_path" \
323 -base:"$BASE" -mine:"$LOCAL" \
324 -theirs:"$REMOTE" -merged:"$MERGED"
325 check_unchanged
326 else
327 echo "TortoiseMerge cannot be used without a base" 1>&2
328 status=1
329 fi
330 ;;
aa03f604 331 xxdiff)
240dc3e8
DA
332 if merge_mode
333 then
b6f0621a 334 touch "$BACKUP"
240dc3e8
DA
335 if $base_present
336 then
aa03f604
SS
337 "$merge_tool_path" -X --show-merged-pane \
338 -R 'Accel.SaveAsMerged: "Ctrl-S"' \
339 -R 'Accel.Search: "Ctrl+F"' \
340 -R 'Accel.SearchForward: "Ctrl-G"' \
341 --merged-file "$MERGED" \
342 "$LOCAL" "$BASE" "$REMOTE"
b6f0621a 343 else
aa03f604
SS
344 "$merge_tool_path" -X $extra \
345 -R 'Accel.SaveAsMerged: "Ctrl-S"' \
346 -R 'Accel.Search: "Ctrl+F"' \
347 -R 'Accel.SearchForward: "Ctrl-G"' \
348 --merged-file "$MERGED" \
349 "$LOCAL" "$REMOTE"
b6f0621a
DA
350 fi
351 check_unchanged
352 else
aa03f604
SS
353 "$merge_tool_path" \
354 -R 'Accel.Search: "Ctrl+F"' \
355 -R 'Accel.SearchForward: "Ctrl-G"' \
356 "$LOCAL" "$REMOTE"
b6f0621a
DA
357 fi
358 ;;
21d0ba7e 359 *)
47d65924 360 merge_tool_cmd="$(get_merge_tool_cmd "$1")"
240dc3e8
DA
361 if test -z "$merge_tool_cmd"
362 then
363 if merge_mode
364 then
21d0ba7e
DA
365 status=1
366 fi
367 break
368 fi
240dc3e8
DA
369 if merge_mode
370 then
47d65924
DA
371 trust_exit_code="$(git config --bool \
372 mergetool."$1".trustExitCode || echo false)"
240dc3e8
DA
373 if test "$trust_exit_code" = "false"
374 then
21d0ba7e
DA
375 touch "$BACKUP"
376 ( eval $merge_tool_cmd )
377 check_unchanged
378 else
379 ( eval $merge_tool_cmd )
380 status=$?
381 fi
382 else
383 ( eval $merge_tool_cmd )
384 fi
385 ;;
386 esac
387 return $status
388}
389
390guess_merge_tool () {
240dc3e8
DA
391 if merge_mode
392 then
21d0ba7e
DA
393 tools="tortoisemerge"
394 else
395 tools="kompare"
396 fi
240dc3e8
DA
397 if test -n "$DISPLAY"
398 then
399 if test -n "$GNOME_DESKTOP_SESSION_ID"
400 then
21d0ba7e
DA
401 tools="meld opendiff kdiff3 tkdiff xxdiff $tools"
402 else
403 tools="opendiff kdiff3 tkdiff xxdiff meld $tools"
404 fi
ffe6dc08 405 tools="$tools gvimdiff diffuse ecmerge p4merge araxis bc3"
21d0ba7e 406 fi
7b104229
RS
407 case "${VISUAL:-$EDITOR}" in
408 *vim*)
21d0ba7e 409 tools="$tools vimdiff emerge"
7b104229
RS
410 ;;
411 *)
21d0ba7e 412 tools="$tools emerge vimdiff"
7b104229
RS
413 ;;
414 esac
21d0ba7e
DA
415 echo >&2 "merge tool candidates: $tools"
416
417 # Loop over each candidate and stop when a valid merge tool is found.
418 for i in $tools
419 do
420 merge_tool_path="$(translate_merge_tool_path "$i")"
240dc3e8
DA
421 if type "$merge_tool_path" >/dev/null 2>&1
422 then
47d65924
DA
423 echo "$i"
424 return 0
21d0ba7e
DA
425 fi
426 done
427
47d65924
DA
428 echo >&2 "No known merge resolution program available."
429 return 1
21d0ba7e
DA
430}
431
432get_configured_merge_tool () {
433 # Diff mode first tries diff.tool and falls back to merge.tool.
434 # Merge mode only checks merge.tool
240dc3e8
DA
435 if diff_mode
436 then
47d65924
DA
437 merge_tool=$(git config diff.tool || git config merge.tool)
438 else
439 merge_tool=$(git config merge.tool)
21d0ba7e 440 fi
240dc3e8
DA
441 if test -n "$merge_tool" && ! valid_tool "$merge_tool"
442 then
21d0ba7e
DA
443 echo >&2 "git config option $TOOL_MODE.tool set to unknown tool: $merge_tool"
444 echo >&2 "Resetting to default..."
445 return 1
446 fi
47d65924 447 echo "$merge_tool"
21d0ba7e
DA
448}
449
450get_merge_tool_path () {
451 # A merge tool has been set, so verify that it's valid.
240dc3e8
DA
452 if test -n "$1"
453 then
47d65924
DA
454 merge_tool="$1"
455 else
456 merge_tool="$(get_merge_tool)"
457 fi
240dc3e8
DA
458 if ! valid_tool "$merge_tool"
459 then
21d0ba7e
DA
460 echo >&2 "Unknown merge tool $merge_tool"
461 exit 1
462 fi
240dc3e8
DA
463 if diff_mode
464 then
47d65924 465 merge_tool_path=$(git config difftool."$merge_tool".path ||
285c6cbf 466 git config mergetool."$merge_tool".path)
47d65924
DA
467 else
468 merge_tool_path=$(git config mergetool."$merge_tool".path)
21d0ba7e 469 fi
240dc3e8
DA
470 if test -z "$merge_tool_path"
471 then
47d65924 472 merge_tool_path="$(translate_merge_tool_path "$merge_tool")"
21d0ba7e 473 fi
47d65924 474 if test -z "$(get_merge_tool_cmd "$merge_tool")" &&
240dc3e8
DA
475 ! type "$merge_tool_path" >/dev/null 2>&1
476 then
47d65924 477 echo >&2 "The $TOOL_MODE tool $merge_tool is not available as"\
285c6cbf 478 "'$merge_tool_path'"
21d0ba7e
DA
479 exit 1
480 fi
481 echo "$merge_tool_path"
482}
483
484get_merge_tool () {
21d0ba7e 485 # Check if a merge tool has been configured
47d65924 486 merge_tool=$(get_configured_merge_tool)
21d0ba7e 487 # Try to guess an appropriate merge tool if no tool has been set.
240dc3e8
DA
488 if test -z "$merge_tool"
489 then
47d65924 490 merge_tool="$(guess_merge_tool)" || exit
21d0ba7e
DA
491 fi
492 echo "$merge_tool"
493}