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