1 # git-mergetool--lib is a library for common merge tool functions
3 test "$TOOL_MODE" = diff
7 test "$TOOL_MODE" = merge
10 translate_merge_tool_path () {
31 if test "$MERGED" -nt "$BACKUP"; then
35 echo "$MERGED seems unchanged."
36 printf "Was the merge successful? [y/n] "
37 read answer < /dev/tty
39 y*|Y*) status=0; break ;;
40 n*|N*) status=1; break ;;
48 kdiff3 | tkdiff | xxdiff | meld | opendiff | \
49 emerge | vimdiff | gvimdiff | ecmerge | diffuse | araxis)
62 if test -z "$(get_merge_tool_cmd "$1")"; then
69 get_merge_tool_cmd () {
70 # Prints the custom command for a merge tool
74 merge_tool="$(get_merge_tool)"
77 echo "$(git config difftool.$merge_tool.cmd ||
78 git config mergetool.$merge_tool.cmd)"
80 echo "$(git config mergetool.$merge_tool.cmd)"
85 merge_tool_path="$(get_merge_tool_path "$1")" || exit
92 if $base_present; then
93 ("$merge_tool_path" --auto \
94 --L1 "$MERGED (Base)" \
95 --L2 "$MERGED (Local)" \
96 --L3 "$MERGED (Remote)" \
98 "$BASE" "$LOCAL" "$REMOTE" \
101 ("$merge_tool_path" --auto \
102 --L1 "$MERGED (Local)" \
103 --L2 "$MERGED (Remote)" \
110 ("$merge_tool_path" --auto \
112 --L2 "$MERGED (B)" "$LOCAL" "$REMOTE" \
117 "$merge_tool_path" "$LOCAL" "$REMOTE"
121 if $base_present; then
122 "$merge_tool_path" -a "$BASE" \
123 -o "$MERGED" "$LOCAL" "$REMOTE"
126 -o "$MERGED" "$LOCAL" "$REMOTE"
130 "$merge_tool_path" "$LOCAL" "$REMOTE"
136 "$merge_tool_path" "$LOCAL" "$MERGED" "$REMOTE"
139 "$merge_tool_path" "$LOCAL" "$REMOTE"
145 if $base_present; then
147 "$LOCAL" "$MERGED" "$REMOTE" \
151 "$LOCAL" "$MERGED" "$REMOTE" | cat
155 "$merge_tool_path" "$LOCAL" "$REMOTE" | cat
161 "$merge_tool_path" -d -c "wincmd l" \
162 "$LOCAL" "$MERGED" "$REMOTE"
165 "$merge_tool_path" -d -c "wincmd l" \
172 "$merge_tool_path" -d -c "wincmd l" -f \
173 "$LOCAL" "$MERGED" "$REMOTE"
176 "$merge_tool_path" -d -c "wincmd l" -f \
183 if $base_present; then
184 "$merge_tool_path" -X --show-merged-pane \
185 -R 'Accel.SaveAsMerged: "Ctrl-S"' \
186 -R 'Accel.Search: "Ctrl+F"' \
187 -R 'Accel.SearchForward: "Ctrl-G"' \
188 --merged-file "$MERGED" \
189 "$LOCAL" "$BASE" "$REMOTE"
191 "$merge_tool_path" -X $extra \
192 -R 'Accel.SaveAsMerged: "Ctrl-S"' \
193 -R 'Accel.Search: "Ctrl+F"' \
194 -R 'Accel.SearchForward: "Ctrl-G"' \
195 --merged-file "$MERGED" \
201 -R 'Accel.Search: "Ctrl+F"' \
202 -R 'Accel.SearchForward: "Ctrl-G"' \
209 if $base_present; then
210 "$merge_tool_path" "$LOCAL" "$REMOTE" \
212 -merge "$MERGED" | cat
214 "$merge_tool_path" "$LOCAL" "$REMOTE" \
215 -merge "$MERGED" | cat
219 "$merge_tool_path" "$LOCAL" "$REMOTE" | cat
225 if $base_present; then
226 "$merge_tool_path" "$BASE" "$LOCAL" "$REMOTE" \
227 --default --mode=merge3 --to="$MERGED"
229 "$merge_tool_path" "$LOCAL" "$REMOTE" \
230 --default --mode=merge2 --to="$MERGED"
234 "$merge_tool_path" --default --mode=diff2 \
240 if $base_present; then
242 -f emerge-files-with-ancestor-command \
243 "$LOCAL" "$REMOTE" "$BASE" \
244 "$(basename "$MERGED")"
247 -f emerge-files-command \
249 "$(basename "$MERGED")"
253 "$merge_tool_path" -f emerge-files-command \
258 if $base_present; then
261 -base:"$BASE" -mine:"$LOCAL" \
262 -theirs:"$REMOTE" -merged:"$MERGED"
265 echo "TortoiseMerge cannot be used without a base" 1>&2
272 if $base_present; then
273 "$merge_tool_path" -wait -merge -3 -a1 \
274 "$BASE" "$LOCAL" "$REMOTE" "$MERGED" \
277 "$merge_tool_path" -wait -2 \
278 "$LOCAL" "$REMOTE" "$MERGED" \
283 "$merge_tool_path" -wait -2 "$LOCAL" "$REMOTE" \
288 merge_tool_cmd="$(get_merge_tool_cmd "$1")"
289 if test -z "$merge_tool_cmd"; then
296 trust_exit_code="$(git config --bool \
297 mergetool."$1".trustExitCode || echo false)"
298 if test "$trust_exit_code" = "false"; then
300 ( eval $merge_tool_cmd )
303 ( eval $merge_tool_cmd )
307 ( eval $merge_tool_cmd )
314 guess_merge_tool () {
316 tools="tortoisemerge"
320 if test -n "$DISPLAY"; then
321 if test -n "$GNOME_DESKTOP_SESSION_ID" ; then
322 tools="meld opendiff kdiff3 tkdiff xxdiff $tools"
324 tools="opendiff kdiff3 tkdiff xxdiff meld $tools"
326 tools="$tools gvimdiff diffuse ecmerge araxis"
328 if echo "${VISUAL:-$EDITOR}" | grep emacs > /dev/null 2>&1; then
329 # $EDITOR is emacs so add emerge as a candidate
330 tools="$tools emerge vimdiff"
331 elif echo "${VISUAL:-$EDITOR}" | grep vim > /dev/null 2>&1; then
332 # $EDITOR is vim so add vimdiff as a candidate
333 tools="$tools vimdiff emerge"
335 tools="$tools emerge vimdiff"
337 echo >&2 "merge tool candidates: $tools"
339 # Loop over each candidate and stop when a valid merge tool is found.
342 merge_tool_path="$(translate_merge_tool_path "$i")"
343 if type "$merge_tool_path" > /dev/null 2>&1; then
349 echo >&2 "No known merge resolution program available."
353 get_configured_merge_tool () {
354 # Diff mode first tries diff.tool and falls back to merge.tool.
355 # Merge mode only checks merge.tool
357 merge_tool=$(git config diff.tool || git config merge.tool)
359 merge_tool=$(git config merge.tool)
361 if test -n "$merge_tool" && ! valid_tool "$merge_tool"; then
362 echo >&2 "git config option $TOOL_MODE.tool set to unknown tool: $merge_tool"
363 echo >&2 "Resetting to default..."
369 get_merge_tool_path () {
370 # A merge tool has been set, so verify that it's valid.
371 if test -n "$1"; then
374 merge_tool="$(get_merge_tool)"
376 if ! valid_tool "$merge_tool"; then
377 echo >&2 "Unknown merge tool $merge_tool"
381 merge_tool_path=$(git config difftool."$merge_tool".path ||
382 git config mergetool."$merge_tool".path)
384 merge_tool_path=$(git config mergetool."$merge_tool".path)
386 if test -z "$merge_tool_path"; then
387 merge_tool_path="$(translate_merge_tool_path "$merge_tool")"
389 if test -z "$(get_merge_tool_cmd "$merge_tool")" &&
390 ! type "$merge_tool_path" > /dev/null 2>&1; then
391 echo >&2 "The $TOOL_MODE tool $merge_tool is not available as"\
395 echo "$merge_tool_path"
399 # Check if a merge tool has been configured
400 merge_tool=$(get_configured_merge_tool)
401 # Try to guess an appropriate merge tool if no tool has been set.
402 if test -z "$merge_tool"; then
403 merge_tool="$(guess_merge_tool)" || exit