diff options
author | David Aguilar <davvid@gmail.com> | 2009-04-08 00:17:20 -0700 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2009-04-08 00:25:24 -0700 |
commit | 21d0ba7ebb0c6b6c6ad844f8a40fff8dd4c0b105 (patch) | |
tree | c09c3a743b2fe74f793607c360b533f06af7d653 /git-mergetool--lib.sh | |
parent | 9a62d72dfa833f98dd0730b3d5136f56d637a5c3 (diff) | |
download | git-21d0ba7ebb0c6b6c6ad844f8a40fff8dd4c0b105.tar.gz git-21d0ba7ebb0c6b6c6ad844f8a40fff8dd4c0b105.tar.xz |
difftool/mergetool: refactor commands to use git-mergetool--lib
This consolidates the common functionality from git-mergetool and
git-difftool--helper into a single git-mergetool--lib scriptlet.
Signed-off-by: David Aguilar <davvid@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'git-mergetool--lib.sh')
-rw-r--r-- | git-mergetool--lib.sh | 378 |
1 files changed, 378 insertions, 0 deletions
diff --git a/git-mergetool--lib.sh b/git-mergetool--lib.sh new file mode 100644 index 000000000..c5db24e45 --- /dev/null +++ b/git-mergetool--lib.sh @@ -0,0 +1,378 @@ +# 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 () { + if test -n "$2"; then + echo "$2" + else + case "$1" in + vimdiff) + path=vim + ;; + gvimdiff) + path=gvim + ;; + emerge) + path=emacs + ;; + *) + path="$1" + ;; + esac + echo "$path" + fi +} + +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 < /dev/tty + 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 | \ + emerge | vimdiff | gvimdiff | ecmerge | diffuse) + ;; # 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 () { + diff_mode && + custom_cmd="$(git config difftool.$1.cmd)" + test -z "$custom_cmd" && + custom_cmd="$(git config mergetool.$1.cmd)" + test -n "$custom_cmd" && + echo "$custom_cmd" +} + +run_merge_tool () { + 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 + ;; + 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) + if merge_mode; then + touch "$BACKUP" + "$merge_tool_path" -d -c "wincmd l" \ + "$LOCAL" "$MERGED" "$REMOTE" + check_unchanged + else + "$merge_tool_path" -d -c "wincmd l" \ + "$LOCAL" "$REMOTE" + fi + ;; + gvimdiff) + if merge_mode; then + touch "$BACKUP" + "$merge_tool_path" -d -c "wincmd l" -f \ + "$LOCAL" "$MERGED" "$REMOTE" + check_unchanged + else + "$merge_tool_path" -d -c "wincmd l" -f \ + "$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" "$LOCAL" "$REMOTE" \ + --default --mode=merge2 --to="$MERGED" + 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" "$(basename "$MERGED")" + 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 + ;; + *) + if test -z "$merge_tool_cmd"; then + if merge_mode; then + status=1 + fi + break + fi + if merge_mode; then + if test "$merge_tool_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" + fi + if echo "${VISUAL:-$EDITOR}" | grep emacs > /dev/null 2>&1; then + # $EDITOR is emacs so add emerge as a candidate + tools="$tools emerge vimdiff" + elif echo "${VISUAL:-$EDITOR}" | grep vim > /dev/null 2>&1; then + # $EDITOR is vim so add vimdiff as a candidate + tools="$tools vimdiff emerge" + else + tools="$tools emerge vimdiff" + fi + 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 + merge_tool="$i" + break + fi + done + + if test -z "$merge_tool" ; then + echo >&2 "No known merge resolution program available." + return 1 + fi + echo "$merge_tool" +} + +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 + tool=$(git config diff.tool) + fi + if test -z "$tool"; then + 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 "$tool" +} + +get_merge_tool_path () { + # A merge tool has been set, so verify that it's valid. + 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) + fi + if test -z "$merge_tool_path"; then + merge_tool_path=$(git config mergetool."$merge_tool".path) + fi + merge_tool_path="$(translate_merge_tool_path "$merge_tool" "$merge_tool_path")" + if test -z "$merge_tool_cmd" && ! 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 () { + merge_tool="$1" + # Check if a merge tool has been configured + if test -z "$merge_tool"; then + merge_tool=$(get_configured_merge_tool) + fi + # 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" +} |