Jonathan Nieder | 11d6214 | 2013-11-25 13:03:52 -0800 | [diff] [blame] | 1 | # git-mergetool--lib is a shell library for common merge tool functions |
David Aguilar | f35ec54 | 2013-01-27 16:52:26 -0800 | [diff] [blame] | 2 | |
| 3 | : ${MERGE_TOOLS_DIR=$(git --exec-path)/mergetools} |
David Aguilar | 073678b | 2013-01-26 16:46:12 -0800 | [diff] [blame] | 4 | |
David Aguilar | 719518f | 2015-05-20 02:07:22 -0700 | [diff] [blame] | 5 | IFS=' |
| 6 | ' |
| 7 | |
David Aguilar | 17a1f1c | 2013-01-27 16:52:25 -0800 | [diff] [blame] | 8 | mode_ok () { |
| 9 | if diff_mode |
| 10 | then |
| 11 | can_diff |
| 12 | elif merge_mode |
| 13 | then |
| 14 | can_merge |
| 15 | else |
| 16 | false |
| 17 | fi |
| 18 | } |
| 19 | |
| 20 | is_available () { |
| 21 | merge_tool_path=$(translate_merge_tool_path "$1") && |
| 22 | type "$merge_tool_path" >/dev/null 2>&1 |
| 23 | } |
| 24 | |
John Keeping | 665682c | 2013-01-30 19:55:46 +0000 | [diff] [blame] | 25 | list_config_tools () { |
| 26 | section=$1 |
| 27 | line_prefix=${2:-} |
| 28 | |
| 29 | git config --get-regexp $section'\..*\.cmd' | |
| 30 | while read -r key value |
| 31 | do |
| 32 | toolname=${key#$section.} |
| 33 | toolname=${toolname%.cmd} |
| 34 | |
| 35 | printf "%s%s\n" "$line_prefix" "$toolname" |
| 36 | done |
| 37 | } |
| 38 | |
David Aguilar | 17a1f1c | 2013-01-27 16:52:25 -0800 | [diff] [blame] | 39 | show_tool_names () { |
| 40 | condition=${1:-true} per_line_prefix=${2:-} preamble=${3:-} |
| 41 | not_found_msg=${4:-} |
John Keeping | 665682c | 2013-01-30 19:55:46 +0000 | [diff] [blame] | 42 | extra_content=${5:-} |
David Aguilar | 17a1f1c | 2013-01-27 16:52:25 -0800 | [diff] [blame] | 43 | |
| 44 | shown_any= |
| 45 | ( cd "$MERGE_TOOLS_DIR" && ls ) | { |
pudinha | 83bbf9b | 2020-07-29 22:31:12 +0100 | [diff] [blame] | 46 | while read scriptname |
| 47 | do |
| 48 | setup_tool "$scriptname" 2>/dev/null |
Philippe Blain | 80f5a16 | 2021-01-07 01:09:05 +0000 | [diff] [blame] | 49 | # We need an actual line feed here |
| 50 | variants="$variants |
| 51 | $(list_tool_variants)" |
pudinha | 83bbf9b | 2020-07-29 22:31:12 +0100 | [diff] [blame] | 52 | done |
Philippe Blain | 80f5a16 | 2021-01-07 01:09:05 +0000 | [diff] [blame] | 53 | variants="$(echo "$variants" | sort -u)" |
pudinha | 83bbf9b | 2020-07-29 22:31:12 +0100 | [diff] [blame] | 54 | |
| 55 | for toolname in $variants |
David Aguilar | 17a1f1c | 2013-01-27 16:52:25 -0800 | [diff] [blame] | 56 | do |
| 57 | if setup_tool "$toolname" 2>/dev/null && |
| 58 | (eval "$condition" "$toolname") |
| 59 | then |
| 60 | if test -n "$preamble" |
| 61 | then |
| 62 | printf "%s\n" "$preamble" |
| 63 | preamble= |
| 64 | fi |
| 65 | shown_any=yes |
| 66 | printf "%s%s\n" "$per_line_prefix" "$toolname" |
| 67 | fi |
| 68 | done |
| 69 | |
John Keeping | 665682c | 2013-01-30 19:55:46 +0000 | [diff] [blame] | 70 | if test -n "$extra_content" |
| 71 | then |
| 72 | if test -n "$preamble" |
| 73 | then |
| 74 | # Note: no '\n' here since we don't want a |
| 75 | # blank line if there is no initial content. |
| 76 | printf "%s" "$preamble" |
| 77 | preamble= |
| 78 | fi |
| 79 | shown_any=yes |
| 80 | printf "\n%s\n" "$extra_content" |
| 81 | fi |
| 82 | |
David Aguilar | 17a1f1c | 2013-01-27 16:52:25 -0800 | [diff] [blame] | 83 | if test -n "$preamble" && test -n "$not_found_msg" |
| 84 | then |
| 85 | printf "%s\n" "$not_found_msg" |
| 86 | fi |
| 87 | |
| 88 | test -n "$shown_any" |
| 89 | } |
| 90 | } |
| 91 | |
Denton Liu | 884630b | 2019-04-29 02:21:11 -0400 | [diff] [blame] | 92 | diff_mode () { |
David Aguilar | 21d0ba7 | 2009-04-08 00:17:20 -0700 | [diff] [blame] | 93 | test "$TOOL_MODE" = diff |
| 94 | } |
| 95 | |
Denton Liu | 884630b | 2019-04-29 02:21:11 -0400 | [diff] [blame] | 96 | merge_mode () { |
David Aguilar | 21d0ba7 | 2009-04-08 00:17:20 -0700 | [diff] [blame] | 97 | test "$TOOL_MODE" = merge |
| 98 | } |
| 99 | |
Denton Liu | 884630b | 2019-04-29 02:21:11 -0400 | [diff] [blame] | 100 | gui_mode () { |
| 101 | test "$GIT_MERGETOOL_GUI" = true |
| 102 | } |
| 103 | |
David Aguilar | 21d0ba7 | 2009-04-08 00:17:20 -0700 | [diff] [blame] | 104 | translate_merge_tool_path () { |
David Aguilar | bc7a96a | 2011-08-18 00:23:46 -0700 | [diff] [blame] | 105 | echo "$1" |
David Aguilar | 21d0ba7 | 2009-04-08 00:17:20 -0700 | [diff] [blame] | 106 | } |
| 107 | |
| 108 | check_unchanged () { |
David Aguilar | 240dc3e | 2011-08-18 00:23:45 -0700 | [diff] [blame] | 109 | if test "$MERGED" -nt "$BACKUP" |
| 110 | then |
David Aguilar | 1b6a534 | 2014-11-20 17:20:27 -0800 | [diff] [blame] | 111 | return 0 |
David Aguilar | 21d0ba7 | 2009-04-08 00:17:20 -0700 | [diff] [blame] | 112 | else |
David Aguilar | 240dc3e | 2011-08-18 00:23:45 -0700 | [diff] [blame] | 113 | while true |
| 114 | do |
David Aguilar | 21d0ba7 | 2009-04-08 00:17:20 -0700 | [diff] [blame] | 115 | echo "$MERGED seems unchanged." |
Nikola Forró | cce076e | 2016-04-12 16:44:20 +0200 | [diff] [blame] | 116 | printf "Was the merge successful [y/n]? " |
Jay Soffian | e622f41 | 2011-09-19 19:40:52 -0400 | [diff] [blame] | 117 | read answer || return 1 |
David Aguilar | 21d0ba7 | 2009-04-08 00:17:20 -0700 | [diff] [blame] | 118 | case "$answer" in |
David Aguilar | 1b6a534 | 2014-11-20 17:20:27 -0800 | [diff] [blame] | 119 | y*|Y*) return 0 ;; |
| 120 | n*|N*) return 1 ;; |
David Aguilar | 21d0ba7 | 2009-04-08 00:17:20 -0700 | [diff] [blame] | 121 | esac |
| 122 | done |
| 123 | fi |
| 124 | } |
| 125 | |
| 126 | valid_tool () { |
David Aguilar | 80ff2b6 | 2013-01-27 16:52:23 -0800 | [diff] [blame] | 127 | setup_tool "$1" && return 0 |
| 128 | cmd=$(get_merge_tool_cmd "$1") |
| 129 | test -n "$cmd" |
David Aguilar | bc7a96a | 2011-08-18 00:23:46 -0700 | [diff] [blame] | 130 | } |
| 131 | |
John Keeping | d2512fc | 2013-06-16 18:51:22 +0100 | [diff] [blame] | 132 | setup_user_tool () { |
| 133 | merge_tool_cmd=$(get_merge_tool_cmd "$tool") |
| 134 | test -n "$merge_tool_cmd" || return 1 |
| 135 | |
| 136 | diff_cmd () { |
| 137 | ( eval $merge_tool_cmd ) |
John Keeping | d2512fc | 2013-06-16 18:51:22 +0100 | [diff] [blame] | 138 | } |
| 139 | |
| 140 | merge_cmd () { |
David Aguilar | 7c10605 | 2016-11-29 01:38:07 -0800 | [diff] [blame] | 141 | ( eval $merge_tool_cmd ) |
John Keeping | d2512fc | 2013-06-16 18:51:22 +0100 | [diff] [blame] | 142 | } |
Johannes Schindelin | 12026f4 | 2020-11-11 20:33:18 +0000 | [diff] [blame] | 143 | |
| 144 | list_tool_variants () { |
| 145 | echo "$tool" |
| 146 | } |
John Keeping | d2512fc | 2013-06-16 18:51:22 +0100 | [diff] [blame] | 147 | } |
| 148 | |
David Aguilar | bc7a96a | 2011-08-18 00:23:46 -0700 | [diff] [blame] | 149 | setup_tool () { |
David Aguilar | 073678b | 2013-01-26 16:46:12 -0800 | [diff] [blame] | 150 | tool="$1" |
David Aguilar | bc7a96a | 2011-08-18 00:23:46 -0700 | [diff] [blame] | 151 | |
OndÅ™ej BÃlka | 98e023d | 2013-07-29 10:18:21 +0200 | [diff] [blame] | 152 | # Fallback definitions, to be overridden by tools. |
David Aguilar | 073678b | 2013-01-26 16:46:12 -0800 | [diff] [blame] | 153 | can_merge () { |
| 154 | return 0 |
| 155 | } |
| 156 | |
| 157 | can_diff () { |
| 158 | return 0 |
| 159 | } |
| 160 | |
| 161 | diff_cmd () { |
David Aguilar | 1b6a534 | 2014-11-20 17:20:27 -0800 | [diff] [blame] | 162 | return 1 |
David Aguilar | 073678b | 2013-01-26 16:46:12 -0800 | [diff] [blame] | 163 | } |
| 164 | |
| 165 | merge_cmd () { |
David Aguilar | 1b6a534 | 2014-11-20 17:20:27 -0800 | [diff] [blame] | 166 | return 1 |
David Aguilar | 073678b | 2013-01-26 16:46:12 -0800 | [diff] [blame] | 167 | } |
| 168 | |
Seth House | 9d9cf23 | 2021-02-09 13:07:12 -0700 | [diff] [blame] | 169 | hide_resolved_enabled () { |
| 170 | return 0 |
| 171 | } |
| 172 | |
David Aguilar | 073678b | 2013-01-26 16:46:12 -0800 | [diff] [blame] | 173 | translate_merge_tool_path () { |
| 174 | echo "$1" |
| 175 | } |
| 176 | |
pudinha | 83bbf9b | 2020-07-29 22:31:12 +0100 | [diff] [blame] | 177 | list_tool_variants () { |
| 178 | echo "$tool" |
| 179 | } |
| 180 | |
David Aguilar | 7c10605 | 2016-11-29 01:38:07 -0800 | [diff] [blame] | 181 | # Most tools' exit codes cannot be trusted, so By default we ignore |
| 182 | # their exit code and check the merged file's modification time in |
| 183 | # check_unchanged() to determine whether or not the merge was |
| 184 | # successful. The return value from run_merge_cmd, by default, is |
| 185 | # determined by check_unchanged(). |
| 186 | # |
| 187 | # When a tool's exit code can be trusted then the return value from |
| 188 | # run_merge_cmd is simply the tool's exit code, and check_unchanged() |
| 189 | # is not called. |
| 190 | # |
| 191 | # The return value of exit_code_trustable() tells us whether or not we |
| 192 | # can trust the tool's exit code. |
| 193 | # |
| 194 | # User-defined and built-in tools default to false. |
| 195 | # Built-in tools advertise that their exit code is trustable by |
| 196 | # redefining exit_code_trustable() to true. |
| 197 | |
| 198 | exit_code_trustable () { |
| 199 | false |
| 200 | } |
| 201 | |
pudinha | 83bbf9b | 2020-07-29 22:31:12 +0100 | [diff] [blame] | 202 | if test -f "$MERGE_TOOLS_DIR/$tool" |
David Aguilar | bc7a96a | 2011-08-18 00:23:46 -0700 | [diff] [blame] | 203 | then |
pudinha | 83bbf9b | 2020-07-29 22:31:12 +0100 | [diff] [blame] | 204 | . "$MERGE_TOOLS_DIR/$tool" |
| 205 | elif test -f "$MERGE_TOOLS_DIR/${tool%[0-9]}" |
| 206 | then |
| 207 | . "$MERGE_TOOLS_DIR/${tool%[0-9]}" |
| 208 | else |
John Keeping | d2512fc | 2013-06-16 18:51:22 +0100 | [diff] [blame] | 209 | setup_user_tool |
| 210 | return $? |
David Aguilar | bc7a96a | 2011-08-18 00:23:46 -0700 | [diff] [blame] | 211 | fi |
| 212 | |
John Keeping | d2512fc | 2013-06-16 18:51:22 +0100 | [diff] [blame] | 213 | # Now let the user override the default command for the tool. If |
| 214 | # they have not done so then this will return 1 which we ignore. |
| 215 | setup_user_tool |
David Aguilar | bc7a96a | 2011-08-18 00:23:46 -0700 | [diff] [blame] | 216 | |
pudinha | 83bbf9b | 2020-07-29 22:31:12 +0100 | [diff] [blame] | 217 | if ! list_tool_variants | grep -q "^$tool$" |
| 218 | then |
| 219 | return 1 |
| 220 | fi |
| 221 | |
David Aguilar | bc7a96a | 2011-08-18 00:23:46 -0700 | [diff] [blame] | 222 | if merge_mode && ! can_merge |
| 223 | then |
| 224 | echo "error: '$tool' can not be used to resolve merges" >&2 |
John Keeping | 62957be | 2013-01-26 16:40:06 -0800 | [diff] [blame] | 225 | return 1 |
David Aguilar | bc7a96a | 2011-08-18 00:23:46 -0700 | [diff] [blame] | 226 | elif diff_mode && ! can_diff |
| 227 | then |
| 228 | echo "error: '$tool' can only be used to resolve merges" >&2 |
John Keeping | 62957be | 2013-01-26 16:40:06 -0800 | [diff] [blame] | 229 | return 1 |
David Aguilar | bc7a96a | 2011-08-18 00:23:46 -0700 | [diff] [blame] | 230 | fi |
| 231 | return 0 |
David Aguilar | 21d0ba7 | 2009-04-08 00:17:20 -0700 | [diff] [blame] | 232 | } |
| 233 | |
| 234 | get_merge_tool_cmd () { |
David Aguilar | bc7a96a | 2011-08-18 00:23:46 -0700 | [diff] [blame] | 235 | merge_tool="$1" |
David Aguilar | 240dc3e | 2011-08-18 00:23:45 -0700 | [diff] [blame] | 236 | if diff_mode |
| 237 | then |
David Aguilar | 80ff2b6 | 2013-01-27 16:52:23 -0800 | [diff] [blame] | 238 | git config "difftool.$merge_tool.cmd" || |
| 239 | git config "mergetool.$merge_tool.cmd" |
David Aguilar | 47d6592 | 2009-04-11 20:41:56 -0700 | [diff] [blame] | 240 | else |
David Aguilar | 80ff2b6 | 2013-01-27 16:52:23 -0800 | [diff] [blame] | 241 | git config "mergetool.$merge_tool.cmd" |
David Aguilar | 47d6592 | 2009-04-11 20:41:56 -0700 | [diff] [blame] | 242 | fi |
David Aguilar | 21d0ba7 | 2009-04-08 00:17:20 -0700 | [diff] [blame] | 243 | } |
| 244 | |
David Aguilar | 7c10605 | 2016-11-29 01:38:07 -0800 | [diff] [blame] | 245 | trust_exit_code () { |
| 246 | if git config --bool "mergetool.$1.trustExitCode" |
| 247 | then |
| 248 | :; # OK |
| 249 | elif exit_code_trustable |
| 250 | then |
| 251 | echo true |
| 252 | else |
| 253 | echo false |
| 254 | fi |
| 255 | } |
| 256 | |
Seth House | de8dafb | 2021-02-09 13:07:11 -0700 | [diff] [blame] | 257 | initialize_merge_tool () { |
| 258 | # Bring tool-specific functions into scope |
| 259 | setup_tool "$1" || return 1 |
| 260 | } |
David Aguilar | 7c10605 | 2016-11-29 01:38:07 -0800 | [diff] [blame] | 261 | |
David Aguilar | bc7a96a | 2011-08-18 00:23:46 -0700 | [diff] [blame] | 262 | # Entry point for running tools |
David Aguilar | 21d0ba7 | 2009-04-08 00:17:20 -0700 | [diff] [blame] | 263 | run_merge_tool () { |
David Aguilar | f9ad901 | 2011-05-25 23:21:01 -0700 | [diff] [blame] | 264 | # If GIT_PREFIX is empty then we cannot use it in tools |
| 265 | # that expect to be able to chdir() to its value. |
| 266 | GIT_PREFIX=${GIT_PREFIX:-.} |
| 267 | export GIT_PREFIX |
| 268 | |
David Aguilar | 80ff2b6 | 2013-01-27 16:52:23 -0800 | [diff] [blame] | 269 | merge_tool_path=$(get_merge_tool_path "$1") || exit |
David Aguilar | 21d0ba7 | 2009-04-08 00:17:20 -0700 | [diff] [blame] | 270 | base_present="$2" |
David Aguilar | 21d0ba7 | 2009-04-08 00:17:20 -0700 | [diff] [blame] | 271 | |
David Aguilar | bc7a96a | 2011-08-18 00:23:46 -0700 | [diff] [blame] | 272 | if merge_mode |
| 273 | then |
David Aguilar | a427ef7 | 2012-09-25 00:48:11 -0700 | [diff] [blame] | 274 | run_merge_cmd "$1" |
| 275 | else |
| 276 | run_diff_cmd "$1" |
| 277 | fi |
David Aguilar | a427ef7 | 2012-09-25 00:48:11 -0700 | [diff] [blame] | 278 | } |
| 279 | |
| 280 | # Run a either a configured or built-in diff tool |
| 281 | run_diff_cmd () { |
John Keeping | d2512fc | 2013-06-16 18:51:22 +0100 | [diff] [blame] | 282 | diff_cmd "$1" |
David Aguilar | a427ef7 | 2012-09-25 00:48:11 -0700 | [diff] [blame] | 283 | } |
| 284 | |
| 285 | # Run a either a configured or built-in merge tool |
| 286 | run_merge_cmd () { |
David Aguilar | 7c10605 | 2016-11-29 01:38:07 -0800 | [diff] [blame] | 287 | mergetool_trust_exit_code=$(trust_exit_code "$1") |
| 288 | if test "$mergetool_trust_exit_code" = "true" |
| 289 | then |
| 290 | merge_cmd "$1" |
| 291 | else |
| 292 | touch "$BACKUP" |
| 293 | merge_cmd "$1" |
| 294 | check_unchanged |
| 295 | fi |
David Aguilar | 21d0ba7 | 2009-04-08 00:17:20 -0700 | [diff] [blame] | 296 | } |
| 297 | |
Junio C Hamano | 109859e | 2012-07-23 14:16:12 -0700 | [diff] [blame] | 298 | list_merge_tool_candidates () { |
David Aguilar | 240dc3e | 2011-08-18 00:23:45 -0700 | [diff] [blame] | 299 | if merge_mode |
| 300 | then |
David Aguilar | 21d0ba7 | 2009-04-08 00:17:20 -0700 | [diff] [blame] | 301 | tools="tortoisemerge" |
| 302 | else |
| 303 | tools="kompare" |
| 304 | fi |
David Aguilar | 240dc3e | 2011-08-18 00:23:45 -0700 | [diff] [blame] | 305 | if test -n "$DISPLAY" |
| 306 | then |
| 307 | if test -n "$GNOME_DESKTOP_SESSION_ID" |
| 308 | then |
David Aguilar | 21d0ba7 | 2009-04-08 00:17:20 -0700 | [diff] [blame] | 309 | tools="meld opendiff kdiff3 tkdiff xxdiff $tools" |
| 310 | else |
| 311 | tools="opendiff kdiff3 tkdiff xxdiff meld $tools" |
| 312 | fi |
Stefan Saasen | c5f424f | 2013-10-13 09:29:35 +1100 | [diff] [blame] | 313 | tools="$tools gvimdiff diffuse diffmerge ecmerge" |
Junio C Hamano | f13f9b0 | 2014-10-20 15:49:36 -0700 | [diff] [blame] | 314 | tools="$tools p4merge araxis bc codecompare" |
David Aguilar | eb12adc | 2019-04-04 00:34:38 -0700 | [diff] [blame] | 315 | tools="$tools smerge" |
David Aguilar | 21d0ba7 | 2009-04-08 00:17:20 -0700 | [diff] [blame] | 316 | fi |
René Scharfe | 7b10422 | 2009-11-24 00:29:17 +0100 | [diff] [blame] | 317 | case "${VISUAL:-$EDITOR}" in |
pudinha | 1186897 | 2020-07-29 22:31:13 +0100 | [diff] [blame] | 318 | *nvim*) |
| 319 | tools="$tools nvimdiff vimdiff emerge" |
| 320 | ;; |
René Scharfe | 7b10422 | 2009-11-24 00:29:17 +0100 | [diff] [blame] | 321 | *vim*) |
pudinha | 1186897 | 2020-07-29 22:31:13 +0100 | [diff] [blame] | 322 | tools="$tools vimdiff nvimdiff emerge" |
René Scharfe | 7b10422 | 2009-11-24 00:29:17 +0100 | [diff] [blame] | 323 | ;; |
| 324 | *) |
pudinha | 1186897 | 2020-07-29 22:31:13 +0100 | [diff] [blame] | 325 | tools="$tools emerge vimdiff nvimdiff" |
René Scharfe | 7b10422 | 2009-11-24 00:29:17 +0100 | [diff] [blame] | 326 | ;; |
| 327 | esac |
Junio C Hamano | 109859e | 2012-07-23 14:16:12 -0700 | [diff] [blame] | 328 | } |
| 329 | |
John Keeping | 4a8273a | 2013-01-25 01:43:48 -0800 | [diff] [blame] | 330 | show_tool_help () { |
Stefan Saasen | 2b7ca91 | 2013-10-04 07:34:53 -0700 | [diff] [blame] | 331 | tool_opt="'git ${TOOL_MODE}tool --tool=<tool>'" |
David Aguilar | 88d3406 | 2013-01-25 01:43:54 -0800 | [diff] [blame] | 332 | |
David Aguilar | 17a1f1c | 2013-01-27 16:52:25 -0800 | [diff] [blame] | 333 | tab=' ' |
| 334 | LF=' |
| 335 | ' |
| 336 | any_shown=no |
John Keeping | 62b6f7e | 2013-01-25 01:43:50 -0800 | [diff] [blame] | 337 | |
| 338 | cmd_name=${TOOL_MODE}tool |
John Keeping | 665682c | 2013-01-30 19:55:46 +0000 | [diff] [blame] | 339 | config_tools=$({ |
| 340 | diff_mode && list_config_tools difftool "$tab$tab" |
| 341 | list_config_tools mergetool "$tab$tab" |
| 342 | } | sort) |
| 343 | extra_content= |
| 344 | if test -n "$config_tools" |
| 345 | then |
| 346 | extra_content="${tab}user-defined:${LF}$config_tools" |
| 347 | fi |
| 348 | |
David Aguilar | 17a1f1c | 2013-01-27 16:52:25 -0800 | [diff] [blame] | 349 | show_tool_names 'mode_ok && is_available' "$tab$tab" \ |
| 350 | "$tool_opt may be set to one of the following:" \ |
John Keeping | 665682c | 2013-01-30 19:55:46 +0000 | [diff] [blame] | 351 | "No suitable tool for 'git $cmd_name --tool=<tool>' found." \ |
| 352 | "$extra_content" && |
David Aguilar | 17a1f1c | 2013-01-27 16:52:25 -0800 | [diff] [blame] | 353 | any_shown=yes |
| 354 | |
| 355 | show_tool_names 'mode_ok && ! is_available' "$tab$tab" \ |
| 356 | "${LF}The following tools are valid, but not currently available:" && |
| 357 | any_shown=yes |
| 358 | |
| 359 | if test "$any_shown" = yes |
John Keeping | 4a8273a | 2013-01-25 01:43:48 -0800 | [diff] [blame] | 360 | then |
| 361 | echo |
| 362 | echo "Some of the tools listed above only work in a windowed" |
| 363 | echo "environment. If run in a terminal-only session, they will fail." |
| 364 | fi |
| 365 | exit 0 |
| 366 | } |
| 367 | |
Junio C Hamano | 109859e | 2012-07-23 14:16:12 -0700 | [diff] [blame] | 368 | guess_merge_tool () { |
| 369 | list_merge_tool_candidates |
David Aguilar | 5338a6a | 2013-01-27 16:52:24 -0800 | [diff] [blame] | 370 | cat >&2 <<-EOF |
| 371 | |
| 372 | This message is displayed because '$TOOL_MODE.tool' is not configured. |
| 373 | See 'git ${TOOL_MODE}tool --tool-help' or 'git help config' for more details. |
| 374 | 'git ${TOOL_MODE}tool' will now attempt to use one of the following tools: |
| 375 | $tools |
| 376 | EOF |
David Aguilar | 21d0ba7 | 2009-04-08 00:17:20 -0700 | [diff] [blame] | 377 | |
| 378 | # Loop over each candidate and stop when a valid merge tool is found. |
Michael J Gruber | f67986b | 2015-06-19 11:30:55 +0200 | [diff] [blame] | 379 | IFS=' ' |
David Aguilar | 17a1f1c | 2013-01-27 16:52:25 -0800 | [diff] [blame] | 380 | for tool in $tools |
David Aguilar | 21d0ba7 | 2009-04-08 00:17:20 -0700 | [diff] [blame] | 381 | do |
David Aguilar | 17a1f1c | 2013-01-27 16:52:25 -0800 | [diff] [blame] | 382 | is_available "$tool" && echo "$tool" && return 0 |
David Aguilar | 21d0ba7 | 2009-04-08 00:17:20 -0700 | [diff] [blame] | 383 | done |
| 384 | |
David Aguilar | 17a1f1c | 2013-01-27 16:52:25 -0800 | [diff] [blame] | 385 | echo >&2 "No known ${TOOL_MODE} tool is available." |
David Aguilar | 47d6592 | 2009-04-11 20:41:56 -0700 | [diff] [blame] | 386 | return 1 |
David Aguilar | 21d0ba7 | 2009-04-08 00:17:20 -0700 | [diff] [blame] | 387 | } |
| 388 | |
| 389 | get_configured_merge_tool () { |
Denton Liu | 60aced3 | 2019-04-29 02:21:14 -0400 | [diff] [blame] | 390 | keys= |
David Aguilar | 240dc3e | 2011-08-18 00:23:45 -0700 | [diff] [blame] | 391 | if diff_mode |
| 392 | then |
Denton Liu | 60aced3 | 2019-04-29 02:21:14 -0400 | [diff] [blame] | 393 | if gui_mode |
| 394 | then |
| 395 | keys="diff.guitool merge.guitool diff.tool merge.tool" |
| 396 | else |
| 397 | keys="diff.tool merge.tool" |
| 398 | fi |
David Aguilar | 47d6592 | 2009-04-11 20:41:56 -0700 | [diff] [blame] | 399 | else |
Denton Liu | 60aced3 | 2019-04-29 02:21:14 -0400 | [diff] [blame] | 400 | if gui_mode |
| 401 | then |
| 402 | keys="merge.guitool merge.tool" |
| 403 | else |
| 404 | keys="merge.tool" |
| 405 | fi |
David Aguilar | 21d0ba7 | 2009-04-08 00:17:20 -0700 | [diff] [blame] | 406 | fi |
Denton Liu | 60aced3 | 2019-04-29 02:21:14 -0400 | [diff] [blame] | 407 | |
| 408 | merge_tool=$( |
| 409 | IFS=' ' |
| 410 | for key in $keys |
| 411 | do |
| 412 | selected=$(git config $key) |
| 413 | if test -n "$selected" |
| 414 | then |
| 415 | echo "$selected" |
| 416 | return |
| 417 | fi |
| 418 | done) |
| 419 | |
David Aguilar | 240dc3e | 2011-08-18 00:23:45 -0700 | [diff] [blame] | 420 | if test -n "$merge_tool" && ! valid_tool "$merge_tool" |
| 421 | then |
Denton Liu | 063f2bd | 2018-10-24 12:25:31 -0400 | [diff] [blame] | 422 | echo >&2 "git config option $TOOL_MODE.${gui_prefix}tool set to unknown tool: $merge_tool" |
David Aguilar | 21d0ba7 | 2009-04-08 00:17:20 -0700 | [diff] [blame] | 423 | echo >&2 "Resetting to default..." |
| 424 | return 1 |
| 425 | fi |
David Aguilar | 47d6592 | 2009-04-11 20:41:56 -0700 | [diff] [blame] | 426 | echo "$merge_tool" |
David Aguilar | 21d0ba7 | 2009-04-08 00:17:20 -0700 | [diff] [blame] | 427 | } |
| 428 | |
| 429 | get_merge_tool_path () { |
| 430 | # A merge tool has been set, so verify that it's valid. |
David Aguilar | bc7a96a | 2011-08-18 00:23:46 -0700 | [diff] [blame] | 431 | merge_tool="$1" |
David Aguilar | 240dc3e | 2011-08-18 00:23:45 -0700 | [diff] [blame] | 432 | if ! valid_tool "$merge_tool" |
| 433 | then |
David Aguilar | 21d0ba7 | 2009-04-08 00:17:20 -0700 | [diff] [blame] | 434 | echo >&2 "Unknown merge tool $merge_tool" |
| 435 | exit 1 |
| 436 | fi |
David Aguilar | 240dc3e | 2011-08-18 00:23:45 -0700 | [diff] [blame] | 437 | if diff_mode |
| 438 | then |
David Aguilar | 47d6592 | 2009-04-11 20:41:56 -0700 | [diff] [blame] | 439 | merge_tool_path=$(git config difftool."$merge_tool".path || |
Jon Seymour | 285c6cb | 2011-08-05 23:31:29 +1000 | [diff] [blame] | 440 | git config mergetool."$merge_tool".path) |
David Aguilar | 47d6592 | 2009-04-11 20:41:56 -0700 | [diff] [blame] | 441 | else |
David Aguilar | 21d0ba7 | 2009-04-08 00:17:20 -0700 | [diff] [blame] | 442 | merge_tool_path=$(git config mergetool."$merge_tool".path) |
| 443 | fi |
David Aguilar | 240dc3e | 2011-08-18 00:23:45 -0700 | [diff] [blame] | 444 | if test -z "$merge_tool_path" |
| 445 | then |
David Aguilar | 80ff2b6 | 2013-01-27 16:52:23 -0800 | [diff] [blame] | 446 | merge_tool_path=$(translate_merge_tool_path "$merge_tool") |
David Aguilar | 47d6592 | 2009-04-11 20:41:56 -0700 | [diff] [blame] | 447 | fi |
| 448 | if test -z "$(get_merge_tool_cmd "$merge_tool")" && |
David Aguilar | 240dc3e | 2011-08-18 00:23:45 -0700 | [diff] [blame] | 449 | ! type "$merge_tool_path" >/dev/null 2>&1 |
| 450 | then |
David Aguilar | 47d6592 | 2009-04-11 20:41:56 -0700 | [diff] [blame] | 451 | echo >&2 "The $TOOL_MODE tool $merge_tool is not available as"\ |
Jon Seymour | 285c6cb | 2011-08-05 23:31:29 +1000 | [diff] [blame] | 452 | "'$merge_tool_path'" |
David Aguilar | 21d0ba7 | 2009-04-08 00:17:20 -0700 | [diff] [blame] | 453 | exit 1 |
| 454 | fi |
| 455 | echo "$merge_tool_path" |
| 456 | } |
| 457 | |
| 458 | get_merge_tool () { |
Denton Liu | 05fb872 | 2019-04-29 02:21:08 -0400 | [diff] [blame] | 459 | is_guessed=false |
David Aguilar | 21d0ba7 | 2009-04-08 00:17:20 -0700 | [diff] [blame] | 460 | # Check if a merge tool has been configured |
David Aguilar | 80ff2b6 | 2013-01-27 16:52:23 -0800 | [diff] [blame] | 461 | merge_tool=$(get_configured_merge_tool) |
David Aguilar | 21d0ba7 | 2009-04-08 00:17:20 -0700 | [diff] [blame] | 462 | # Try to guess an appropriate merge tool if no tool has been set. |
David Aguilar | 240dc3e | 2011-08-18 00:23:45 -0700 | [diff] [blame] | 463 | if test -z "$merge_tool" |
| 464 | then |
David Aguilar | 80ff2b6 | 2013-01-27 16:52:23 -0800 | [diff] [blame] | 465 | merge_tool=$(guess_merge_tool) || exit |
Denton Liu | 05fb872 | 2019-04-29 02:21:08 -0400 | [diff] [blame] | 466 | is_guessed=true |
David Aguilar | 21d0ba7 | 2009-04-08 00:17:20 -0700 | [diff] [blame] | 467 | fi |
| 468 | echo "$merge_tool" |
Denton Liu | 05fb872 | 2019-04-29 02:21:08 -0400 | [diff] [blame] | 469 | test "$is_guessed" = false |
David Aguilar | 21d0ba7 | 2009-04-08 00:17:20 -0700 | [diff] [blame] | 470 | } |
Jacob Nisnevich | e36d716 | 2016-03-25 16:17:56 -0700 | [diff] [blame] | 471 | |
| 472 | mergetool_find_win32_cmd () { |
| 473 | executable=$1 |
| 474 | sub_directory=$2 |
| 475 | |
| 476 | # Use $executable if it exists in $PATH |
| 477 | if type -p "$executable" >/dev/null 2>&1 |
| 478 | then |
| 479 | printf '%s' "$executable" |
| 480 | return |
| 481 | fi |
| 482 | |
| 483 | # Look for executable in the typical locations |
| 484 | for directory in $(env | grep -Ei '^PROGRAM(FILES(\(X86\))?|W6432)=' | |
| 485 | cut -d '=' -f 2- | sort -u) |
| 486 | do |
| 487 | if test -n "$directory" && test -x "$directory/$sub_directory/$executable" |
| 488 | then |
| 489 | printf '%s' "$directory/$sub_directory/$executable" |
| 490 | return |
| 491 | fi |
| 492 | done |
| 493 | |
| 494 | printf '%s' "$executable" |
| 495 | } |