git-mergetool--lib.shon commit mergetool--lib: don't call "exit" in setup_tool (62957be)
   1#!/bin/sh
   2# git-mergetool--lib is a library for common merge tool functions
   3diff_mode() {
   4        test "$TOOL_MODE" = diff
   5}
   6
   7merge_mode() {
   8        test "$TOOL_MODE" = merge
   9}
  10
  11translate_merge_tool_path () {
  12        echo "$1"
  13}
  14
  15check_unchanged () {
  16        if test "$MERGED" -nt "$BACKUP"
  17        then
  18                status=0
  19        else
  20                while true
  21                do
  22                        echo "$MERGED seems unchanged."
  23                        printf "Was the merge successful? [y/n] "
  24                        read answer || return 1
  25                        case "$answer" in
  26                        y*|Y*) status=0; break ;;
  27                        n*|N*) status=1; break ;;
  28                        esac
  29                done
  30        fi
  31}
  32
  33valid_tool_config () {
  34        if test -n "$(get_merge_tool_cmd "$1")"
  35        then
  36                return 0
  37        else
  38                return 1
  39        fi
  40}
  41
  42valid_tool () {
  43        setup_tool "$1" || valid_tool_config "$1"
  44}
  45
  46setup_tool () {
  47        case "$1" in
  48        vim*|gvim*)
  49                tool=vim
  50                ;;
  51        *)
  52                tool="$1"
  53                ;;
  54        esac
  55        mergetools="$(git --exec-path)/mergetools"
  56
  57        # Load the default definitions
  58        . "$mergetools/defaults"
  59        if ! test -f "$mergetools/$tool"
  60        then
  61                # Use a special return code for this case since we want to
  62                # source "defaults" even when an explicit tool path is
  63                # configured since the user can use that to override the
  64                # default path in the scriptlet.
  65                return 2
  66        fi
  67
  68        # Load the redefined functions
  69        . "$mergetools/$tool"
  70
  71        if merge_mode && ! can_merge
  72        then
  73                echo "error: '$tool' can not be used to resolve merges" >&2
  74                return 1
  75        elif diff_mode && ! can_diff
  76        then
  77                echo "error: '$tool' can only be used to resolve merges" >&2
  78                return 1
  79        fi
  80        return 0
  81}
  82
  83get_merge_tool_cmd () {
  84        # Prints the custom command for a merge tool
  85        merge_tool="$1"
  86        if diff_mode
  87        then
  88                echo "$(git config difftool.$merge_tool.cmd ||
  89                        git config mergetool.$merge_tool.cmd)"
  90        else
  91                echo "$(git config mergetool.$merge_tool.cmd)"
  92        fi
  93}
  94
  95# Entry point for running tools
  96run_merge_tool () {
  97        # If GIT_PREFIX is empty then we cannot use it in tools
  98        # that expect to be able to chdir() to its value.
  99        GIT_PREFIX=${GIT_PREFIX:-.}
 100        export GIT_PREFIX
 101
 102        merge_tool_path="$(get_merge_tool_path "$1")" || exit
 103        base_present="$2"
 104        status=0
 105
 106        # Bring tool-specific functions into scope
 107        setup_tool "$1"
 108        exitcode=$?
 109        case $exitcode in
 110        0)
 111                :
 112                ;;
 113        2)
 114                # The configured tool is not a built-in tool.
 115                test -n "$merge_tool_path" || return 1
 116                ;;
 117        *)
 118                return $exitcode
 119                ;;
 120        esac
 121
 122        if merge_mode
 123        then
 124                run_merge_cmd "$1"
 125        else
 126                run_diff_cmd "$1"
 127        fi
 128        return $status
 129}
 130
 131# Run a either a configured or built-in diff tool
 132run_diff_cmd () {
 133        merge_tool_cmd="$(get_merge_tool_cmd "$1")"
 134        if test -n "$merge_tool_cmd"
 135        then
 136                ( eval $merge_tool_cmd )
 137                status=$?
 138                return $status
 139        else
 140                diff_cmd "$1"
 141        fi
 142}
 143
 144# Run a either a configured or built-in merge tool
 145run_merge_cmd () {
 146        merge_tool_cmd="$(get_merge_tool_cmd "$1")"
 147        if test -n "$merge_tool_cmd"
 148        then
 149                trust_exit_code="$(git config --bool \
 150                        mergetool."$1".trustExitCode || echo false)"
 151                if test "$trust_exit_code" = "false"
 152                then
 153                        touch "$BACKUP"
 154                        ( eval $merge_tool_cmd )
 155                        status=$?
 156                        check_unchanged
 157                else
 158                        ( eval $merge_tool_cmd )
 159                        status=$?
 160                fi
 161                return $status
 162        else
 163                merge_cmd "$1"
 164        fi
 165}
 166
 167list_merge_tool_candidates () {
 168        if merge_mode
 169        then
 170                tools="tortoisemerge"
 171        else
 172                tools="kompare"
 173        fi
 174        if test -n "$DISPLAY"
 175        then
 176                if test -n "$GNOME_DESKTOP_SESSION_ID"
 177                then
 178                        tools="meld opendiff kdiff3 tkdiff xxdiff $tools"
 179                else
 180                        tools="opendiff kdiff3 tkdiff xxdiff meld $tools"
 181                fi
 182                tools="$tools gvimdiff diffuse ecmerge p4merge araxis bc3 codecompare"
 183        fi
 184        case "${VISUAL:-$EDITOR}" in
 185        *vim*)
 186                tools="$tools vimdiff emerge"
 187                ;;
 188        *)
 189                tools="$tools emerge vimdiff"
 190                ;;
 191        esac
 192}
 193
 194show_tool_help () {
 195        unavailable= available= LF='
 196'
 197
 198        scriptlets="$(git --exec-path)"/mergetools
 199        for i in "$scriptlets"/*
 200        do
 201                . "$scriptlets"/defaults
 202                . "$i"
 203
 204                tool="$(basename "$i")"
 205                if test "$tool" = "defaults"
 206                then
 207                        continue
 208                elif merge_mode && ! can_merge
 209                then
 210                        continue
 211                elif diff_mode && ! can_diff
 212                then
 213                        continue
 214                fi
 215
 216                merge_tool_path=$(translate_merge_tool_path "$tool")
 217                if type "$merge_tool_path" >/dev/null 2>&1
 218                then
 219                        available="$available$tool$LF"
 220                else
 221                        unavailable="$unavailable$tool$LF"
 222                fi
 223        done
 224
 225        cmd_name=${TOOL_MODE}tool
 226        if test -n "$available"
 227        then
 228                echo "'git $cmd_name --tool=<tool>' may be set to one of the following:"
 229                echo "$available" | sort | sed -e 's/^/ /'
 230        else
 231                echo "No suitable tool for 'git $cmd_name --tool=<tool>' found."
 232        fi
 233        if test -n "$unavailable"
 234        then
 235                echo
 236                echo 'The following tools are valid, but not currently available:'
 237                echo "$unavailable" | sort | sed -e 's/^/       /'
 238        fi
 239        if test -n "$unavailable$available"
 240        then
 241                echo
 242                echo "Some of the tools listed above only work in a windowed"
 243                echo "environment. If run in a terminal-only session, they will fail."
 244        fi
 245        exit 0
 246}
 247
 248guess_merge_tool () {
 249        list_merge_tool_candidates
 250        echo >&2 "merge tool candidates: $tools"
 251
 252        # Loop over each candidate and stop when a valid merge tool is found.
 253        for i in $tools
 254        do
 255                merge_tool_path="$(translate_merge_tool_path "$i")"
 256                if type "$merge_tool_path" >/dev/null 2>&1
 257                then
 258                        echo "$i"
 259                        return 0
 260                fi
 261        done
 262
 263        echo >&2 "No known merge resolution program available."
 264        return 1
 265}
 266
 267get_configured_merge_tool () {
 268        # Diff mode first tries diff.tool and falls back to merge.tool.
 269        # Merge mode only checks merge.tool
 270        if diff_mode
 271        then
 272                merge_tool=$(git config diff.tool || git config merge.tool)
 273        else
 274                merge_tool=$(git config merge.tool)
 275        fi
 276        if test -n "$merge_tool" && ! valid_tool "$merge_tool"
 277        then
 278                echo >&2 "git config option $TOOL_MODE.tool set to unknown tool: $merge_tool"
 279                echo >&2 "Resetting to default..."
 280                return 1
 281        fi
 282        echo "$merge_tool"
 283}
 284
 285get_merge_tool_path () {
 286        # A merge tool has been set, so verify that it's valid.
 287        merge_tool="$1"
 288        if ! valid_tool "$merge_tool"
 289        then
 290                echo >&2 "Unknown merge tool $merge_tool"
 291                exit 1
 292        fi
 293        if diff_mode
 294        then
 295                merge_tool_path=$(git config difftool."$merge_tool".path ||
 296                                  git config mergetool."$merge_tool".path)
 297        else
 298                merge_tool_path=$(git config mergetool."$merge_tool".path)
 299        fi
 300        if test -z "$merge_tool_path"
 301        then
 302                merge_tool_path="$(translate_merge_tool_path "$merge_tool")"
 303        fi
 304        if test -z "$(get_merge_tool_cmd "$merge_tool")" &&
 305                ! type "$merge_tool_path" >/dev/null 2>&1
 306        then
 307                echo >&2 "The $TOOL_MODE tool $merge_tool is not available as"\
 308                         "'$merge_tool_path'"
 309                exit 1
 310        fi
 311        echo "$merge_tool_path"
 312}
 313
 314get_merge_tool () {
 315        # Check if a merge tool has been configured
 316        merge_tool="$(get_configured_merge_tool)"
 317        # Try to guess an appropriate merge tool if no tool has been set.
 318        if test -z "$merge_tool"
 319        then
 320                merge_tool="$(guess_merge_tool)" || exit
 321        fi
 322        echo "$merge_tool"
 323}