]>
Commit | Line | Data |
---|---|---|
21d0ba7e DA |
1 | # git-mergetool--lib is a library for common merge tool functions |
2 | diff_mode() { | |
3 | test "$TOOL_MODE" = diff | |
4 | } | |
5 | ||
6 | merge_mode() { | |
7 | test "$TOOL_MODE" = merge | |
8 | } | |
9 | ||
10 | translate_merge_tool_path () { | |
11 | if test -n "$2"; then | |
12 | echo "$2" | |
13 | else | |
14 | case "$1" in | |
15 | vimdiff) | |
16 | path=vim | |
17 | ;; | |
18 | gvimdiff) | |
19 | path=gvim | |
20 | ;; | |
21 | emerge) | |
22 | path=emacs | |
23 | ;; | |
24 | *) | |
25 | path="$1" | |
26 | ;; | |
27 | esac | |
28 | echo "$path" | |
29 | fi | |
30 | } | |
31 | ||
32 | check_unchanged () { | |
33 | if test "$MERGED" -nt "$BACKUP"; then | |
34 | status=0 | |
35 | else | |
36 | while true; do | |
37 | echo "$MERGED seems unchanged." | |
38 | printf "Was the merge successful? [y/n] " | |
39 | read answer < /dev/tty | |
40 | case "$answer" in | |
41 | y*|Y*) status=0; break ;; | |
42 | n*|N*) status=1; break ;; | |
43 | esac | |
44 | done | |
45 | fi | |
46 | } | |
47 | ||
48 | valid_tool () { | |
49 | case "$1" in | |
50 | kdiff3 | tkdiff | xxdiff | meld | opendiff | \ | |
51 | emerge | vimdiff | gvimdiff | ecmerge | diffuse) | |
52 | ;; # happy | |
53 | tortoisemerge) | |
54 | if ! merge_mode; then | |
55 | return 1 | |
56 | fi | |
57 | ;; | |
58 | kompare) | |
59 | if ! diff_mode; then | |
60 | return 1 | |
61 | fi | |
62 | ;; | |
63 | *) | |
64 | if test -z "$(get_merge_tool_cmd "$1")"; then | |
65 | return 1 | |
66 | fi | |
67 | ;; | |
68 | esac | |
69 | } | |
70 | ||
71 | get_merge_tool_cmd () { | |
72 | diff_mode && | |
73 | custom_cmd="$(git config difftool.$1.cmd)" | |
74 | test -z "$custom_cmd" && | |
75 | custom_cmd="$(git config mergetool.$1.cmd)" | |
76 | test -n "$custom_cmd" && | |
77 | echo "$custom_cmd" | |
78 | } | |
79 | ||
80 | run_merge_tool () { | |
81 | base_present="$2" | |
82 | status=0 | |
83 | ||
84 | case "$1" in | |
85 | kdiff3) | |
86 | if merge_mode; then | |
87 | if $base_present; then | |
88 | ("$merge_tool_path" --auto \ | |
89 | --L1 "$MERGED (Base)" \ | |
90 | --L2 "$MERGED (Local)" \ | |
91 | --L3 "$MERGED (Remote)" \ | |
92 | -o "$MERGED" \ | |
93 | "$BASE" "$LOCAL" "$REMOTE" \ | |
94 | > /dev/null 2>&1) | |
95 | else | |
96 | ("$merge_tool_path" --auto \ | |
97 | --L1 "$MERGED (Local)" \ | |
98 | --L2 "$MERGED (Remote)" \ | |
99 | -o "$MERGED" \ | |
100 | "$LOCAL" "$REMOTE" \ | |
101 | > /dev/null 2>&1) | |
102 | fi | |
103 | status=$? | |
104 | else | |
105 | ("$merge_tool_path" --auto \ | |
106 | --L1 "$MERGED (A)" \ | |
107 | --L2 "$MERGED (B)" "$LOCAL" "$REMOTE" \ | |
108 | > /dev/null 2>&1) | |
109 | fi | |
110 | ;; | |
111 | kompare) | |
112 | "$merge_tool_path" "$LOCAL" "$REMOTE" | |
113 | ;; | |
114 | tkdiff) | |
115 | if merge_mode; then | |
116 | if $base_present; then | |
117 | "$merge_tool_path" -a "$BASE" \ | |
118 | -o "$MERGED" "$LOCAL" "$REMOTE" | |
119 | else | |
120 | "$merge_tool_path" \ | |
121 | -o "$MERGED" "$LOCAL" "$REMOTE" | |
122 | fi | |
123 | status=$? | |
124 | else | |
125 | "$merge_tool_path" "$LOCAL" "$REMOTE" | |
126 | fi | |
127 | ;; | |
128 | meld) | |
129 | if merge_mode; then | |
130 | touch "$BACKUP" | |
131 | "$merge_tool_path" "$LOCAL" "$MERGED" "$REMOTE" | |
132 | check_unchanged | |
133 | else | |
134 | "$merge_tool_path" "$LOCAL" "$REMOTE" | |
135 | fi | |
136 | ;; | |
137 | diffuse) | |
138 | if merge_mode; then | |
139 | touch "$BACKUP" | |
140 | if $base_present; then | |
141 | "$merge_tool_path" \ | |
142 | "$LOCAL" "$MERGED" "$REMOTE" \ | |
143 | "$BASE" | cat | |
144 | else | |
145 | "$merge_tool_path" \ | |
146 | "$LOCAL" "$MERGED" "$REMOTE" | cat | |
147 | fi | |
148 | check_unchanged | |
149 | else | |
150 | "$merge_tool_path" "$LOCAL" "$REMOTE" | cat | |
151 | fi | |
152 | ;; | |
153 | vimdiff) | |
154 | if merge_mode; then | |
155 | touch "$BACKUP" | |
156 | "$merge_tool_path" -d -c "wincmd l" \ | |
157 | "$LOCAL" "$MERGED" "$REMOTE" | |
158 | check_unchanged | |
159 | else | |
160 | "$merge_tool_path" -d -c "wincmd l" \ | |
161 | "$LOCAL" "$REMOTE" | |
162 | fi | |
163 | ;; | |
164 | gvimdiff) | |
165 | if merge_mode; then | |
166 | touch "$BACKUP" | |
167 | "$merge_tool_path" -d -c "wincmd l" -f \ | |
168 | "$LOCAL" "$MERGED" "$REMOTE" | |
169 | check_unchanged | |
170 | else | |
171 | "$merge_tool_path" -d -c "wincmd l" -f \ | |
172 | "$LOCAL" "$REMOTE" | |
173 | fi | |
174 | ;; | |
175 | xxdiff) | |
176 | if merge_mode; then | |
177 | touch "$BACKUP" | |
178 | if $base_present; then | |
179 | "$merge_tool_path" -X --show-merged-pane \ | |
180 | -R 'Accel.SaveAsMerged: "Ctrl-S"' \ | |
181 | -R 'Accel.Search: "Ctrl+F"' \ | |
182 | -R 'Accel.SearchForward: "Ctrl-G"' \ | |
183 | --merged-file "$MERGED" \ | |
184 | "$LOCAL" "$BASE" "$REMOTE" | |
185 | else | |
186 | "$merge_tool_path" -X $extra \ | |
187 | -R 'Accel.SaveAsMerged: "Ctrl-S"' \ | |
188 | -R 'Accel.Search: "Ctrl+F"' \ | |
189 | -R 'Accel.SearchForward: "Ctrl-G"' \ | |
190 | --merged-file "$MERGED" \ | |
191 | "$LOCAL" "$REMOTE" | |
192 | fi | |
193 | check_unchanged | |
194 | else | |
195 | "$merge_tool_path" \ | |
196 | -R 'Accel.Search: "Ctrl+F"' \ | |
197 | -R 'Accel.SearchForward: "Ctrl-G"' \ | |
198 | "$LOCAL" "$REMOTE" | |
199 | fi | |
200 | ;; | |
201 | opendiff) | |
202 | if merge_mode; then | |
203 | touch "$BACKUP" | |
204 | if $base_present; then | |
205 | "$merge_tool_path" "$LOCAL" "$REMOTE" \ | |
206 | -ancestor "$BASE" \ | |
207 | -merge "$MERGED" | cat | |
208 | else | |
209 | "$merge_tool_path" "$LOCAL" "$REMOTE" \ | |
210 | -merge "$MERGED" | cat | |
211 | fi | |
212 | check_unchanged | |
213 | else | |
214 | "$merge_tool_path" "$LOCAL" "$REMOTE" | cat | |
215 | fi | |
216 | ;; | |
217 | ecmerge) | |
218 | if merge_mode; then | |
219 | touch "$BACKUP" | |
220 | if $base_present; then | |
221 | "$merge_tool_path" "$BASE" "$LOCAL" "$REMOTE" \ | |
222 | --default --mode=merge3 --to="$MERGED" | |
223 | else | |
224 | "$merge_tool_path" "$LOCAL" "$REMOTE" \ | |
225 | --default --mode=merge2 --to="$MERGED" | |
226 | fi | |
227 | check_unchanged | |
228 | else | |
229 | "$merge_tool_path" "$LOCAL" "$REMOTE" \ | |
230 | --default --mode=merge2 --to="$MERGED" | |
231 | fi | |
232 | ;; | |
233 | emerge) | |
234 | if merge_mode; then | |
235 | if $base_present; then | |
236 | "$merge_tool_path" \ | |
237 | -f emerge-files-with-ancestor-command \ | |
238 | "$LOCAL" "$REMOTE" "$BASE" \ | |
239 | "$(basename "$MERGED")" | |
240 | else | |
241 | "$merge_tool_path" \ | |
242 | -f emerge-files-command \ | |
243 | "$LOCAL" "$REMOTE" \ | |
244 | "$(basename "$MERGED")" | |
245 | fi | |
246 | status=$? | |
247 | else | |
248 | "$merge_tool_path" -f emerge-files-command \ | |
249 | "$LOCAL" "$REMOTE" "$(basename "$MERGED")" | |
250 | fi | |
251 | ;; | |
252 | tortoisemerge) | |
253 | if $base_present; then | |
254 | touch "$BACKUP" | |
255 | "$merge_tool_path" \ | |
256 | -base:"$BASE" -mine:"$LOCAL" \ | |
257 | -theirs:"$REMOTE" -merged:"$MERGED" | |
258 | check_unchanged | |
259 | else | |
260 | echo "TortoiseMerge cannot be used without a base" 1>&2 | |
261 | status=1 | |
262 | fi | |
263 | ;; | |
264 | *) | |
265 | if test -z "$merge_tool_cmd"; then | |
266 | if merge_mode; then | |
267 | status=1 | |
268 | fi | |
269 | break | |
270 | fi | |
271 | if merge_mode; then | |
272 | if test "$merge_tool_trust_exit_code" = "false"; then | |
273 | touch "$BACKUP" | |
274 | ( eval $merge_tool_cmd ) | |
275 | check_unchanged | |
276 | else | |
277 | ( eval $merge_tool_cmd ) | |
278 | status=$? | |
279 | fi | |
280 | else | |
281 | ( eval $merge_tool_cmd ) | |
282 | fi | |
283 | ;; | |
284 | esac | |
285 | return $status | |
286 | } | |
287 | ||
288 | guess_merge_tool () { | |
289 | if merge_mode; then | |
290 | tools="tortoisemerge" | |
291 | else | |
292 | tools="kompare" | |
293 | fi | |
294 | if test -n "$DISPLAY"; then | |
295 | if test -n "$GNOME_DESKTOP_SESSION_ID" ; then | |
296 | tools="meld opendiff kdiff3 tkdiff xxdiff $tools" | |
297 | else | |
298 | tools="opendiff kdiff3 tkdiff xxdiff meld $tools" | |
299 | fi | |
300 | tools="$tools gvimdiff diffuse ecmerge" | |
301 | fi | |
302 | if echo "${VISUAL:-$EDITOR}" | grep emacs > /dev/null 2>&1; then | |
303 | # $EDITOR is emacs so add emerge as a candidate | |
304 | tools="$tools emerge vimdiff" | |
305 | elif echo "${VISUAL:-$EDITOR}" | grep vim > /dev/null 2>&1; then | |
306 | # $EDITOR is vim so add vimdiff as a candidate | |
307 | tools="$tools vimdiff emerge" | |
308 | else | |
309 | tools="$tools emerge vimdiff" | |
310 | fi | |
311 | echo >&2 "merge tool candidates: $tools" | |
312 | ||
313 | # Loop over each candidate and stop when a valid merge tool is found. | |
314 | for i in $tools | |
315 | do | |
316 | merge_tool_path="$(translate_merge_tool_path "$i")" | |
317 | if type "$merge_tool_path" > /dev/null 2>&1; then | |
318 | merge_tool="$i" | |
319 | break | |
320 | fi | |
321 | done | |
322 | ||
323 | if test -z "$merge_tool" ; then | |
324 | echo >&2 "No known merge resolution program available." | |
325 | return 1 | |
326 | fi | |
327 | echo "$merge_tool" | |
328 | } | |
329 | ||
330 | get_configured_merge_tool () { | |
331 | # Diff mode first tries diff.tool and falls back to merge.tool. | |
332 | # Merge mode only checks merge.tool | |
333 | if diff_mode; then | |
334 | tool=$(git config diff.tool) | |
335 | fi | |
336 | if test -z "$tool"; then | |
337 | tool=$(git config merge.tool) | |
338 | fi | |
339 | if test -n "$merge_tool" && ! valid_tool "$merge_tool"; then | |
340 | echo >&2 "git config option $TOOL_MODE.tool set to unknown tool: $merge_tool" | |
341 | echo >&2 "Resetting to default..." | |
342 | return 1 | |
343 | fi | |
344 | echo "$tool" | |
345 | } | |
346 | ||
347 | get_merge_tool_path () { | |
348 | # A merge tool has been set, so verify that it's valid. | |
349 | if ! valid_tool "$merge_tool"; then | |
350 | echo >&2 "Unknown merge tool $merge_tool" | |
351 | exit 1 | |
352 | fi | |
353 | if diff_mode; then | |
354 | merge_tool_path=$(git config difftool."$merge_tool".path) | |
355 | fi | |
356 | if test -z "$merge_tool_path"; then | |
357 | merge_tool_path=$(git config mergetool."$merge_tool".path) | |
358 | fi | |
359 | merge_tool_path="$(translate_merge_tool_path "$merge_tool" "$merge_tool_path")" | |
360 | if test -z "$merge_tool_cmd" && ! type "$merge_tool_path" > /dev/null 2>&1; then | |
361 | echo >&2 "The $TOOL_MODE tool $merge_tool is not available as '$merge_tool_path'" | |
362 | exit 1 | |
363 | fi | |
364 | echo "$merge_tool_path" | |
365 | } | |
366 | ||
367 | get_merge_tool () { | |
368 | merge_tool="$1" | |
369 | # Check if a merge tool has been configured | |
370 | if test -z "$merge_tool"; then | |
371 | merge_tool=$(get_configured_merge_tool) | |
372 | fi | |
373 | # Try to guess an appropriate merge tool if no tool has been set. | |
374 | if test -z "$merge_tool"; then | |
375 | merge_tool=$(guess_merge_tool) || exit | |
376 | fi | |
377 | echo "$merge_tool" | |
378 | } |