difftool: remove merge options for opendiff, tkdiff, kdiff3 and xxdiff
[git/git.git] / contrib / difftool / git-difftool-helper
CommitLineData
5c38ea31
DA
1#!/bin/sh
2# git-difftool-helper is a GIT_EXTERNAL_DIFF-compatible diff tool launcher.
384770a5
MH
3# It supports kdiff3, kompare, tkdiff, xxdiff, meld, opendiff,
4# emerge, ecmerge, vimdiff, gvimdiff, and custom user-configurable tools.
5c38ea31
DA
5# This script is typically launched by using the 'git difftool'
6# convenience command.
7#
8# Copyright (c) 2009 David Aguilar
9
10# Set GIT_DIFFTOOL_NO_PROMPT to bypass the per-file prompt.
11should_prompt () {
12 ! test -n "$GIT_DIFFTOOL_NO_PROMPT"
13}
14
15# Should we keep the backup .orig file?
16keep_backup_mode="$(git config --bool merge.keepBackup || echo true)"
17keep_backup () {
18 test "$keep_backup_mode" = "true"
19}
20
21# This function manages the backup .orig file.
22# A backup $MERGED.orig file is created if changes are detected.
23cleanup_temp_files () {
24 if test -n "$MERGED"; then
25 if keep_backup && test "$MERGED" -nt "$BACKUP"; then
26 test -f "$BACKUP" && mv -- "$BACKUP" "$MERGED.orig"
27 else
28 rm -f -- "$BACKUP"
29 fi
30 fi
31}
32
33# This is called when users Ctrl-C out of git-difftool-helper
34sigint_handler () {
5c38ea31
DA
35 cleanup_temp_files
36 exit 1
37}
38
39# This function prepares temporary files and launches the appropriate
40# merge tool.
41launch_merge_tool () {
42 # Merged is the filename as it appears in the work tree
43 # Local is the contents of a/filename
44 # Remote is the contents of b/filename
45 # Custom merge tool commands might use $BASE so we provide it
46 MERGED="$1"
47 LOCAL="$2"
48 REMOTE="$3"
49 BASE="$1"
50 ext="$$$(expr "$MERGED" : '.*\(\.[^/]*\)$')"
51 BACKUP="$MERGED.BACKUP.$ext"
52
53 # Create and ensure that we clean up $BACKUP
54 test -f "$MERGED" && cp -- "$MERGED" "$BACKUP"
f13bfc1b 55 trap sigint_handler INT
5c38ea31
DA
56
57 # $LOCAL and $REMOTE are temporary files so prompt
58 # the user with the real $MERGED name before launching $merge_tool.
59 if should_prompt; then
60 printf "\nViewing: '$MERGED'\n"
61 printf "Hit return to launch '%s': " "$merge_tool"
62 read ans
63 fi
64
65 # Run the appropriate merge tool command
66 case "$merge_tool" in
67 kdiff3)
68 basename=$(basename "$MERGED")
69 "$merge_tool_path" --auto \
70 --L1 "$basename (A)" \
71 --L2 "$basename (B)" \
76ca6538 72 "$LOCAL" "$REMOTE" \
5c38ea31
DA
73 > /dev/null 2>&1
74 ;;
75
384770a5
MH
76 kompare)
77 "$merge_tool_path" "$LOCAL" "$REMOTE"
78 ;;
79
5c38ea31 80 tkdiff)
76ca6538 81 "$merge_tool_path" "$LOCAL" "$REMOTE"
5c38ea31
DA
82 ;;
83
28da86a5 84 meld)
5c38ea31
DA
85 "$merge_tool_path" "$LOCAL" "$REMOTE"
86 ;;
87
28da86a5 88 vimdiff)
bad42732 89 "$merge_tool_path" -d -c "wincmd l" "$LOCAL" "$REMOTE"
28da86a5
DA
90 ;;
91
5c38ea31 92 gvimdiff)
bad42732 93 "$merge_tool_path" -d -c "wincmd l" -f "$LOCAL" "$REMOTE"
5c38ea31
DA
94 ;;
95
96 xxdiff)
97 "$merge_tool_path" \
5c38ea31
DA
98 -R 'Accel.Search: "Ctrl+F"' \
99 -R 'Accel.SearchForward: "Ctrl-G"' \
5c38ea31
DA
100 "$LOCAL" "$REMOTE"
101 ;;
102
103 opendiff)
76ca6538 104 "$merge_tool_path" "$LOCAL" "$REMOTE" | cat
5c38ea31
DA
105 ;;
106
107 ecmerge)
108 "$merge_tool_path" "$LOCAL" "$REMOTE" \
109 --default --mode=merge2 --to="$MERGED"
110 ;;
111
112 emerge)
113 "$merge_tool_path" -f emerge-files-command \
114 "$LOCAL" "$REMOTE" "$(basename "$MERGED")"
115 ;;
116
117 *)
118 if test -n "$merge_tool_cmd"; then
119 ( eval $merge_tool_cmd )
120 fi
121 ;;
122 esac
123
124 cleanup_temp_files
125}
126
2464456a 127# Verifies that (difftool|mergetool).<tool>.cmd exists
5c38ea31 128valid_custom_tool() {
2464456a
DA
129 merge_tool_cmd="$(git config difftool.$1.cmd)"
130 test -z "$merge_tool_cmd" &&
5c38ea31
DA
131 merge_tool_cmd="$(git config mergetool.$1.cmd)"
132 test -n "$merge_tool_cmd"
133}
134
135# Verifies that the chosen merge tool is properly setup.
136# Built-in merge tools are always valid.
137valid_tool() {
138 case "$1" in
384770a5 139 kdiff3 | kompare | tkdiff | xxdiff | meld | opendiff | emerge | vimdiff | gvimdiff | ecmerge)
5c38ea31
DA
140 ;; # happy
141 *)
142 if ! valid_custom_tool "$1"
143 then
144 return 1
145 fi
146 ;;
147 esac
148}
149
150# Sets up the merge_tool_path variable.
2464456a
DA
151# This handles the difftool.<tool>.path configuration.
152# This also falls back to mergetool defaults.
5c38ea31 153init_merge_tool_path() {
2464456a
DA
154 merge_tool_path=$(git config difftool."$1".path)
155 test -z "$merge_tool_path" &&
5c38ea31
DA
156 merge_tool_path=$(git config mergetool."$1".path)
157 if test -z "$merge_tool_path"; then
158 case "$1" in
bad42732
MH
159 vimdiff)
160 merge_tool_path=vim
161 ;;
162 gvimdiff)
163 merge_tool_path=gvim
164 ;;
5c38ea31
DA
165 emerge)
166 merge_tool_path=emacs
167 ;;
168 *)
169 merge_tool_path="$1"
170 ;;
171 esac
172 fi
173}
174
2464456a 175# Allow GIT_DIFF_TOOL and GIT_MERGE_TOOL to provide default values
5c38ea31 176test -n "$GIT_MERGE_TOOL" && merge_tool="$GIT_MERGE_TOOL"
2464456a 177test -n "$GIT_DIFF_TOOL" && merge_tool="$GIT_DIFF_TOOL"
5c38ea31 178
2464456a 179# If merge tool was not specified then use the diff.tool
5c38ea31 180# configuration variable. If that's invalid then reset merge_tool.
2464456a 181# Fallback to merge.tool.
5c38ea31 182if test -z "$merge_tool"; then
2464456a
DA
183 merge_tool=$(git config diff.tool)
184 test -z "$merge_tool" &&
5c38ea31
DA
185 merge_tool=$(git config merge.tool)
186 if test -n "$merge_tool" && ! valid_tool "$merge_tool"; then
2464456a 187 echo >&2 "git config option diff.tool set to unknown tool: $merge_tool"
5c38ea31
DA
188 echo >&2 "Resetting to default..."
189 unset merge_tool
190 fi
191fi
192
193# Try to guess an appropriate merge tool if no tool has been set.
194if test -z "$merge_tool"; then
5c38ea31
DA
195 # We have a $DISPLAY so try some common UNIX merge tools
196 if test -n "$DISPLAY"; then
99ccabaf
DA
197 # If gnome then prefer meld, otherwise, prefer kdiff3 or kompare
198 if test -n "$GNOME_DESKTOP_SESSION_ID" ; then
199 merge_tool_candidates="meld kdiff3 kompare tkdiff xxdiff gvimdiff"
200 else
201 merge_tool_candidates="kdiff3 kompare tkdiff xxdiff meld gvimdiff"
5c38ea31
DA
202 fi
203 fi
5c38ea31 204 if echo "${VISUAL:-$EDITOR}" | grep 'emacs' > /dev/null 2>&1; then
99ccabaf
DA
205 # $EDITOR is emacs so add emerge as a candidate
206 merge_tool_candidates="$merge_tool_candidates emerge opendiff vimdiff"
207 elif echo "${VISUAL:-$EDITOR}" | grep 'vim' > /dev/null 2>&1; then
208 # $EDITOR is vim so add vimdiff as a candidate
209 merge_tool_candidates="$merge_tool_candidates vimdiff opendiff emerge"
210 else
211 merge_tool_candidates="$merge_tool_candidates opendiff emerge vimdiff"
5c38ea31 212 fi
5c38ea31
DA
213 echo "merge tool candidates: $merge_tool_candidates"
214
215 # Loop over each candidate and stop when a valid merge tool is found.
216 for i in $merge_tool_candidates
217 do
218 init_merge_tool_path $i
219 if type "$merge_tool_path" > /dev/null 2>&1; then
220 merge_tool=$i
221 break
222 fi
223 done
224
225 if test -z "$merge_tool" ; then
226 echo "No known merge resolution program available."
227 exit 1
228 fi
229
230else
231 # A merge tool has been set, so verify that it's valid.
232 if ! valid_tool "$merge_tool"; then
233 echo >&2 "Unknown merge tool $merge_tool"
234 exit 1
235 fi
236
237 init_merge_tool_path "$merge_tool"
238
239 if test -z "$merge_tool_cmd" && ! type "$merge_tool_path" > /dev/null 2>&1; then
240 echo "The merge tool $merge_tool is not available as '$merge_tool_path'"
241 exit 1
242 fi
243fi
244
245
246# Launch the merge tool on each path provided by 'git diff'
247while test $# -gt 6
248do
249 launch_merge_tool "$1" "$2" "$5"
250 shift 7
251done