mergetool--lib: simplify command expressions
[git/git.git] / git-mergetool--lib.sh
CommitLineData
02e51243 1#!/bin/sh
21d0ba7e 2# git-mergetool--lib is a library for common merge tool functions
073678b8
DA
3MERGE_TOOLS_DIR=$(git --exec-path)/mergetools
4
21d0ba7e
DA
5diff_mode() {
6 test "$TOOL_MODE" = diff
7}
8
9merge_mode() {
10 test "$TOOL_MODE" = merge
11}
12
13translate_merge_tool_path () {
bc7a96a8 14 echo "$1"
21d0ba7e
DA
15}
16
17check_unchanged () {
240dc3e8
DA
18 if test "$MERGED" -nt "$BACKUP"
19 then
21d0ba7e
DA
20 status=0
21 else
240dc3e8
DA
22 while true
23 do
21d0ba7e
DA
24 echo "$MERGED seems unchanged."
25 printf "Was the merge successful? [y/n] "
e622f41d 26 read answer || return 1
21d0ba7e
DA
27 case "$answer" in
28 y*|Y*) status=0; break ;;
29 n*|N*) status=1; break ;;
30 esac
31 done
32 fi
33}
34
35valid_tool () {
80ff2b68
DA
36 setup_tool "$1" && return 0
37 cmd=$(get_merge_tool_cmd "$1")
38 test -n "$cmd"
bc7a96a8
DA
39}
40
41setup_tool () {
073678b8
DA
42 tool="$1"
43
44 # Fallback definitions, to be overriden by tools.
45 can_merge () {
46 return 0
47 }
48
49 can_diff () {
50 return 0
51 }
52
53 diff_cmd () {
54 status=1
55 return $status
56 }
57
58 merge_cmd () {
59 status=1
60 return $status
61 }
bc7a96a8 62
073678b8
DA
63 translate_merge_tool_path () {
64 echo "$1"
65 }
66
67 if ! test -f "$MERGE_TOOLS_DIR/$tool"
bc7a96a8 68 then
62957bea
JK
69 # Use a special return code for this case since we want to
70 # source "defaults" even when an explicit tool path is
71 # configured since the user can use that to override the
72 # default path in the scriptlet.
73 return 2
bc7a96a8
DA
74 fi
75
76 # Load the redefined functions
073678b8 77 . "$MERGE_TOOLS_DIR/$tool"
bc7a96a8
DA
78
79 if merge_mode && ! can_merge
80 then
81 echo "error: '$tool' can not be used to resolve merges" >&2
62957bea 82 return 1
bc7a96a8
DA
83 elif diff_mode && ! can_diff
84 then
85 echo "error: '$tool' can only be used to resolve merges" >&2
62957bea 86 return 1
bc7a96a8
DA
87 fi
88 return 0
21d0ba7e
DA
89}
90
91get_merge_tool_cmd () {
bc7a96a8 92 merge_tool="$1"
240dc3e8
DA
93 if diff_mode
94 then
80ff2b68
DA
95 git config "difftool.$merge_tool.cmd" ||
96 git config "mergetool.$merge_tool.cmd"
47d65924 97 else
80ff2b68 98 git config "mergetool.$merge_tool.cmd"
47d65924 99 fi
21d0ba7e
DA
100}
101
bc7a96a8 102# Entry point for running tools
21d0ba7e 103run_merge_tool () {
f9ad901f
DA
104 # If GIT_PREFIX is empty then we cannot use it in tools
105 # that expect to be able to chdir() to its value.
106 GIT_PREFIX=${GIT_PREFIX:-.}
107 export GIT_PREFIX
108
80ff2b68 109 merge_tool_path=$(get_merge_tool_path "$1") || exit
21d0ba7e
DA
110 base_present="$2"
111 status=0
112
bc7a96a8
DA
113 # Bring tool-specific functions into scope
114 setup_tool "$1"
62957bea
JK
115 exitcode=$?
116 case $exitcode in
117 0)
118 :
119 ;;
120 2)
121 # The configured tool is not a built-in tool.
122 test -n "$merge_tool_path" || return 1
123 ;;
124 *)
125 return $exitcode
126 ;;
127 esac
bc7a96a8
DA
128
129 if merge_mode
130 then
a427ef7a 131 run_merge_cmd "$1"
bc7a96a8 132 else
a427ef7a 133 run_diff_cmd "$1"
bc7a96a8 134 fi
21d0ba7e
DA
135 return $status
136}
137
a427ef7a
DA
138# Run a either a configured or built-in diff tool
139run_diff_cmd () {
80ff2b68 140 merge_tool_cmd=$(get_merge_tool_cmd "$1")
a427ef7a
DA
141 if test -n "$merge_tool_cmd"
142 then
143 ( eval $merge_tool_cmd )
144 status=$?
145 return $status
146 else
147 diff_cmd "$1"
148 fi
149}
150
151# Run a either a configured or built-in merge tool
152run_merge_cmd () {
80ff2b68 153 merge_tool_cmd=$(get_merge_tool_cmd "$1")
a427ef7a
DA
154 if test -n "$merge_tool_cmd"
155 then
80ff2b68
DA
156 trust_exit_code=$(git config --bool \
157 "mergetool.$1.trustExitCode" || echo false)
a427ef7a
DA
158 if test "$trust_exit_code" = "false"
159 then
160 touch "$BACKUP"
161 ( eval $merge_tool_cmd )
162 status=$?
163 check_unchanged
164 else
165 ( eval $merge_tool_cmd )
166 status=$?
167 fi
168 return $status
169 else
170 merge_cmd "$1"
171 fi
172}
173
109859e2 174list_merge_tool_candidates () {
240dc3e8
DA
175 if merge_mode
176 then
21d0ba7e
DA
177 tools="tortoisemerge"
178 else
179 tools="kompare"
180 fi
240dc3e8
DA
181 if test -n "$DISPLAY"
182 then
183 if test -n "$GNOME_DESKTOP_SESSION_ID"
184 then
21d0ba7e
DA
185 tools="meld opendiff kdiff3 tkdiff xxdiff $tools"
186 else
187 tools="opendiff kdiff3 tkdiff xxdiff meld $tools"
188 fi
755e8b3f 189 tools="$tools gvimdiff diffuse ecmerge p4merge araxis bc3 codecompare"
21d0ba7e 190 fi
7b104229
RS
191 case "${VISUAL:-$EDITOR}" in
192 *vim*)
21d0ba7e 193 tools="$tools vimdiff emerge"
7b104229
RS
194 ;;
195 *)
21d0ba7e 196 tools="$tools emerge vimdiff"
7b104229
RS
197 ;;
198 esac
109859e2
JH
199}
200
4a8273a3 201show_tool_help () {
4a8273a3
JK
202 unavailable= available= LF='
203'
073678b8 204 for i in "$MERGE_TOOLS_DIR"/*
4a8273a3 205 do
073678b8
DA
206 tool=$(basename "$i")
207 setup_tool "$tool" 2>/dev/null || continue
88d3406a
DA
208
209 merge_tool_path=$(translate_merge_tool_path "$tool")
4a8273a3
JK
210 if type "$merge_tool_path" >/dev/null 2>&1
211 then
88d3406a 212 available="$available$tool$LF"
4a8273a3 213 else
88d3406a 214 unavailable="$unavailable$tool$LF"
4a8273a3
JK
215 fi
216 done
62b6f7e0
JK
217
218 cmd_name=${TOOL_MODE}tool
4a8273a3
JK
219 if test -n "$available"
220 then
62b6f7e0 221 echo "'git $cmd_name --tool=<tool>' may be set to one of the following:"
4a8273a3
JK
222 echo "$available" | sort | sed -e 's/^/ /'
223 else
62b6f7e0 224 echo "No suitable tool for 'git $cmd_name --tool=<tool>' found."
4a8273a3
JK
225 fi
226 if test -n "$unavailable"
227 then
228 echo
229 echo 'The following tools are valid, but not currently available:'
230 echo "$unavailable" | sort | sed -e 's/^/ /'
231 fi
232 if test -n "$unavailable$available"
233 then
234 echo
235 echo "Some of the tools listed above only work in a windowed"
236 echo "environment. If run in a terminal-only session, they will fail."
237 fi
238 exit 0
239}
240
109859e2
JH
241guess_merge_tool () {
242 list_merge_tool_candidates
21d0ba7e
DA
243 echo >&2 "merge tool candidates: $tools"
244
245 # Loop over each candidate and stop when a valid merge tool is found.
246 for i in $tools
247 do
80ff2b68 248 merge_tool_path=$(translate_merge_tool_path "$i")
240dc3e8
DA
249 if type "$merge_tool_path" >/dev/null 2>&1
250 then
47d65924
DA
251 echo "$i"
252 return 0
21d0ba7e
DA
253 fi
254 done
255
47d65924
DA
256 echo >&2 "No known merge resolution program available."
257 return 1
21d0ba7e
DA
258}
259
260get_configured_merge_tool () {
261 # Diff mode first tries diff.tool and falls back to merge.tool.
262 # Merge mode only checks merge.tool
240dc3e8
DA
263 if diff_mode
264 then
47d65924
DA
265 merge_tool=$(git config diff.tool || git config merge.tool)
266 else
267 merge_tool=$(git config merge.tool)
21d0ba7e 268 fi
240dc3e8
DA
269 if test -n "$merge_tool" && ! valid_tool "$merge_tool"
270 then
21d0ba7e
DA
271 echo >&2 "git config option $TOOL_MODE.tool set to unknown tool: $merge_tool"
272 echo >&2 "Resetting to default..."
273 return 1
274 fi
47d65924 275 echo "$merge_tool"
21d0ba7e
DA
276}
277
278get_merge_tool_path () {
279 # A merge tool has been set, so verify that it's valid.
bc7a96a8 280 merge_tool="$1"
240dc3e8
DA
281 if ! valid_tool "$merge_tool"
282 then
21d0ba7e
DA
283 echo >&2 "Unknown merge tool $merge_tool"
284 exit 1
285 fi
240dc3e8
DA
286 if diff_mode
287 then
47d65924 288 merge_tool_path=$(git config difftool."$merge_tool".path ||
285c6cbf 289 git config mergetool."$merge_tool".path)
47d65924
DA
290 else
291 merge_tool_path=$(git config mergetool."$merge_tool".path)
21d0ba7e 292 fi
240dc3e8
DA
293 if test -z "$merge_tool_path"
294 then
80ff2b68 295 merge_tool_path=$(translate_merge_tool_path "$merge_tool")
21d0ba7e 296 fi
47d65924 297 if test -z "$(get_merge_tool_cmd "$merge_tool")" &&
240dc3e8
DA
298 ! type "$merge_tool_path" >/dev/null 2>&1
299 then
47d65924 300 echo >&2 "The $TOOL_MODE tool $merge_tool is not available as"\
285c6cbf 301 "'$merge_tool_path'"
21d0ba7e
DA
302 exit 1
303 fi
304 echo "$merge_tool_path"
305}
306
307get_merge_tool () {
21d0ba7e 308 # Check if a merge tool has been configured
80ff2b68 309 merge_tool=$(get_configured_merge_tool)
21d0ba7e 310 # Try to guess an appropriate merge tool if no tool has been set.
240dc3e8
DA
311 if test -z "$merge_tool"
312 then
80ff2b68 313 merge_tool=$(guess_merge_tool) || exit
21d0ba7e
DA
314 fi
315 echo "$merge_tool"
316}