]>
Commit | Line | Data |
---|---|---|
02e51243 | 1 | #!/bin/sh |
21d0ba7e DA |
2 | # git-mergetool--lib is a library for common merge tool functions |
3 | diff_mode() { | |
4 | test "$TOOL_MODE" = diff | |
5 | } | |
6 | ||
7 | merge_mode() { | |
8 | test "$TOOL_MODE" = merge | |
9 | } | |
10 | ||
11 | translate_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 | ||
34 | check_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 | ||
52 | valid_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 | ||
78 | get_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 | ||
95 | run_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 | ||
390 | guess_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 | ||
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 | |
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 | ||
450 | get_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 | ||
484 | get_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 | } |