mergetool--lib: simplify command expressions
[alt-git.git] / git-mergetool--lib.sh
blob2a67383081cae8e33702fdb70db51fb1d1db87ba
1 #!/bin/sh
2 # git-mergetool--lib is a library for common merge tool functions
3 MERGE_TOOLS_DIR=$(git --exec-path)/mergetools
5 diff_mode() {
6 test "$TOOL_MODE" = diff
9 merge_mode() {
10 test "$TOOL_MODE" = merge
13 translate_merge_tool_path () {
14 echo "$1"
17 check_unchanged () {
18 if test "$MERGED" -nt "$BACKUP"
19 then
20 status=0
21 else
22 while true
24 echo "$MERGED seems unchanged."
25 printf "Was the merge successful? [y/n] "
26 read answer || return 1
27 case "$answer" in
28 y*|Y*) status=0; break ;;
29 n*|N*) status=1; break ;;
30 esac
31 done
35 valid_tool () {
36 setup_tool "$1" && return 0
37 cmd=$(get_merge_tool_cmd "$1")
38 test -n "$cmd"
41 setup_tool () {
42 tool="$1"
44 # Fallback definitions, to be overriden by tools.
45 can_merge () {
46 return 0
49 can_diff () {
50 return 0
53 diff_cmd () {
54 status=1
55 return $status
58 merge_cmd () {
59 status=1
60 return $status
63 translate_merge_tool_path () {
64 echo "$1"
67 if ! test -f "$MERGE_TOOLS_DIR/$tool"
68 then
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
76 # Load the redefined functions
77 . "$MERGE_TOOLS_DIR/$tool"
79 if merge_mode && ! can_merge
80 then
81 echo "error: '$tool' can not be used to resolve merges" >&2
82 return 1
83 elif diff_mode && ! can_diff
84 then
85 echo "error: '$tool' can only be used to resolve merges" >&2
86 return 1
88 return 0
91 get_merge_tool_cmd () {
92 merge_tool="$1"
93 if diff_mode
94 then
95 git config "difftool.$merge_tool.cmd" ||
96 git config "mergetool.$merge_tool.cmd"
97 else
98 git config "mergetool.$merge_tool.cmd"
102 # Entry point for running tools
103 run_merge_tool () {
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
109 merge_tool_path=$(get_merge_tool_path "$1") || exit
110 base_present="$2"
111 status=0
113 # Bring tool-specific functions into scope
114 setup_tool "$1"
115 exitcode=$?
116 case $exitcode in
121 # The configured tool is not a built-in tool.
122 test -n "$merge_tool_path" || return 1
125 return $exitcode
127 esac
129 if merge_mode
130 then
131 run_merge_cmd "$1"
132 else
133 run_diff_cmd "$1"
135 return $status
138 # Run a either a configured or built-in diff tool
139 run_diff_cmd () {
140 merge_tool_cmd=$(get_merge_tool_cmd "$1")
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"
151 # Run a either a configured or built-in merge tool
152 run_merge_cmd () {
153 merge_tool_cmd=$(get_merge_tool_cmd "$1")
154 if test -n "$merge_tool_cmd"
155 then
156 trust_exit_code=$(git config --bool \
157 "mergetool.$1.trustExitCode" || echo false)
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=$?
168 return $status
169 else
170 merge_cmd "$1"
174 list_merge_tool_candidates () {
175 if merge_mode
176 then
177 tools="tortoisemerge"
178 else
179 tools="kompare"
181 if test -n "$DISPLAY"
182 then
183 if test -n "$GNOME_DESKTOP_SESSION_ID"
184 then
185 tools="meld opendiff kdiff3 tkdiff xxdiff $tools"
186 else
187 tools="opendiff kdiff3 tkdiff xxdiff meld $tools"
189 tools="$tools gvimdiff diffuse ecmerge p4merge araxis bc3 codecompare"
191 case "${VISUAL:-$EDITOR}" in
192 *vim*)
193 tools="$tools vimdiff emerge"
196 tools="$tools emerge vimdiff"
198 esac
201 show_tool_help () {
202 unavailable= available= LF='
204 for i in "$MERGE_TOOLS_DIR"/*
206 tool=$(basename "$i")
207 setup_tool "$tool" 2>/dev/null || continue
209 merge_tool_path=$(translate_merge_tool_path "$tool")
210 if type "$merge_tool_path" >/dev/null 2>&1
211 then
212 available="$available$tool$LF"
213 else
214 unavailable="$unavailable$tool$LF"
216 done
218 cmd_name=${TOOL_MODE}tool
219 if test -n "$available"
220 then
221 echo "'git $cmd_name --tool=<tool>' may be set to one of the following:"
222 echo "$available" | sort | sed -e 's/^/ /'
223 else
224 echo "No suitable tool for 'git $cmd_name --tool=<tool>' found."
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/^/ /'
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."
238 exit 0
241 guess_merge_tool () {
242 list_merge_tool_candidates
243 echo >&2 "merge tool candidates: $tools"
245 # Loop over each candidate and stop when a valid merge tool is found.
246 for i in $tools
248 merge_tool_path=$(translate_merge_tool_path "$i")
249 if type "$merge_tool_path" >/dev/null 2>&1
250 then
251 echo "$i"
252 return 0
254 done
256 echo >&2 "No known merge resolution program available."
257 return 1
260 get_configured_merge_tool () {
261 # Diff mode first tries diff.tool and falls back to merge.tool.
262 # Merge mode only checks merge.tool
263 if diff_mode
264 then
265 merge_tool=$(git config diff.tool || git config merge.tool)
266 else
267 merge_tool=$(git config merge.tool)
269 if test -n "$merge_tool" && ! valid_tool "$merge_tool"
270 then
271 echo >&2 "git config option $TOOL_MODE.tool set to unknown tool: $merge_tool"
272 echo >&2 "Resetting to default..."
273 return 1
275 echo "$merge_tool"
278 get_merge_tool_path () {
279 # A merge tool has been set, so verify that it's valid.
280 merge_tool="$1"
281 if ! valid_tool "$merge_tool"
282 then
283 echo >&2 "Unknown merge tool $merge_tool"
284 exit 1
286 if diff_mode
287 then
288 merge_tool_path=$(git config difftool."$merge_tool".path ||
289 git config mergetool."$merge_tool".path)
290 else
291 merge_tool_path=$(git config mergetool."$merge_tool".path)
293 if test -z "$merge_tool_path"
294 then
295 merge_tool_path=$(translate_merge_tool_path "$merge_tool")
297 if test -z "$(get_merge_tool_cmd "$merge_tool")" &&
298 ! type "$merge_tool_path" >/dev/null 2>&1
299 then
300 echo >&2 "The $TOOL_MODE tool $merge_tool is not available as"\
301 "'$merge_tool_path'"
302 exit 1
304 echo "$merge_tool_path"
307 get_merge_tool () {
308 # Check if a merge tool has been configured
309 merge_tool=$(get_configured_merge_tool)
310 # Try to guess an appropriate merge tool if no tool has been set.
311 if test -z "$merge_tool"
312 then
313 merge_tool=$(guess_merge_tool) || exit
315 echo "$merge_tool"