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