mergetool: Fix abort command when resolving symlinks and deleted files
[gitweb.git] / git-mergetool.sh
index 52386a5443ac19f1d8cbf7dc32c1237b2665b861..9b736507be030cc12ed15960206eb7220dcfe6c1 100755 (executable)
@@ -14,19 +14,19 @@ SUBDIRECTORY_OK=Yes
 require_work_tree
 
 # Returns true if the mode reflects a symlink
-function is_symlink () {
+is_symlink () {
     test "$1" = 120000
 }
 
-function local_present () {
+local_present () {
     test -n "$local_mode"
 }
 
-function remote_present () {
+remote_present () {
     test -n "$remote_mode"
 }
 
-function base_present () {
+base_present () {
     test -n "$base_mode"
 }
 
@@ -39,23 +39,21 @@ cleanup_temp_files () {
     fi
 }
 
-function describe_file () {
+describe_file () {
     mode="$1"
     branch="$2"
     file="$3"
 
-    echo -n "    "
+    printf "    "
     if test -z "$mode"; then
-       echo -n "'$path' was deleted"
+       printf "'%s' was deleted" "$path"
     elif is_symlink "$mode" ; then
-       echo -n "'$path' is a symlink containing '"
-       cat "$file"
-       echo -n "'"
+       printf "'%s' is a symlink containing '%s'" "$path" "$file"
     else
        if base_present; then
-           echo -n "'$path' was created"
+           printf "'%s' was created" "$path"
        else
-           echo -n "'$path' was modified"
+           printf "'%s' was modified" "$path"
        fi
     fi
     echo " in the $branch branch"
@@ -63,8 +61,8 @@ function describe_file () {
 
 
 resolve_symlink_merge () {
-    while /bin/true; do
-       echo -n "Use (r)emote or (l)ocal, or (a)bort? "
+    while true; do
+       printf "Use (r)emote or (l)ocal, or (a)bort? "
        read ans
        case "$ans" in
            [lL]*)
@@ -73,13 +71,13 @@ resolve_symlink_merge () {
                cleanup_temp_files --save-backup
                return
                ;;
-          [rR]*)
+           [rR]*)
                git-checkout-index -f --stage=3 -- "$path"
                git-add -- "$path"
                cleanup_temp_files --save-backup
                return
                ;;
-           [qQ]*)
+           [aA]*)
                exit 1
                ;;
            esac
@@ -87,8 +85,8 @@ resolve_symlink_merge () {
 }
 
 resolve_deleted_merge () {
-    while /bin/true; do
-       echo -n "Use (m)odified or (d)eleted file, or (a)bort? "
+    while true; do
+       printf "Use (m)odified or (d)eleted file, or (a)bort? "
        read ans
        case "$ans" in
            [mM]*)
@@ -96,29 +94,56 @@ resolve_deleted_merge () {
                cleanup_temp_files --save-backup
                return
                ;;
-          [dD]*)
+           [dD]*)
                git-rm -- "$path"
                cleanup_temp_files
                return
                ;;
-           [qQ]*)
+           [aA]*)
                exit 1
                ;;
            esac
        done
 }
 
-merge_file () {
-    path="$1"
+check_unchanged () {
+    if test "$path" -nt "$BACKUP" ; then
+       status=0;
+    else
+       while true; do
+           echo "$path 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
+}
 
-    if test ! -f "$path" ; then
-       echo "$path: file not found"
-       exit 1
+save_backup () {
+    if test "$status" -eq 0; then
+       mv -- "$BACKUP" "$path.orig"
+    fi
+}
+
+remove_backup () {
+    if test "$status" -eq 0; then
+       rm "$BACKUP"
     fi
+}
+
+merge_file () {
+    path="$1"
 
     f=`git-ls-files -u -- "$path"`
     if test -z "$f" ; then
-       echo "$path: file does not need merging"
+       if test ! -f "$path" ; then
+           echo "$path: file not found"
+       else
+           echo "$path: file does not need merging"
+       fi
        exit 1
     fi
 
@@ -157,7 +182,7 @@ merge_file () {
     echo "Normal merge conflict for $path:"
     describe_file "$local_mode" "local" "$LOCAL"
     describe_file "$remote_mode" "remote" "$REMOTE"
-    echo -n "Hit return to start merge resolution tool ($merge_tool): "
+    printf "Hit return to start merge resolution tool (%s): " "$merge_tool"
     read ans
 
     case "$merge_tool" in
@@ -170,9 +195,7 @@ merge_file () {
                    -o "$path" -- "$LOCAL" "$REMOTE" > /dev/null 2>&1)
            fi
            status=$?
-           if test "$status" -eq 0; then
-               rm "$BACKUP"
-           fi
+           remove_backup
            ;;
        tkdiff)
            if base_present ; then
@@ -181,29 +204,13 @@ merge_file () {
                tkdiff -o "$path" -- "$LOCAL" "$REMOTE"
            fi
            status=$?
-           if test "$status" -eq 0; then
-               mv -- "$BACKUP" "$path.orig"
-           fi
+           save_backup
            ;;
-       meld)
+       meld|vimdiff)
            touch "$BACKUP"
-           meld -- "$LOCAL" "$path" "$REMOTE"
-           if test "$path" -nt "$BACKUP" ; then
-               status=0;
-           else
-               while true; do
-                   echo "$path seems unchanged."
-                   echo -n "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
-           if test "$status" -eq 0; then
-               mv -- "$BACKUP" "$path.orig"
-           fi
+           $merge_tool -- "$LOCAL" "$path" "$REMOTE"
+           check_unchanged
+           save_backup
            ;;
        xxdiff)
            touch "$BACKUP"
@@ -220,22 +227,8 @@ merge_file () {
                    -R 'Accel.SearchForward: "Ctrl-G"' \
                    --merged-file "$path" -- "$LOCAL" "$REMOTE"
            fi
-           if test "$path" -nt "$BACKUP" ; then
-               status=0;
-           else
-               while true; do
-                   echo "$path seems unchanged."
-                   echo -n "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
-           if test "$status" -eq 0; then
-               mv -- "$BACKUP" "$path.orig"
-           fi
+           check_unchanged
+           save_backup
            ;;
        emerge)
            if base_present ; then
@@ -244,9 +237,7 @@ merge_file () {
                emacs -f emerge-files-command "$LOCAL" "$REMOTE" "$path"
            fi
            status=$?
-           if test "$status" -eq 0; then
-               mv -- "$BACKUP" "$path.orig"
-           fi
+           save_backup
            ;;
     esac
     if test "$status" -ne 0; then
@@ -288,10 +279,15 @@ done
 
 if test -z "$merge_tool"; then
     merge_tool=`git-config merge.tool`
-    if test $merge_tool = kdiff3 -o $merge_tool = tkdiff -o \
-       $merge_tool = xxdiff -o $merge_tool = meld ; then
-       unset merge_tool
-    fi
+    case "$merge_tool" in
+       kdiff3 | tkdiff | xxdiff | meld | emerge | vimdiff | "")
+           ;; # happy
+       *)
+           echo >&2 "git config option merge.tool set to unknown tool: $merge_tool"
+           echo >&2 "Resetting to default..."
+           unset merge_tool
+           ;;
+    esac
 fi
 
 if test -z "$merge_tool" ; then
@@ -305,6 +301,8 @@ if test -z "$merge_tool" ; then
        merge_tool=meld
     elif type emacs >/dev/null 2>&1; then
        merge_tool=emerge
+    elif type vimdiff >/dev/null 2>&1; then
+       merge_tool=vimdiff
     else
        echo "No available merge resolution programs available."
        exit 1
@@ -312,7 +310,7 @@ if test -z "$merge_tool" ; then
 fi
 
 case "$merge_tool" in
-    kdiff3|tkdiff|meld|xxdiff)
+    kdiff3|tkdiff|meld|xxdiff|vimdiff)
        if ! type "$merge_tool" > /dev/null 2>&1; then
            echo "The merge tool $merge_tool is not available"
            exit 1
@@ -339,12 +337,12 @@ if test $# -eq 0 ; then
        echo Merging the files: $files
        git ls-files -u | sed -e 's/^[^ ]*      //' | sort -u | while read i
        do
-               echo ""
+               printf "\n"
                merge_file "$i" < /dev/tty > /dev/tty
        done
 else
        while test $# -gt 0; do
-               echo ""
+               printf "\n"
                merge_file "$1"
                shift
        done