git/git-mergetool--lib.sh

253 lines
4.9 KiB
Bash
Raw Normal View History

#!/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"
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"
}