Merge branch 'jc/mention-tracking-for-pull-default'
[git.git] / git-mergetool--lib.sh
index 7edc27f92c462774c37f65904cb17a64d86eb6e3..e338be5e57e32f52cfa818fd44a6364c00c24cdd 100644 (file)
@@ -1,6 +1,82 @@
 #!/bin/sh
 # git-mergetool--lib is a library for common merge tool functions
-MERGE_TOOLS_DIR=$(git --exec-path)/mergetools
+
+: ${MERGE_TOOLS_DIR=$(git --exec-path)/mergetools}
+
+mode_ok () {
+       if diff_mode
+       then
+               can_diff
+       elif merge_mode
+       then
+               can_merge
+       else
+               false
+       fi
+}
+
+is_available () {
+       merge_tool_path=$(translate_merge_tool_path "$1") &&
+       type "$merge_tool_path" >/dev/null 2>&1
+}
+
+list_config_tools () {
+       section=$1
+       line_prefix=${2:-}
+
+       git config --get-regexp $section'\..*\.cmd' |
+       while read -r key value
+       do
+               toolname=${key#$section.}
+               toolname=${toolname%.cmd}
+
+               printf "%s%s\n" "$line_prefix" "$toolname"
+       done
+}
+
+show_tool_names () {
+       condition=${1:-true} per_line_prefix=${2:-} preamble=${3:-}
+       not_found_msg=${4:-}
+       extra_content=${5:-}
+
+       shown_any=
+       ( cd "$MERGE_TOOLS_DIR" && ls ) | {
+               while read toolname
+               do
+                       if setup_tool "$toolname" 2>/dev/null &&
+                               (eval "$condition" "$toolname")
+                       then
+                               if test -n "$preamble"
+                               then
+                                       printf "%s\n" "$preamble"
+                                       preamble=
+                               fi
+                               shown_any=yes
+                               printf "%s%s\n" "$per_line_prefix" "$toolname"
+                       fi
+               done
+
+               if test -n "$extra_content"
+               then
+                       if test -n "$preamble"
+                       then
+                               # Note: no '\n' here since we don't want a
+                               # blank line if there is no initial content.
+                               printf "%s" "$preamble"
+                               preamble=
+                       fi
+                       shown_any=yes
+                       printf "\n%s\n" "$extra_content"
+               fi
+
+               if test -n "$preamble" && test -n "$not_found_msg"
+               then
+                       printf "%s\n" "$not_found_msg"
+               fi
+
+               test -n "$shown_any"
+       }
+}
 
 diff_mode() {
        test "$TOOL_MODE" = diff
@@ -199,37 +275,35 @@ list_merge_tool_candidates () {
 }
 
 show_tool_help () {
-       unavailable= available= LF='
-'
-       for i in "$MERGE_TOOLS_DIR"/*
-       do
-               tool=$(basename "$i")
-               setup_tool "$tool" 2>/dev/null || continue
+       tool_opt="'git ${TOOL_MODE}tool --tool-<tool>'"
 
-               merge_tool_path=$(translate_merge_tool_path "$tool")
-               if type "$merge_tool_path" >/dev/null 2>&1
-               then
-                       available="$available$tool$LF"
-               else
-                       unavailable="$unavailable$tool$LF"
-               fi
-       done
+       tab='   '
+       LF='
+'
+       any_shown=no
 
        cmd_name=${TOOL_MODE}tool
-       if test -n "$available"
-       then
-               echo "'git $cmd_name --tool=<tool>' may be set to one of the following:"
-               echo "$available" | sort | sed -e 's/^/ /'
-       else
-               echo "No suitable tool for 'git $cmd_name --tool=<tool>' found."
-       fi
-       if test -n "$unavailable"
+       config_tools=$({
+               diff_mode && list_config_tools difftool "$tab$tab"
+               list_config_tools mergetool "$tab$tab"
+       } | sort)
+       extra_content=
+       if test -n "$config_tools"
        then
-               echo
-               echo 'The following tools are valid, but not currently available:'
-               echo "$unavailable" | sort | sed -e 's/^/       /'
+               extra_content="${tab}user-defined:${LF}$config_tools"
        fi
-       if test -n "$unavailable$available"
+
+       show_tool_names 'mode_ok && is_available' "$tab$tab" \
+               "$tool_opt may be set to one of the following:" \
+               "No suitable tool for 'git $cmd_name --tool=<tool>' found." \
+               "$extra_content" &&
+               any_shown=yes
+
+       show_tool_names 'mode_ok && ! is_available' "$tab$tab" \
+               "${LF}The following tools are valid, but not currently available:" &&
+               any_shown=yes
+
+       if test "$any_shown" = yes
        then
                echo
                echo "Some of the tools listed above only work in a windowed"
@@ -249,17 +323,12 @@ guess_merge_tool () {
        EOF
 
        # Loop over each candidate and stop when a valid merge tool is found.
-       for i in $tools
+       for tool in $tools
        do
-               merge_tool_path=$(translate_merge_tool_path "$i")
-               if type "$merge_tool_path" >/dev/null 2>&1
-               then
-                       echo "$i"
-                       return 0
-               fi
+               is_available "$tool" && echo "$tool" && return 0
        done
 
-       echo >&2 "No known merge resolution program available."
+       echo >&2 "No known ${TOOL_MODE} tool is available."
        return 1
 }