]>
Commit | Line | Data |
---|---|---|
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 | 10 | should_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. | |
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" | |
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 | 104 | valid_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. | |
113 | valid_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 | 129 | init_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 | 152 | test -n "$GIT_MERGE_TOOL" && merge_tool="$GIT_MERGE_TOOL" |
2464456a | 153 | test -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 | 158 | if 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 | |
167 | fi | |
168 | ||
169 | # Try to guess an appropriate merge tool if no tool has been set. | |
170 | if 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 | ||
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 | |
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 | |
219 | fi | |
220 | ||
221 | ||
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 |