contrib / difftool / git-difftool-helperon commit difftool: use perl built-ins when testing for msys (46ae156)
   1#!/bin/sh
   2# git-difftool-helper is a GIT_EXTERNAL_DIFF-compatible diff tool launcher.
   3# It supports kdiff3, kompare, tkdiff, xxdiff, meld, opendiff,
   4# emerge, ecmerge, vimdiff, gvimdiff, and custom user-configurable tools.
   5# This script is typically launched by using the 'git difftool'
   6# convenience command.
   7#
   8# Copyright (c) 2009 David Aguilar
   9
  10# Set GIT_DIFFTOOL_NO_PROMPT to bypass the per-file prompt.
  11should_prompt () {
  12        test -z "$GIT_DIFFTOOL_NO_PROMPT"
  13}
  14
  15# This function prepares temporary files and launches the appropriate
  16# merge tool.
  17launch_merge_tool () {
  18        # Merged is the filename as it appears in the work tree
  19        # Local is the contents of a/filename
  20        # Remote is the contents of b/filename
  21        # Custom merge tool commands might use $BASE so we provide it
  22        MERGED="$1"
  23        LOCAL="$2"
  24        REMOTE="$3"
  25        BASE="$1"
  26
  27        # $LOCAL and $REMOTE are temporary files so prompt
  28        # the user with the real $MERGED name before launching $merge_tool.
  29        if should_prompt; then
  30                printf "\nViewing: '$MERGED'\n"
  31                printf "Hit return to launch '%s': " "$merge_tool"
  32                read ans
  33        fi
  34
  35        # Run the appropriate merge tool command
  36        case "$merge_tool" in
  37        kdiff3)
  38                basename=$(basename "$MERGED")
  39                "$merge_tool_path" --auto \
  40                        --L1 "$basename (A)" \
  41                        --L2 "$basename (B)" \
  42                        "$LOCAL" "$REMOTE" \
  43                        > /dev/null 2>&1
  44                ;;
  45
  46        kompare)
  47                "$merge_tool_path" "$LOCAL" "$REMOTE"
  48                ;;
  49
  50        tkdiff)
  51                "$merge_tool_path" "$LOCAL" "$REMOTE"
  52                ;;
  53
  54        meld)
  55                "$merge_tool_path" "$LOCAL" "$REMOTE"
  56                ;;
  57
  58        vimdiff)
  59                "$merge_tool_path" -d -c "wincmd l" "$LOCAL" "$REMOTE"
  60                ;;
  61
  62        gvimdiff)
  63                "$merge_tool_path" -d -c "wincmd l" -f "$LOCAL" "$REMOTE"
  64                ;;
  65
  66        xxdiff)
  67                "$merge_tool_path" \
  68                        -R 'Accel.Search: "Ctrl+F"' \
  69                        -R 'Accel.SearchForward: "Ctrl-G"' \
  70                        "$LOCAL" "$REMOTE"
  71                ;;
  72
  73        opendiff)
  74                "$merge_tool_path" "$LOCAL" "$REMOTE" | cat
  75                ;;
  76
  77        ecmerge)
  78                "$merge_tool_path" "$LOCAL" "$REMOTE" \
  79                        --default --mode=merge2 --to="$MERGED"
  80                ;;
  81
  82        emerge)
  83                "$merge_tool_path" -f emerge-files-command \
  84                        "$LOCAL" "$REMOTE" "$(basename "$MERGED")"
  85                ;;
  86
  87        *)
  88                if test -n "$merge_tool_cmd"; then
  89                        ( eval $merge_tool_cmd )
  90                fi
  91                ;;
  92        esac
  93}
  94
  95# Verifies that (difftool|mergetool).<tool>.cmd exists
  96valid_custom_tool() {
  97        merge_tool_cmd="$(git config difftool.$1.cmd)"
  98        test -z "$merge_tool_cmd" &&
  99        merge_tool_cmd="$(git config mergetool.$1.cmd)"
 100        test -n "$merge_tool_cmd"
 101}
 102
 103# Verifies that the chosen merge tool is properly setup.
 104# Built-in merge tools are always valid.
 105valid_tool() {
 106        case "$1" in
 107        kdiff3 | kompare | tkdiff | xxdiff | meld | opendiff | emerge | vimdiff | gvimdiff | ecmerge)
 108                ;; # happy
 109        *)
 110                if ! valid_custom_tool "$1"
 111                then
 112                        return 1
 113                fi
 114                ;;
 115        esac
 116}
 117
 118# Sets up the merge_tool_path variable.
 119# This handles the difftool.<tool>.path configuration.
 120# This also falls back to mergetool defaults.
 121init_merge_tool_path() {
 122        merge_tool_path=$(git config difftool."$1".path)
 123        test -z "$merge_tool_path" &&
 124        merge_tool_path=$(git config mergetool."$1".path)
 125        if test -z "$merge_tool_path"; then
 126                case "$1" in
 127                vimdiff)
 128                        merge_tool_path=vim
 129                        ;;
 130                gvimdiff)
 131                        merge_tool_path=gvim
 132                        ;;
 133                emerge)
 134                        merge_tool_path=emacs
 135                        ;;
 136                *)
 137                        merge_tool_path="$1"
 138                        ;;
 139                esac
 140        fi
 141}
 142
 143# Allow GIT_DIFF_TOOL and GIT_MERGE_TOOL to provide default values
 144test -n "$GIT_MERGE_TOOL" && merge_tool="$GIT_MERGE_TOOL"
 145test -n "$GIT_DIFF_TOOL" && merge_tool="$GIT_DIFF_TOOL"
 146
 147# If merge tool was not specified then use the diff.tool
 148# configuration variable.  If that's invalid then reset merge_tool.
 149# Fallback to merge.tool.
 150if test -z "$merge_tool"; then
 151        merge_tool=$(git config diff.tool)
 152        test -z "$merge_tool" &&
 153        merge_tool=$(git config merge.tool)
 154        if test -n "$merge_tool" && ! valid_tool "$merge_tool"; then
 155                echo >&2 "git config option diff.tool set to unknown tool: $merge_tool"
 156                echo >&2 "Resetting to default..."
 157                unset merge_tool
 158        fi
 159fi
 160
 161# Try to guess an appropriate merge tool if no tool has been set.
 162if test -z "$merge_tool"; then
 163        # We have a $DISPLAY so try some common UNIX merge tools
 164        if test -n "$DISPLAY"; then
 165                # If gnome then prefer meld, otherwise, prefer kdiff3 or kompare
 166                if test -n "$GNOME_DESKTOP_SESSION_ID" ; then
 167                        merge_tool_candidates="meld kdiff3 kompare tkdiff xxdiff gvimdiff"
 168                else
 169                        merge_tool_candidates="kdiff3 kompare tkdiff xxdiff meld gvimdiff"
 170                fi
 171        fi
 172        if echo "${VISUAL:-$EDITOR}" | grep 'emacs' > /dev/null 2>&1; then
 173                # $EDITOR is emacs so add emerge as a candidate
 174                merge_tool_candidates="$merge_tool_candidates emerge opendiff vimdiff"
 175        elif echo "${VISUAL:-$EDITOR}" | grep 'vim' > /dev/null 2>&1; then
 176                # $EDITOR is vim so add vimdiff as a candidate
 177                merge_tool_candidates="$merge_tool_candidates vimdiff opendiff emerge"
 178        else
 179                merge_tool_candidates="$merge_tool_candidates opendiff emerge vimdiff"
 180        fi
 181        echo "merge tool candidates: $merge_tool_candidates"
 182
 183        # Loop over each candidate and stop when a valid merge tool is found.
 184        for i in $merge_tool_candidates
 185        do
 186                init_merge_tool_path $i
 187                if type "$merge_tool_path" > /dev/null 2>&1; then
 188                        merge_tool=$i
 189                        break
 190                fi
 191        done
 192
 193        if test -z "$merge_tool" ; then
 194                echo "No known merge resolution program available."
 195                exit 1
 196        fi
 197
 198else
 199        # A merge tool has been set, so verify that it's valid.
 200        if ! valid_tool "$merge_tool"; then
 201                echo >&2 "Unknown merge tool $merge_tool"
 202                exit 1
 203        fi
 204
 205        init_merge_tool_path "$merge_tool"
 206
 207        if test -z "$merge_tool_cmd" && ! type "$merge_tool_path" > /dev/null 2>&1; then
 208                echo "The merge tool $merge_tool is not available as '$merge_tool_path'"
 209                exit 1
 210        fi
 211fi
 212
 213
 214# Launch the merge tool on each path provided by 'git diff'
 215while test $# -gt 6
 216do
 217        launch_merge_tool "$1" "$2" "$5"
 218        shift 7
 219done