@matheusbsbs / matheus-bagliano / commits / 21d0ba7ebb
Fork 0

difftool/mergetool: refactor commands to use git-mergetool--lib

This consolidates the common functionality from git-mergetool and git-difftool--helper into a single git-mergetool--lib scriptlet. Signed-off-by: David Aguilar <davvid@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

David Aguilar committed Apr 8, 2009 at 00:17 UTC 21d0ba7ebb0c6b6c6ad844f8a40fff8dd4c0b105
6 files changed +458 -388
.gitignore
+1
@@ -80,6 +80,7 @@ git-merge-recursive
80 git-merge-resolve
81 git-merge-subtree
82 git-mergetool
83 +git-mergetool--lib
84 git-mktag
85 git-mktree
86 git-name-rev
Documentation/git-mergetool--lib.txt new
+56
@@ -0,0 +1,56 @@
1 +git-mergetool--lib(1)
2 +=====================
3 +
4 +NAME
5 +----
6 +git-mergetool--lib - Common git merge tool shell scriptlets
7 +
8 +SYNOPSIS
9 +--------
10 +'. "$(git --exec-path)/git-mergetool--lib"'
11 +
12 +DESCRIPTION
13 +-----------
14 +
15 +This is not a command the end user would want to run. Ever.
16 +This documentation is meant for people who are studying the
17 +Porcelain-ish scripts and/or are writing new ones.
18 +
19 +The 'git-mergetool--lib' scriptlet is designed to be sourced (using
20 +`.`) by other shell scripts to set up functions for working
21 +with git merge tools.
22 +
23 +Before sourcing it, your script should set up a few variables;
24 +`TOOL_MODE` is used to define the operation mode for various
25 +functions. 'diff' and 'merge' are valid values.
26 +
27 +FUNCTIONS
28 +---------
29 +get_merge_tool::
30 + returns a merge tool
31 +
32 +get_merge_tool_cmd::
33 + returns the custom command for a merge tool.
34 +
35 +get_merge_tool_path::
36 + returns the custom path for a merge tool.
37 +
38 +run_merge_tool::
39 + launches a merge tool given the tool name and a true/false
40 + flag to indicate whether a merge base is present.
41 + '$merge_tool', '$merge_tool_path', and for custom commands,
42 + '$merge_tool_cmd', must be defined prior to calling
43 + run_merge_tool. Additionally, '$MERGED', '$LOCAL', '$REMOTE',
44 + and '$BASE' must be defined for use by the merge tool.
45 +
46 +Author
47 +------
48 +Written by David Aguilar <davvid@gmail.com>
49 +
50 +Documentation
51 +--------------
52 +Documentation by David Aguilar and the git-list <git@vger.kernel.org>.
53 +
54 +GIT
55 +---
56 +Part of the linkgit:git[1] suite
Makefile
+1
@@ -284,6 +284,7 @@ SCRIPT_SH += git-merge-octopus.sh
284 SCRIPT_SH += git-merge-one-file.sh
285 SCRIPT_SH += git-merge-resolve.sh
286 SCRIPT_SH += git-mergetool.sh
287 +SCRIPT_SH += git-mergetool--lib.sh
288 SCRIPT_SH += git-parse-remote.sh
289 SCRIPT_SH += git-pull.sh
290 SCRIPT_SH += git-quiltimport.sh
git-difftool--helper.sh
+9 -177
@@ -5,6 +5,10 @@
5 #
6 # Copyright (c) 2009 David Aguilar
7
8 +# Load common functions from git-mergetool--lib
9 +TOOL_MODE=diff
10 +. git-mergetool--lib
11 +
12 # difftool.prompt controls the default prompt/no-prompt behavior
13 # and is overridden with $GIT_DIFFTOOL*_PROMPT.
14 should_prompt () {
@@ -16,8 +20,7 @@ should_prompt () {
20 fi
21 }
22
19 -# This function prepares temporary files and launches the appropriate
20 -# merge tool.
23 +# Sets up shell variables and runs a merge tool
24 launch_merge_tool () {
25 # Merged is the filename as it appears in the work tree
26 # Local is the contents of a/filename
@@ -37,187 +40,16 @@ launch_merge_tool () {
40 fi
41
42 # 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 - ;;
49 -
50 - kompare)
51 - "$merge_tool_path" "$LOCAL" "$REMOTE"
52 - ;;
53 -
54 - tkdiff)
55 - "$merge_tool_path" "$LOCAL" "$REMOTE"
56 - ;;
57 -
58 - meld)
59 - "$merge_tool_path" "$LOCAL" "$REMOTE"
60 - ;;
61 -
62 - diffuse)
63 - "$merge_tool_path" "$LOCAL" "$REMOTE" | cat
64 - ;;
65 -
66 - vimdiff)
67 - "$merge_tool_path" -d -c "wincmd l" "$LOCAL" "$REMOTE"
68 - ;;
69 -
70 - gvimdiff)
71 - "$merge_tool_path" -d -c "wincmd l" -f "$LOCAL" "$REMOTE"
72 - ;;
73 -
74 - xxdiff)
75 - "$merge_tool_path" \
76 - -R 'Accel.Search: "Ctrl+F"' \
77 - -R 'Accel.SearchForward: "Ctrl-G"' \
78 - "$LOCAL" "$REMOTE"
79 - ;;
80 -
81 - opendiff)
82 - "$merge_tool_path" "$LOCAL" "$REMOTE" | cat
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
101 -}
102 -
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"
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
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
124 -}
125 -
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
43 + run_merge_tool "$merge_tool"
44 }
45
46 # Allow GIT_DIFF_TOOL and GIT_MERGE_TOOL to provide default values
47 test -n "$GIT_MERGE_TOOL" && merge_tool="$GIT_MERGE_TOOL"
48 test -n "$GIT_DIFF_TOOL" && merge_tool="$GIT_DIFF_TOOL"
49
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
168 -
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"
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 -
50 +merge_tool=$(get_merge_tool "$merge_tool") || exit
51 +merge_tool_cmd="$(get_merge_tool_cmd "$merge_tool")"
52 +merge_tool_path="$(get_merge_tool_path "$merge_tool")" || exit
53
54 # Launch the merge tool on each path provided by 'git diff'
55 while test $# -gt 6
git-mergetool--lib.sh new
+378
@@ -0,0 +1,378 @@
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 +}
git-mergetool.sh
+13 -211
@@ -11,7 +11,9 @@
11 USAGE='[--tool=tool] [-y|--no-prompt|--prompt] [file to merge] ...'
12 SUBDIRECTORY_OK=Yes
13 OPTIONS_SPEC=
14 +TOOL_MODE=merge
15 . git-sh-setup
16 +. git-mergetool--lib
17 require_work_tree
18
19 # Returns true if the mode reflects a symlink
@@ -110,22 +112,6 @@ resolve_deleted_merge () {
112 done
113 }
114
113 -check_unchanged () {
114 - if test "$MERGED" -nt "$BACKUP" ; then
115 - status=0;
116 - else
117 - while true; do
118 - echo "$MERGED seems unchanged."
119 - printf "Was the merge successful? [y/n] "
120 - read answer < /dev/tty
121 - case "$answer" in
122 - y*|Y*) status=0; break ;;
123 - n*|N*) status=1; break ;;
124 - esac
125 - done
126 - fi
127 -}
128 -
115 checkout_staged_file () {
116 tmpfile=$(expr "$(git checkout-index --temp --stage="$1" "$2")" : '\([^ ]*\) ')
117
@@ -188,107 +174,11 @@ merge_file () {
174 read ans
175 fi
176
191 - case "$merge_tool" in
192 - kdiff3)
193 - if base_present ; then
194 - ("$merge_tool_path" --auto --L1 "$MERGED (Base)" --L2 "$MERGED (Local)" --L3 "$MERGED (Remote)" \
195 - -o "$MERGED" "$BASE" "$LOCAL" "$REMOTE" > /dev/null 2>&1)
196 - else
197 - ("$merge_tool_path" --auto --L1 "$MERGED (Local)" --L2 "$MERGED (Remote)" \
198 - -o "$MERGED" "$LOCAL" "$REMOTE" > /dev/null 2>&1)
199 - fi
200 - status=$?
201 - ;;
202 - tkdiff)
203 - if base_present ; then
204 - "$merge_tool_path" -a "$BASE" -o "$MERGED" "$LOCAL" "$REMOTE"
205 - else
206 - "$merge_tool_path" -o "$MERGED" "$LOCAL" "$REMOTE"
207 - fi
208 - status=$?
209 - ;;
210 - meld)
211 - touch "$BACKUP"
212 - "$merge_tool_path" "$LOCAL" "$MERGED" "$REMOTE"
213 - check_unchanged
214 - ;;
215 - vimdiff)
216 - touch "$BACKUP"
217 - "$merge_tool_path" -d -c "wincmd l" "$LOCAL" "$MERGED" "$REMOTE"
218 - check_unchanged
219 - ;;
220 - gvimdiff)
221 - touch "$BACKUP"
222 - "$merge_tool_path" -d -c "wincmd l" -f "$LOCAL" "$MERGED" "$REMOTE"
223 - check_unchanged
224 - ;;
225 - xxdiff)
226 - touch "$BACKUP"
227 - if base_present ; then
228 - "$merge_tool_path" -X --show-merged-pane \
229 - -R 'Accel.SaveAsMerged: "Ctrl-S"' \
230 - -R 'Accel.Search: "Ctrl+F"' \
231 - -R 'Accel.SearchForward: "Ctrl-G"' \
232 - --merged-file "$MERGED" "$LOCAL" "$BASE" "$REMOTE"
233 - else
234 - "$merge_tool_path" -X --show-merged-pane \
235 - -R 'Accel.SaveAsMerged: "Ctrl-S"' \
236 - -R 'Accel.Search: "Ctrl+F"' \
237 - -R 'Accel.SearchForward: "Ctrl-G"' \
238 - --merged-file "$MERGED" "$LOCAL" "$REMOTE"
239 - fi
240 - check_unchanged
241 - ;;
242 - opendiff)
243 - touch "$BACKUP"
244 - if base_present; then
245 - "$merge_tool_path" "$LOCAL" "$REMOTE" -ancestor "$BASE" -merge "$MERGED" | cat
246 - else
247 - "$merge_tool_path" "$LOCAL" "$REMOTE" -merge "$MERGED" | cat
248 - fi
249 - check_unchanged
250 - ;;
251 - ecmerge)
252 - touch "$BACKUP"
253 - if base_present; then
254 - "$merge_tool_path" "$BASE" "$LOCAL" "$REMOTE" --default --mode=merge3 --to="$MERGED"
255 - else
256 - "$merge_tool_path" "$LOCAL" "$REMOTE" --default --mode=merge2 --to="$MERGED"
257 - fi
258 - check_unchanged
259 - ;;
260 - emerge)
261 - if base_present ; then
262 - "$merge_tool_path" -f emerge-files-with-ancestor-command "$LOCAL" "$REMOTE" "$BASE" "$(basename "$MERGED")"
263 - else
264 - "$merge_tool_path" -f emerge-files-command "$LOCAL" "$REMOTE" "$(basename "$MERGED")"
265 - fi
266 - status=$?
267 - ;;
268 - tortoisemerge)
269 - if base_present ; then
270 - touch "$BACKUP"
271 - "$merge_tool_path" -base:"$BASE" -mine:"$LOCAL" -theirs:"$REMOTE" -merged:"$MERGED"
272 - check_unchanged
273 - else
274 - echo "TortoiseMerge cannot be used without a base" 1>&2
275 - status=1
276 - fi
277 - ;;
278 - *)
279 - if test -n "$merge_tool_cmd"; then
280 - if test "$merge_tool_trust_exit_code" = "false"; then
281 - touch "$BACKUP"
282 - ( eval $merge_tool_cmd )
283 - check_unchanged
284 - else
285 - ( eval $merge_tool_cmd )
286 - status=$?
287 - fi
288 - fi
289 - ;;
290 - esac
291 - if test "$status" -ne 0; then
177 + present=false
178 + base_present &&
179 + present=true
180 +
181 + if ! run_merge_tool "$merge_tool" "$present"; then
182 echo "merge of $MERGED failed" 1>&2
183 mv -- "$BACKUP" "$MERGED"
184
@@ -347,44 +237,6 @@ do
237 shift
238 done
239
350 -valid_custom_tool()
351 -{
352 - merge_tool_cmd="$(git config mergetool.$1.cmd)"
353 - test -n "$merge_tool_cmd"
354 -}
355 -
356 -valid_tool() {
357 - case "$1" in
358 - kdiff3 | tkdiff | xxdiff | meld | opendiff | emerge | vimdiff | gvimdiff | ecmerge | tortoisemerge)
359 - ;; # happy
360 - *)
361 - if ! valid_custom_tool "$1"; then
362 - return 1
363 - fi
364 - ;;
365 - esac
366 -}
367 -
368 -init_merge_tool_path() {
369 - merge_tool_path=$(git config mergetool.$1.path)
370 - if test -z "$merge_tool_path" ; then
371 - case "$1" in
372 - vimdiff)
373 - merge_tool_path=vim
374 - ;;
375 - gvimdiff)
376 - merge_tool_path=gvim
377 - ;;
378 - emerge)
379 - merge_tool_path=emacs
380 - ;;
381 - *)
382 - merge_tool_path=$1
383 - ;;
384 - esac
385 - fi
386 -}
387 -
240 prompt_after_failed_merge() {
241 while true; do
242 printf "Continue merging other unresolved paths (y/n) ? "
@@ -402,62 +254,12 @@ prompt_after_failed_merge() {
254 done
255 }
256
405 -if test -z "$merge_tool"; then
406 - merge_tool=$(git config merge.tool)
407 - if test -n "$merge_tool" && ! valid_tool "$merge_tool"; then
408 - echo >&2 "git config option merge.tool set to unknown tool: $merge_tool"
409 - echo >&2 "Resetting to default..."
410 - unset merge_tool
411 - fi
412 -fi
413 -
414 -if test -z "$merge_tool" ; then
415 - if test -n "$DISPLAY"; then
416 - if test -n "$GNOME_DESKTOP_SESSION_ID" ; then
417 - merge_tool_candidates="meld kdiff3 tkdiff xxdiff tortoisemerge gvimdiff diffuse"
418 - else
419 - merge_tool_candidates="kdiff3 tkdiff xxdiff meld tortoisemerge gvimdiff diffuse"
420 - fi
421 - fi
422 - if echo "${VISUAL:-$EDITOR}" | grep 'emacs' > /dev/null 2>&1; then
423 - merge_tool_candidates="$merge_tool_candidates emerge opendiff vimdiff"
424 - elif echo "${VISUAL:-$EDITOR}" | grep 'vim' > /dev/null 2>&1; then
425 - merge_tool_candidates="$merge_tool_candidates vimdiff opendiff emerge"
426 - else
427 - merge_tool_candidates="$merge_tool_candidates opendiff emerge vimdiff"
428 - fi
429 - echo "merge tool candidates: $merge_tool_candidates"
430 - for i in $merge_tool_candidates; do
431 - init_merge_tool_path $i
432 - if type "$merge_tool_path" > /dev/null 2>&1; then
433 - merge_tool=$i
434 - break
435 - fi
436 - done
437 - if test -z "$merge_tool" ; then
438 - echo "No known merge resolution program available."
439 - exit 1
440 - fi
441 -else
442 - if ! valid_tool "$merge_tool"; then
443 - echo >&2 "Unknown merge_tool $merge_tool"
444 - exit 1
445 - fi
446 -
447 - init_merge_tool_path "$merge_tool"
448 -
449 - merge_keep_backup="$(git config --bool merge.keepBackup || echo true)"
450 - merge_keep_temporaries="$(git config --bool mergetool.keepTemporaries || echo false)"
451 -
452 - if test -z "$merge_tool_cmd" && ! type "$merge_tool_path" > /dev/null 2>&1; then
453 - echo "The merge tool $merge_tool is not available as '$merge_tool_path'"
454 - exit 1
455 - fi
456 -
457 - if ! test -z "$merge_tool_cmd"; then
458 - merge_tool_trust_exit_code="$(git config --bool mergetool.$merge_tool.trustExitCode || echo false)"
459 - fi
460 -fi
257 +merge_tool=$(get_merge_tool "$merge_tool") || exit
258 +merge_tool_cmd="$(get_merge_tool_cmd "$merge_tool")"
259 +merge_tool_path="$(get_merge_tool_path "$merge_tool")" || exit
260 +merge_keep_backup="$(git config --bool merge.keepBackup || echo true)"
261 +merge_keep_temporaries="$(git config --bool mergetool.keepTemporaries || echo false)"
262 +merge_tool_trust_exit_code="$(git config --bool mergetool."$merge_tool".trustExitCode || echo false)"
263
264 last_status=0
265 rollup_status=0