diff options
Diffstat (limited to 'git-mergetool--lib.sh')
-rw-r--r-- | git-mergetool--lib.sh | 252 |
1 files changed, 252 insertions, 0 deletions
diff --git a/git-mergetool--lib.sh b/git-mergetool--lib.sh new file mode 100644 index 0000000000..f013a03506 --- /dev/null +++ b/git-mergetool--lib.sh @@ -0,0 +1,252 @@ +#!/bin/sh +# git-mergetool--lib is a library for common merge tool functions +diff_mode() { + test "$TOOL_MODE" = diff +} + +merge_mode() { + test "$TOOL_MODE" = merge +} + +translate_merge_tool_path () { + echo "$1" +} + +check_unchanged () { + if test "$MERGED" -nt "$BACKUP" + then + status=0 + else + while true + do + echo "$MERGED seems unchanged." + printf "Was the merge successful? [y/n] " + read answer || return 1 + case "$answer" in + y*|Y*) status=0; break ;; + n*|N*) status=1; break ;; + esac + done + fi +} + +valid_tool_config () { + if test -n "$(get_merge_tool_cmd "$1")" + then + return 0 + else + return 1 + fi +} + +valid_tool () { + setup_tool "$1" || valid_tool_config "$1" +} + +setup_tool () { + case "$1" in + vim*|gvim*) + tool=vim + ;; + *) + tool="$1" + ;; + esac + mergetools="$(git --exec-path)/mergetools" + + # Load the default definitions + . "$mergetools/defaults" + if ! test -f "$mergetools/$tool" + then + return 1 + fi + + # Load the redefined functions + . "$mergetools/$tool" + + if merge_mode && ! can_merge + then + echo "error: '$tool' can not be used to resolve merges" >&2 + exit 1 + elif diff_mode && ! can_diff + then + echo "error: '$tool' can only be used to resolve merges" >&2 + exit 1 + fi + return 0 +} + +get_merge_tool_cmd () { + # Prints the custom command for a merge tool + merge_tool="$1" + if diff_mode + then + echo "$(git config difftool.$merge_tool.cmd || + git config mergetool.$merge_tool.cmd)" + else + echo "$(git config mergetool.$merge_tool.cmd)" + fi +} + +# Entry point for running tools +run_merge_tool () { + # If GIT_PREFIX is empty then we cannot use it in tools + # that expect to be able to chdir() to its value. + GIT_PREFIX=${GIT_PREFIX:-.} + export GIT_PREFIX + + merge_tool_path="$(get_merge_tool_path "$1")" || exit + base_present="$2" + status=0 + + # Bring tool-specific functions into scope + setup_tool "$1" + + if merge_mode + then + run_merge_cmd "$1" + else + run_diff_cmd "$1" + fi + return $status +} + +# Run a either a configured or built-in diff tool +run_diff_cmd () { + merge_tool_cmd="$(get_merge_tool_cmd "$1")" + if test -n "$merge_tool_cmd" + then + ( eval $merge_tool_cmd ) + status=$? + return $status + else + diff_cmd "$1" + fi +} + +# Run a either a configured or built-in merge tool +run_merge_cmd () { + merge_tool_cmd="$(get_merge_tool_cmd "$1")" + if test -n "$merge_tool_cmd" + then + trust_exit_code="$(git config --bool \ + mergetool."$1".trustExitCode || echo false)" + if test "$trust_exit_code" = "false" + then + touch "$BACKUP" + ( eval $merge_tool_cmd ) + status=$? + check_unchanged + else + ( eval $merge_tool_cmd ) + status=$? + fi + return $status + else + merge_cmd "$1" + fi +} + +list_merge_tool_candidates () { + if merge_mode + then + tools="tortoisemerge" + else + tools="kompare" + fi + if test -n "$DISPLAY" + then + if test -n "$GNOME_DESKTOP_SESSION_ID" + then + tools="meld opendiff kdiff3 tkdiff xxdiff $tools" + else + tools="opendiff kdiff3 tkdiff xxdiff meld $tools" + fi + tools="$tools gvimdiff diffuse ecmerge p4merge araxis bc3 codecompare" + fi + case "${VISUAL:-$EDITOR}" in + *vim*) + tools="$tools vimdiff emerge" + ;; + *) + tools="$tools emerge vimdiff" + ;; + esac +} + +guess_merge_tool () { + list_merge_tool_candidates + echo >&2 "merge tool candidates: $tools" + + # Loop over each candidate and stop when a valid merge tool is found. + for i 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 + done + + echo >&2 "No known merge resolution program available." + return 1 +} + +get_configured_merge_tool () { + # Diff mode first tries diff.tool and falls back to merge.tool. + # Merge mode only checks merge.tool + if diff_mode + then + merge_tool=$(git config diff.tool || git config merge.tool) + else + merge_tool=$(git config merge.tool) + fi + if test -n "$merge_tool" && ! valid_tool "$merge_tool" + then + echo >&2 "git config option $TOOL_MODE.tool set to unknown tool: $merge_tool" + echo >&2 "Resetting to default..." + return 1 + fi + echo "$merge_tool" +} + +get_merge_tool_path () { + # A merge tool has been set, so verify that it's valid. + merge_tool="$1" + if ! valid_tool "$merge_tool" + then + echo >&2 "Unknown merge tool $merge_tool" + exit 1 + fi + if diff_mode + then + merge_tool_path=$(git config difftool."$merge_tool".path || + git config mergetool."$merge_tool".path) + else + merge_tool_path=$(git config mergetool."$merge_tool".path) + fi + if test -z "$merge_tool_path" + then + merge_tool_path="$(translate_merge_tool_path "$merge_tool")" + fi + if test -z "$(get_merge_tool_cmd "$merge_tool")" && + ! type "$merge_tool_path" >/dev/null 2>&1 + then + echo >&2 "The $TOOL_MODE tool $merge_tool is not available as"\ + "'$merge_tool_path'" + exit 1 + fi + echo "$merge_tool_path" +} + +get_merge_tool () { + # Check if a merge tool has been configured + merge_tool="$(get_configured_merge_tool)" + # Try to guess an appropriate merge tool if no tool has been set. + if test -z "$merge_tool" + then + merge_tool="$(guess_merge_tool)" || exit + fi + echo "$merge_tool" +} |