mergetool--lib: Allow custom commands to override built-ins

Allow users to override the default commands provided by the mergetools/* scriptlets. Users occasionally run into problems where they expect to be able to override the built-in tool names. The documentation does not explicitly mention that built-ins cannot be overridden, so it's easy to assume that it should work. Lift this restriction so that built-in tools are handled the same way as user-configured tools. Add tests to guarantee this behavior. A nice benefit of this change is that it protects users from having future versions of git trump their custom configuration with a new built-in tool. C.f.: http://stackoverflow.com/questions/7435002/mergetool-from-gitconfig-being-ignored http://thread.gmane.org/gmane.comp.version-control.msysgit/13188 http://thread.gmane.org/gmane.comp.version-control.git/148267 Signed-off-by: David Aguilar <davvid@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

David Aguilar committed Sep 25, 2012 at 00:48 UTC a427ef7acc9d932d1c203dd2fae67f51c4b1d1e8
4 files changed +64 -28
git-mergetool--lib.sh
+38 -2
@@ -104,13 +104,49 @@ run_merge_tool () {
104
105 if merge_mode
106 then
107 - merge_cmd "$1"
107 + run_merge_cmd "$1"
108 else
109 - diff_cmd "$1"
109 + run_diff_cmd "$1"
110 fi
111 return $status
112 }
113
114 +# Run a either a configured or built-in diff tool
115 +run_diff_cmd () {
116 + merge_tool_cmd="$(get_merge_tool_cmd "$1")"
117 + if test -n "$merge_tool_cmd"
118 + then
119 + ( eval $merge_tool_cmd )
120 + status=$?
121 + return $status
122 + else
123 + diff_cmd "$1"
124 + fi
125 +}
126 +
127 +# Run a either a configured or built-in merge tool
128 +run_merge_cmd () {
129 + merge_tool_cmd="$(get_merge_tool_cmd "$1")"
130 + if test -n "$merge_tool_cmd"
131 + then
132 + trust_exit_code="$(git config --bool \
133 + mergetool."$1".trustExitCode || echo false)"
134 + if test "$trust_exit_code" = "false"
135 + then
136 + touch "$BACKUP"
137 + ( eval $merge_tool_cmd )
138 + status=$?
139 + check_unchanged
140 + else
141 + ( eval $merge_tool_cmd )
142 + status=$?
143 + fi
144 + return $status
145 + else
146 + merge_cmd "$1"
147 + fi
148 +}
149 +
150 list_merge_tool_candidates () {
151 if merge_mode
152 then
mergetools/defaults
+2 -26
@@ -8,36 +8,12 @@ can_diff () {
8 }
9
10 diff_cmd () {
11 - merge_tool_cmd="$(get_merge_tool_cmd "$1")"
12 - if test -z "$merge_tool_cmd"
13 - then
14 - status=1
15 - break
16 - fi
17 - ( eval $merge_tool_cmd )
18 - status=$?
11 + status=1
12 return $status
13 }
14
15 merge_cmd () {
23 - merge_tool_cmd="$(get_merge_tool_cmd "$1")"
24 - if test -z "$merge_tool_cmd"
25 - then
26 - status=1
27 - break
28 - fi
29 - trust_exit_code="$(git config --bool \
30 - mergetool."$1".trustExitCode || echo false)"
31 - if test "$trust_exit_code" = "false"
32 - then
33 - touch "$BACKUP"
34 - ( eval $merge_tool_cmd )
35 - status=$?
36 - check_unchanged
37 - else
38 - ( eval $merge_tool_cmd )
39 - status=$?
40 - fi
16 + status=1
17 return $status
18 }
19
t/t7610-mergetool.sh
+13
@@ -471,4 +471,17 @@ test_expect_success 'file with no base' '
471 git reset --hard master >/dev/null 2>&1
472 '
473
474 +test_expect_success 'custom commands override built-ins' '
475 + git checkout -b test14 branch1 &&
476 + git config mergetool.defaults.cmd "cat \"\$REMOTE\" >\"\$MERGED\"" &&
477 + git config mergetool.defaults.trustExitCode true &&
478 + test_must_fail git merge master &&
479 + git mergetool --no-prompt --tool defaults -- both &&
480 + echo master both added >expected &&
481 + test_cmp both expected &&
482 + git config --unset mergetool.defaults.cmd &&
483 + git config --unset mergetool.defaults.trustExitCode &&
484 + git reset --hard master >/dev/null 2>&1
485 +'
486 +
487 test_done
t/t7800-difftool.sh
+11
@@ -76,6 +76,17 @@ test_expect_success PERL 'custom commands' '
76 test "$diff" = "branch"
77 '
78
79 +# Ensures that a custom difftool.<tool>.cmd overrides built-ins
80 +test_expect_success PERL 'custom commands override built-ins' '
81 + restore_test_defaults &&
82 + git config difftool.defaults.cmd "cat \$REMOTE" &&
83 +
84 + diff=$(git difftool --tool defaults --no-prompt branch) &&
85 + test "$diff" = "master" &&
86 +
87 + git config --unset difftool.defaults.cmd
88 +'
89 +
90 # Ensures that git-difftool ignores bogus --tool values
91 test_expect_success PERL 'difftool ignores bad --tool values' '
92 diff=$(git difftool --no-prompt --tool=bad-tool branch)