Code

mergetool: use $( ... ) instead of `backticks`
[git.git] / git-difftool--helper.sh
1 #!/bin/sh
2 # git-difftool--helper is a GIT_EXTERNAL_DIFF-compatible diff tool launcher.
3 # This script is typically launched by using the 'git difftool'
4 # convenience command.
5 #
6 # Copyright (c) 2009 David Aguilar
8 # difftool.prompt controls the default prompt/no-prompt behavior
9 # and is overridden with $GIT_DIFFTOOL*_PROMPT.
10 should_prompt () {
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
17 }
19 # This function prepares temporary files and launches the appropriate
20 # merge tool.
21 launch_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"
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
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)" \
46                         "$LOCAL" "$REMOTE" \
47                         > /dev/null 2>&1
48                 ;;
50         kompare)
51                 "$merge_tool_path" "$LOCAL" "$REMOTE"
52                 ;;
54         tkdiff)
55                 "$merge_tool_path" "$LOCAL" "$REMOTE"
56                 ;;
58         meld)
59                 "$merge_tool_path" "$LOCAL" "$REMOTE"
60                 ;;
62         diffuse)
63                 "$merge_tool_path" "$LOCAL" "$REMOTE" | cat
64                 ;;
66         vimdiff)
67                 "$merge_tool_path" -d -c "wincmd l" "$LOCAL" "$REMOTE"
68                 ;;
70         gvimdiff)
71                 "$merge_tool_path" -d -c "wincmd l" -f "$LOCAL" "$REMOTE"
72                 ;;
74         xxdiff)
75                 "$merge_tool_path" \
76                         -R 'Accel.Search: "Ctrl+F"' \
77                         -R 'Accel.SearchForward: "Ctrl-G"' \
78                         "$LOCAL" "$REMOTE"
79                 ;;
81         opendiff)
82                 "$merge_tool_path" "$LOCAL" "$REMOTE" | cat
83                 ;;
85         ecmerge)
86                 "$merge_tool_path" "$LOCAL" "$REMOTE" \
87                         --default --mode=merge2 --to="$MERGED"
88                 ;;
90         emerge)
91                 "$merge_tool_path" -f emerge-files-command \
92                         "$LOCAL" "$REMOTE" "$(basename "$MERGED")"
93                 ;;
95         *)
96                 if test -n "$merge_tool_cmd"; then
97                         ( eval $merge_tool_cmd )
98                 fi
99                 ;;
100         esac
103 # Verifies that (difftool|mergetool).<tool>.cmd exists
104 valid_custom_tool() {
105         merge_tool_cmd="$(git config difftool.$1.cmd)"
106         test -z "$merge_tool_cmd" &&
107         merge_tool_cmd="$(git config mergetool.$1.cmd)"
108         test -n "$merge_tool_cmd"
111 # Verifies that the chosen merge tool is properly setup.
112 # Built-in merge tools are always valid.
113 valid_tool() {
114         case "$1" in
115         kdiff3 | kompare | tkdiff | xxdiff | meld | opendiff | emerge | vimdiff | gvimdiff | ecmerge)
116                 ;; # happy
117         *)
118                 if ! valid_custom_tool "$1"
119                 then
120                         return 1
121                 fi
122                 ;;
123         esac
126 # Sets up the merge_tool_path variable.
127 # This handles the difftool.<tool>.path configuration.
128 # This also falls back to mergetool defaults.
129 init_merge_tool_path() {
130         merge_tool_path=$(git config difftool."$1".path)
131         test -z "$merge_tool_path" &&
132         merge_tool_path=$(git config mergetool."$1".path)
133         if test -z "$merge_tool_path"; then
134                 case "$1" in
135                 vimdiff)
136                         merge_tool_path=vim
137                         ;;
138                 gvimdiff)
139                         merge_tool_path=gvim
140                         ;;
141                 emerge)
142                         merge_tool_path=emacs
143                         ;;
144                 *)
145                         merge_tool_path="$1"
146                         ;;
147                 esac
148         fi
151 # Allow GIT_DIFF_TOOL and GIT_MERGE_TOOL to provide default values
152 test -n "$GIT_MERGE_TOOL" && merge_tool="$GIT_MERGE_TOOL"
153 test -n "$GIT_DIFF_TOOL" && merge_tool="$GIT_DIFF_TOOL"
155 # If merge tool was not specified then use the diff.tool
156 # configuration variable.  If that's invalid then reset merge_tool.
157 # Fallback to merge.tool.
158 if test -z "$merge_tool"; then
159         merge_tool=$(git config diff.tool)
160         test -z "$merge_tool" &&
161         merge_tool=$(git config merge.tool)
162         if test -n "$merge_tool" && ! valid_tool "$merge_tool"; then
163                 echo >&2 "git config option diff.tool set to unknown tool: $merge_tool"
164                 echo >&2 "Resetting to default..."
165                 unset merge_tool
166         fi
167 fi
169 # Try to guess an appropriate merge tool if no tool has been set.
170 if test -z "$merge_tool"; then
171         # We have a $DISPLAY so try some common UNIX merge tools
172         if test -n "$DISPLAY"; then
173                 # If gnome then prefer meld, otherwise, prefer kdiff3 or kompare
174                 if test -n "$GNOME_DESKTOP_SESSION_ID" ; then
175                         merge_tool_candidates="meld kdiff3 kompare tkdiff xxdiff gvimdiff diffuse"
176                 else
177                         merge_tool_candidates="kdiff3 kompare tkdiff xxdiff meld gvimdiff diffuse"
178                 fi
179         fi
180         if echo "${VISUAL:-$EDITOR}" | grep 'emacs' > /dev/null 2>&1; then
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"
188         fi
189         echo "merge tool candidates: $merge_tool_candidates"
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
201         if test -z "$merge_tool" ; then
202                 echo "No known merge resolution program available."
203                 exit 1
204         fi
206 else
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
213         init_merge_tool_path "$merge_tool"
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
219 fi
222 # Launch the merge tool on each path provided by 'git diff'
223 while test $# -gt 6
224 do
225         launch_merge_tool "$1" "$2" "$5"
226         shift 7
227 done