git-commit-vandalism/git-mergetool--lib.sh
Michael J Gruber 853c0ffe42 mergetool-lib: call vim in readonly mode for diffs
When [g]vimdiff is called for files which are opened already, the editor
complains about the existing swap file. But we do not want to write
anything when called from difftool. So, make difftool use "-R" for the
vim family. This

- prevents the use of a swap file and
- marks the buffers readonly.

Signed-off-by: Michael J Gruber <git@drmicha.warpmail.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-02-25 12:00:28 -08:00

426 lines
9.0 KiB
Bash

#!/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 () {
case "$1" in
vimdiff|vimdiff2)
echo vim
;;
gvimdiff|gvimdiff2)
echo gvim
;;
emerge)
echo emacs
;;
araxis)
echo compare
;;
*)
echo "$1"
;;
esac
}
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
case "$answer" in
y*|Y*) status=0; break ;;
n*|N*) status=1; break ;;
esac
done
fi
}
valid_tool () {
case "$1" in
kdiff3 | tkdiff | xxdiff | meld | opendiff | \
vimdiff | gvimdiff | vimdiff2 | gvimdiff2 | \
emerge | ecmerge | diffuse | araxis | p4merge)
;; # happy
tortoisemerge)
if ! merge_mode; then
return 1
fi
;;
kompare)
if ! diff_mode; then
return 1
fi
;;
*)
if test -z "$(get_merge_tool_cmd "$1")"; then
return 1
fi
;;
esac
}
get_merge_tool_cmd () {
# Prints the custom command for a merge tool
if test -n "$1"; then
merge_tool="$1"
else
merge_tool="$(get_merge_tool)"
fi
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
}
run_merge_tool () {
merge_tool_path="$(get_merge_tool_path "$1")" || exit
base_present="$2"
status=0
case "$1" in
kdiff3)
if merge_mode; then
if $base_present; then
("$merge_tool_path" --auto \
--L1 "$MERGED (Base)" \
--L2 "$MERGED (Local)" \
--L3 "$MERGED (Remote)" \
-o "$MERGED" \
"$BASE" "$LOCAL" "$REMOTE" \
> /dev/null 2>&1)
else
("$merge_tool_path" --auto \
--L1 "$MERGED (Local)" \
--L2 "$MERGED (Remote)" \
-o "$MERGED" \
"$LOCAL" "$REMOTE" \
> /dev/null 2>&1)
fi
status=$?
else
("$merge_tool_path" --auto \
--L1 "$MERGED (A)" \
--L2 "$MERGED (B)" "$LOCAL" "$REMOTE" \
> /dev/null 2>&1)
fi
;;
kompare)
"$merge_tool_path" "$LOCAL" "$REMOTE"
;;
tkdiff)
if merge_mode; then
if $base_present; then
"$merge_tool_path" -a "$BASE" \
-o "$MERGED" "$LOCAL" "$REMOTE"
else
"$merge_tool_path" \
-o "$MERGED" "$LOCAL" "$REMOTE"
fi
status=$?
else
"$merge_tool_path" "$LOCAL" "$REMOTE"
fi
;;
p4merge)
if merge_mode; then
touch "$BACKUP"
if $base_present; then
"$merge_tool_path" "$BASE" "$LOCAL" "$REMOTE" "$MERGED"
else
"$merge_tool_path" "$LOCAL" "$LOCAL" "$REMOTE" "$MERGED"
fi
check_unchanged
else
"$merge_tool_path" "$LOCAL" "$REMOTE"
fi
;;
meld)
if merge_mode; then
touch "$BACKUP"
"$merge_tool_path" "$LOCAL" "$MERGED" "$REMOTE"
check_unchanged
else
"$merge_tool_path" "$LOCAL" "$REMOTE"
fi
;;
diffuse)
if merge_mode; then
touch "$BACKUP"
if $base_present; then
"$merge_tool_path" \
"$LOCAL" "$MERGED" "$REMOTE" \
"$BASE" | cat
else
"$merge_tool_path" \
"$LOCAL" "$MERGED" "$REMOTE" | cat
fi
check_unchanged
else
"$merge_tool_path" "$LOCAL" "$REMOTE" | cat
fi
;;
vimdiff|gvimdiff)
if merge_mode; then
touch "$BACKUP"
if $base_present; then
"$merge_tool_path" -f -d -c "wincmd J" \
"$MERGED" "$LOCAL" "$BASE" "$REMOTE"
else
"$merge_tool_path" -f -d -c "wincmd l" \
"$LOCAL" "$MERGED" "$REMOTE"
fi
check_unchanged
else
"$merge_tool_path" -R -f -d -c "wincmd l" \
"$LOCAL" "$REMOTE"
fi
;;
vimdiff2|gvimdiff2)
if merge_mode; then
touch "$BACKUP"
"$merge_tool_path" -f -d -c "wincmd l" \
"$LOCAL" "$MERGED" "$REMOTE"
check_unchanged
else
"$merge_tool_path" -R -f -d -c "wincmd l" \
"$LOCAL" "$REMOTE"
fi
;;
xxdiff)
if merge_mode; then
touch "$BACKUP"
if $base_present; then
"$merge_tool_path" -X --show-merged-pane \
-R 'Accel.SaveAsMerged: "Ctrl-S"' \
-R 'Accel.Search: "Ctrl+F"' \
-R 'Accel.SearchForward: "Ctrl-G"' \
--merged-file "$MERGED" \
"$LOCAL" "$BASE" "$REMOTE"
else
"$merge_tool_path" -X $extra \
-R 'Accel.SaveAsMerged: "Ctrl-S"' \
-R 'Accel.Search: "Ctrl+F"' \
-R 'Accel.SearchForward: "Ctrl-G"' \
--merged-file "$MERGED" \
"$LOCAL" "$REMOTE"
fi
check_unchanged
else
"$merge_tool_path" \
-R 'Accel.Search: "Ctrl+F"' \
-R 'Accel.SearchForward: "Ctrl-G"' \
"$LOCAL" "$REMOTE"
fi
;;
opendiff)
if merge_mode; then
touch "$BACKUP"
if $base_present; then
"$merge_tool_path" "$LOCAL" "$REMOTE" \
-ancestor "$BASE" \
-merge "$MERGED" | cat
else
"$merge_tool_path" "$LOCAL" "$REMOTE" \
-merge "$MERGED" | cat
fi
check_unchanged
else
"$merge_tool_path" "$LOCAL" "$REMOTE" | cat
fi
;;
ecmerge)
if merge_mode; then
touch "$BACKUP"
if $base_present; then
"$merge_tool_path" "$BASE" "$LOCAL" "$REMOTE" \
--default --mode=merge3 --to="$MERGED"
else
"$merge_tool_path" "$LOCAL" "$REMOTE" \
--default --mode=merge2 --to="$MERGED"
fi
check_unchanged
else
"$merge_tool_path" --default --mode=diff2 \
"$LOCAL" "$REMOTE"
fi
;;
emerge)
if merge_mode; then
if $base_present; then
"$merge_tool_path" \
-f emerge-files-with-ancestor-command \
"$LOCAL" "$REMOTE" "$BASE" \
"$(basename "$MERGED")"
else
"$merge_tool_path" \
-f emerge-files-command \
"$LOCAL" "$REMOTE" \
"$(basename "$MERGED")"
fi
status=$?
else
"$merge_tool_path" -f emerge-files-command \
"$LOCAL" "$REMOTE"
fi
;;
tortoisemerge)
if $base_present; then
touch "$BACKUP"
"$merge_tool_path" \
-base:"$BASE" -mine:"$LOCAL" \
-theirs:"$REMOTE" -merged:"$MERGED"
check_unchanged
else
echo "TortoiseMerge cannot be used without a base" 1>&2
status=1
fi
;;
araxis)
if merge_mode; then
touch "$BACKUP"
if $base_present; then
"$merge_tool_path" -wait -merge -3 -a1 \
"$BASE" "$LOCAL" "$REMOTE" "$MERGED" \
>/dev/null 2>&1
else
"$merge_tool_path" -wait -2 \
"$LOCAL" "$REMOTE" "$MERGED" \
>/dev/null 2>&1
fi
check_unchanged
else
"$merge_tool_path" -wait -2 "$LOCAL" "$REMOTE" \
>/dev/null 2>&1
fi
;;
*)
merge_tool_cmd="$(get_merge_tool_cmd "$1")"
if test -z "$merge_tool_cmd"; then
if merge_mode; then
status=1
fi
break
fi
if merge_mode; 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 )
check_unchanged
else
( eval $merge_tool_cmd )
status=$?
fi
else
( eval $merge_tool_cmd )
fi
;;
esac
return $status
}
guess_merge_tool () {
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"
fi
case "${VISUAL:-$EDITOR}" in
*vim*)
tools="$tools vimdiff emerge"
;;
*)
tools="$tools emerge vimdiff"
;;
esac
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.
if test -n "$1"; then
merge_tool="$1"
else
merge_tool="$(get_merge_tool)"
fi
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"
}