mergetool--lib: Make style consistent with git
[alt-git.git] / git-mergetool--lib.sh
blob5820a6354a706324c755f31df71f328122f7a45b
1 #!/bin/sh
2 # git-mergetool--lib is a library for common merge tool functions
3 diff_mode() {
4 test "$TOOL_MODE" = diff
7 merge_mode() {
8 test "$TOOL_MODE" = merge
11 translate_merge_tool_path () {
12 case "$1" in
13 araxis)
14 echo compare
16 bc3)
17 echo bcompare
19 emerge)
20 echo emacs
22 gvimdiff|gvimdiff2)
23 echo gvim
25 vimdiff|vimdiff2)
26 echo vim
29 echo "$1"
31 esac
34 check_unchanged () {
35 if test "$MERGED" -nt "$BACKUP"
36 then
37 status=0
38 else
39 while true
41 echo "$MERGED seems unchanged."
42 printf "Was the merge successful? [y/n] "
43 read answer
44 case "$answer" in
45 y*|Y*) status=0; break ;;
46 n*|N*) status=1; break ;;
47 esac
48 done
52 valid_tool () {
53 case "$1" in
54 araxis | bc3 | diffuse | ecmerge | emerge | gvimdiff | gvimdiff2 | \
55 kdiff3 | meld | opendiff | p4merge | tkdiff | vimdiff | vimdiff2 | xxdiff)
56 ;; # happy
57 kompare)
58 if ! diff_mode
59 then
60 return 1
63 tortoisemerge)
64 if ! merge_mode
65 then
66 return 1
70 if test -z "$(get_merge_tool_cmd "$1")"
71 then
72 return 1
75 esac
78 get_merge_tool_cmd () {
79 # Prints the custom command for a merge tool
80 if test -n "$1"
81 then
82 merge_tool="$1"
83 else
84 merge_tool="$(get_merge_tool)"
86 if diff_mode
87 then
88 echo "$(git config difftool.$merge_tool.cmd ||
89 git config mergetool.$merge_tool.cmd)"
90 else
91 echo "$(git config mergetool.$merge_tool.cmd)"
95 run_merge_tool () {
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
101 merge_tool_path="$(get_merge_tool_path "$1")" || exit
102 base_present="$2"
103 status=0
105 case "$1" in
106 araxis)
107 if merge_mode
108 then
109 touch "$BACKUP"
110 if $base_present
111 then
112 "$merge_tool_path" -wait -merge -3 -a1 \
113 "$BASE" "$LOCAL" "$REMOTE" "$MERGED" \
114 >/dev/null 2>&1
115 else
116 "$merge_tool_path" -wait -2 \
117 "$LOCAL" "$REMOTE" "$MERGED" \
118 >/dev/null 2>&1
120 check_unchanged
121 else
122 "$merge_tool_path" -wait -2 "$LOCAL" "$REMOTE" \
123 >/dev/null 2>&1
126 bc3)
127 if merge_mode
128 then
129 touch "$BACKUP"
130 if $base_present
131 then
132 "$merge_tool_path" "$LOCAL" "$REMOTE" "$BASE" \
133 -mergeoutput="$MERGED"
134 else
135 "$merge_tool_path" "$LOCAL" "$REMOTE" \
136 -mergeoutput="$MERGED"
138 check_unchanged
139 else
140 "$merge_tool_path" "$LOCAL" "$REMOTE"
143 diffuse)
144 if merge_mode
145 then
146 touch "$BACKUP"
147 if $base_present
148 then
149 "$merge_tool_path" \
150 "$LOCAL" "$MERGED" "$REMOTE" \
151 "$BASE" | cat
152 else
153 "$merge_tool_path" \
154 "$LOCAL" "$MERGED" "$REMOTE" | cat
156 check_unchanged
157 else
158 "$merge_tool_path" "$LOCAL" "$REMOTE" | cat
161 ecmerge)
162 if merge_mode
163 then
164 touch "$BACKUP"
165 if $base_present
166 then
167 "$merge_tool_path" "$BASE" "$LOCAL" "$REMOTE" \
168 --default --mode=merge3 --to="$MERGED"
169 else
170 "$merge_tool_path" "$LOCAL" "$REMOTE" \
171 --default --mode=merge2 --to="$MERGED"
173 check_unchanged
174 else
175 "$merge_tool_path" --default --mode=diff2 \
176 "$LOCAL" "$REMOTE"
179 emerge)
180 if merge_mode
181 then
182 if $base_present
183 then
184 "$merge_tool_path" \
185 -f emerge-files-with-ancestor-command \
186 "$LOCAL" "$REMOTE" "$BASE" \
187 "$(basename "$MERGED")"
188 else
189 "$merge_tool_path" \
190 -f emerge-files-command \
191 "$LOCAL" "$REMOTE" \
192 "$(basename "$MERGED")"
194 status=$?
195 else
196 "$merge_tool_path" -f emerge-files-command \
197 "$LOCAL" "$REMOTE"
200 gvimdiff|vimdiff)
201 if merge_mode
202 then
203 touch "$BACKUP"
204 if $base_present
205 then
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"
212 check_unchanged
213 else
214 "$merge_tool_path" -R -f -d -c "wincmd l" \
215 -c 'cd $GIT_PREFIX' \
216 "$LOCAL" "$REMOTE"
219 gvimdiff2|vimdiff2)
220 if merge_mode
221 then
222 touch "$BACKUP"
223 "$merge_tool_path" -f -d -c "wincmd l" \
224 "$LOCAL" "$MERGED" "$REMOTE"
225 check_unchanged
226 else
227 "$merge_tool_path" -R -f -d -c "wincmd l" \
228 -c 'cd $GIT_PREFIX' \
229 "$LOCAL" "$REMOTE"
232 kdiff3)
233 if merge_mode
234 then
235 if $base_present
236 then
237 "$merge_tool_path" --auto \
238 --L1 "$MERGED (Base)" \
239 --L2 "$MERGED (Local)" \
240 --L3 "$MERGED (Remote)" \
241 -o "$MERGED" \
242 "$BASE" "$LOCAL" "$REMOTE" \
243 >/dev/null 2>&1
244 else
245 "$merge_tool_path" --auto \
246 --L1 "$MERGED (Local)" \
247 --L2 "$MERGED (Remote)" \
248 -o "$MERGED" \
249 "$LOCAL" "$REMOTE" \
250 >/dev/null 2>&1
252 status=$?
253 else
254 "$merge_tool_path" --auto \
255 --L1 "$MERGED (A)" \
256 --L2 "$MERGED (B)" "$LOCAL" "$REMOTE" \
257 >/dev/null 2>&1
260 kompare)
261 "$merge_tool_path" "$LOCAL" "$REMOTE"
263 meld)
264 if merge_mode
265 then
266 touch "$BACKUP"
267 "$merge_tool_path" "$LOCAL" "$MERGED" "$REMOTE"
268 check_unchanged
269 else
270 "$merge_tool_path" "$LOCAL" "$REMOTE"
273 opendiff)
274 if merge_mode
275 then
276 touch "$BACKUP"
277 if $base_present
278 then
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
286 check_unchanged
287 else
288 "$merge_tool_path" "$LOCAL" "$REMOTE" | cat
291 p4merge)
292 if merge_mode
293 then
294 touch "$BACKUP"
295 $base_present || >"$BASE"
296 "$merge_tool_path" "$BASE" "$LOCAL" "$REMOTE" "$MERGED"
297 check_unchanged
298 else
299 "$merge_tool_path" "$LOCAL" "$REMOTE"
302 tkdiff)
303 if merge_mode
304 then
305 if $base_present
306 then
307 "$merge_tool_path" -a "$BASE" \
308 -o "$MERGED" "$LOCAL" "$REMOTE"
309 else
310 "$merge_tool_path" \
311 -o "$MERGED" "$LOCAL" "$REMOTE"
313 status=$?
314 else
315 "$merge_tool_path" "$LOCAL" "$REMOTE"
318 tortoisemerge)
319 if $base_present
320 then
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
331 xxdiff)
332 if merge_mode
333 then
334 touch "$BACKUP"
335 if $base_present
336 then
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"
343 else
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"
351 check_unchanged
352 else
353 "$merge_tool_path" \
354 -R 'Accel.Search: "Ctrl+F"' \
355 -R 'Accel.SearchForward: "Ctrl-G"' \
356 "$LOCAL" "$REMOTE"
360 merge_tool_cmd="$(get_merge_tool_cmd "$1")"
361 if test -z "$merge_tool_cmd"
362 then
363 if merge_mode
364 then
365 status=1
367 break
369 if merge_mode
370 then
371 trust_exit_code="$(git config --bool \
372 mergetool."$1".trustExitCode || echo false)"
373 if test "$trust_exit_code" = "false"
374 then
375 touch "$BACKUP"
376 ( eval $merge_tool_cmd )
377 check_unchanged
378 else
379 ( eval $merge_tool_cmd )
380 status=$?
382 else
383 ( eval $merge_tool_cmd )
386 esac
387 return $status
390 guess_merge_tool () {
391 if merge_mode
392 then
393 tools="tortoisemerge"
394 else
395 tools="kompare"
397 if test -n "$DISPLAY"
398 then
399 if test -n "$GNOME_DESKTOP_SESSION_ID"
400 then
401 tools="meld opendiff kdiff3 tkdiff xxdiff $tools"
402 else
403 tools="opendiff kdiff3 tkdiff xxdiff meld $tools"
405 tools="$tools gvimdiff diffuse ecmerge p4merge araxis bc3"
407 case "${VISUAL:-$EDITOR}" in
408 *vim*)
409 tools="$tools vimdiff emerge"
412 tools="$tools emerge vimdiff"
414 esac
415 echo >&2 "merge tool candidates: $tools"
417 # Loop over each candidate and stop when a valid merge tool is found.
418 for i in $tools
420 merge_tool_path="$(translate_merge_tool_path "$i")"
421 if type "$merge_tool_path" >/dev/null 2>&1
422 then
423 echo "$i"
424 return 0
426 done
428 echo >&2 "No known merge resolution program available."
429 return 1
432 get_configured_merge_tool () {
433 # Diff mode first tries diff.tool and falls back to merge.tool.
434 # Merge mode only checks merge.tool
435 if diff_mode
436 then
437 merge_tool=$(git config diff.tool || git config merge.tool)
438 else
439 merge_tool=$(git config merge.tool)
441 if test -n "$merge_tool" && ! valid_tool "$merge_tool"
442 then
443 echo >&2 "git config option $TOOL_MODE.tool set to unknown tool: $merge_tool"
444 echo >&2 "Resetting to default..."
445 return 1
447 echo "$merge_tool"
450 get_merge_tool_path () {
451 # A merge tool has been set, so verify that it's valid.
452 if test -n "$1"
453 then
454 merge_tool="$1"
455 else
456 merge_tool="$(get_merge_tool)"
458 if ! valid_tool "$merge_tool"
459 then
460 echo >&2 "Unknown merge tool $merge_tool"
461 exit 1
463 if diff_mode
464 then
465 merge_tool_path=$(git config difftool."$merge_tool".path ||
466 git config mergetool."$merge_tool".path)
467 else
468 merge_tool_path=$(git config mergetool."$merge_tool".path)
470 if test -z "$merge_tool_path"
471 then
472 merge_tool_path="$(translate_merge_tool_path "$merge_tool")"
474 if test -z "$(get_merge_tool_cmd "$merge_tool")" &&
475 ! type "$merge_tool_path" >/dev/null 2>&1
476 then
477 echo >&2 "The $TOOL_MODE tool $merge_tool is not available as"\
478 "'$merge_tool_path'"
479 exit 1
481 echo "$merge_tool_path"
484 get_merge_tool () {
485 # Check if a merge tool has been configured
486 merge_tool=$(get_configured_merge_tool)
487 # Try to guess an appropriate merge tool if no tool has been set.
488 if test -z "$merge_tool"
489 then
490 merge_tool="$(guess_merge_tool)" || exit
492 echo "$merge_tool"