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