fix for more minor memory leaks
[gitweb.git] / git-mergetool.sh
index 1355fcb19f8120fffef3009a2fdc6534ef14e4cc..9f4f3134b60174495c23968cf1ca01ffdbc49bdf 100755 (executable)
@@ -5,13 +5,14 @@
 # Copyright (c) 2006 Theodore Y. Ts'o
 #
 # This file is licensed under the GPL v2, or a later version
-# at the discretion of Junio C Hammano.
+# at the discretion of Junio C Hamano.
 #
 
 USAGE='[--tool=tool] [file to merge] ...'
 SUBDIRECTORY_OK=Yes
 . git-sh-setup
 require_work_tree
+prefix=$(git rev-parse --show-prefix)
 
 # Returns true if the mode reflects a symlink
 is_symlink () {
@@ -44,40 +45,39 @@ describe_file () {
     branch="$2"
     file="$3"
 
-    printf "    "
+    printf "  {%s}: " "$branch"
     if test -z "$mode"; then
-       printf "'%s' was deleted" "$path"
+       echo "deleted"
     elif is_symlink "$mode" ; then
-       printf "'%s' is a symlink containing '%s'" "$path" "$file"
+       echo "a symbolic link -> '$(cat "$file")'"
     else
        if base_present; then
-           printf "'%s' was created" "$path"
+           echo "modified"
        else
-           printf "'%s' was modified" "$path"
+           echo "created"
        fi
     fi
-    echo " in the $branch branch"
 }
 
 
 resolve_symlink_merge () {
     while true; do
-       printf "Use (r)emote or (l)ocal, or (a)bort? "
+       printf "Use (l)ocal or (r)emote, or (a)bort? "
        read ans
        case "$ans" in
            [lL]*)
-               git-checkout-index -f --stage=2 -- "$path"
-               git-add -- "$path"
+               git checkout-index -f --stage=2 -- "$path"
+               git add -- "$path"
                cleanup_temp_files --save-backup
                return
                ;;
-          [rR]*)
-               git-checkout-index -f --stage=3 -- "$path"
-               git-add -- "$path"
+           [rR]*)
+               git checkout-index -f --stage=3 -- "$path"
+               git add -- "$path"
                cleanup_temp_files --save-backup
                return
                ;;
-           [qQ]*)
+           [aA]*)
                exit 1
                ;;
            esac
@@ -86,20 +86,24 @@ resolve_symlink_merge () {
 
 resolve_deleted_merge () {
     while true; do
-       printf "Use (m)odified or (d)eleted file, or (a)bort? "
+       if base_present; then
+           printf "Use (m)odified or (d)eleted file, or (a)bort? "
+       else
+           printf "Use (c)reated or (d)eleted file, or (a)bort? "
+       fi
        read ans
        case "$ans" in
-           [mM]*)
-               git-add -- "$path"
+           [mMcC]*)
+               git add -- "$path"
                cleanup_temp_files --save-backup
                return
                ;;
-          [dD]*)
-               git-rm -- "$path"
+           [dD]*)
+               git rm -- "$path" > /dev/null
                cleanup_temp_files
                return
                ;;
-           [qQ]*)
+           [aA]*)
                exit 1
                ;;
            esac
@@ -137,7 +141,7 @@ remove_backup () {
 merge_file () {
     path="$1"
 
-    f=`git-ls-files -u -- "$path"`
+    f=`git ls-files -u -- "$path"`
     if test -z "$f" ; then
        if test ! -f "$path" ; then
            echo "$path: file not found"
@@ -159,12 +163,12 @@ merge_file () {
     local_mode=`git ls-files -u -- "$path" | awk '{if ($3==2) print $1;}'`
     remote_mode=`git ls-files -u -- "$path" | awk '{if ($3==3) print $1;}'`
 
-    base_present   && git cat-file blob ":1:$path" > "$BASE" 2>/dev/null
-    local_present  && git cat-file blob ":2:$path" > "$LOCAL" 2>/dev/null
-    remote_present && git cat-file blob ":3:$path" > "$REMOTE" 2>/dev/null
+    base_present   && git cat-file blob ":1:$prefix$path" >"$BASE" 2>/dev/null
+    local_present  && git cat-file blob ":2:$prefix$path" >"$LOCAL" 2>/dev/null
+    remote_present && git cat-file blob ":3:$prefix$path" >"$REMOTE" 2>/dev/null
 
     if test -z "$local_mode" -o -z "$remote_mode"; then
-       echo "Deleted merge conflict for $path:"
+       echo "Deleted merge conflict for '$path':"
        describe_file "$local_mode" "local" "$LOCAL"
        describe_file "$remote_mode" "remote" "$REMOTE"
        resolve_deleted_merge
@@ -172,14 +176,14 @@ merge_file () {
     fi
 
     if is_symlink "$local_mode" || is_symlink "$remote_mode"; then
-       echo "Symlink merge conflict for $path:"
+       echo "Symbolic link merge conflict for '$path':"
        describe_file "$local_mode" "local" "$LOCAL"
        describe_file "$remote_mode" "remote" "$REMOTE"
        resolve_symlink_merge
        return
     fi
 
-    echo "Normal merge conflict for $path:"
+    echo "Normal merge conflict for '$path':"
     describe_file "$local_mode" "local" "$LOCAL"
     describe_file "$remote_mode" "remote" "$REMOTE"
     printf "Hit return to start merge resolution tool (%s): " "$merge_tool"
@@ -188,10 +192,10 @@ merge_file () {
     case "$merge_tool" in
        kdiff3)
            if base_present ; then
-               (kdiff3 --auto --L1 "$path (Base)" -L2 "$path (Local)" --L3 "$path (Remote)" \
+               (kdiff3 --auto --L1 "$path (Base)" --L2 "$path (Local)" --L3 "$path (Remote)" \
                    -o "$path" -- "$BASE" "$LOCAL" "$REMOTE" > /dev/null 2>&1)
            else
-               (kdiff3 --auto -L1 "$path (Local)" --L2 "$path (Remote)" \
+               (kdiff3 --auto --L1 "$path (Local)" --L2 "$path (Remote)" \
                    -o "$path" -- "$LOCAL" "$REMOTE" > /dev/null 2>&1)
            fi
            status=$?
@@ -212,6 +216,12 @@ merge_file () {
            check_unchanged
            save_backup
            ;;
+       gvimdiff)
+               touch "$BACKUP"
+               gvimdiff -f -- "$LOCAL" "$path" "$REMOTE"
+               check_unchanged
+               save_backup
+               ;;
        xxdiff)
            touch "$BACKUP"
            if base_present ; then
@@ -230,11 +240,21 @@ merge_file () {
            check_unchanged
            save_backup
            ;;
+       opendiff)
+           touch "$BACKUP"
+           if base_present; then
+               opendiff "$LOCAL" "$REMOTE" -ancestor "$BASE" -merge "$path" | cat
+           else
+               opendiff "$LOCAL" "$REMOTE" -merge "$path" | cat
+           fi
+           check_unchanged
+           save_backup
+           ;;
        emerge)
            if base_present ; then
-               emacs -f emerge-files-with-ancestor-command "$LOCAL" "$REMOTE" "$BASE" "$path"
+               emacs -f emerge-files-with-ancestor-command "$LOCAL" "$REMOTE" "$BASE" "$(basename "$path")"
            else
-               emacs -f emerge-files-command "$LOCAL" "$REMOTE" "$path"
+               emacs -f emerge-files-command "$LOCAL" "$REMOTE" "$(basename "$path")"
            fi
            status=$?
            save_backup
@@ -249,7 +269,7 @@ merge_file () {
     cleanup_temp_files
 }
 
-while case $# in 0) break ;; esac
+while test $# != 0
 do
     case "$1" in
        -t|--tool*)
@@ -278,9 +298,9 @@ do
 done
 
 if test -z "$merge_tool"; then
-    merge_tool=`git-config merge.tool`
+    merge_tool=`git config merge.tool`
     case "$merge_tool" in
-       kdiff3 | tkdiff | xxdiff | meld | emerge | vimdiff)
+       kdiff3 | tkdiff | xxdiff | meld | opendiff | emerge | vimdiff | gvimdiff | "")
            ;; # happy
        *)
            echo >&2 "git config option merge.tool set to unknown tool: $merge_tool"
@@ -291,26 +311,42 @@ if test -z "$merge_tool"; then
 fi
 
 if test -z "$merge_tool" ; then
-    if type kdiff3 >/dev/null 2>&1 && test -n "$DISPLAY"; then
-       merge_tool="kdiff3";
-    elif type tkdiff >/dev/null 2>&1 && test -n "$DISPLAY"; then
-       merge_tool=tkdiff
-    elif type xxdiff >/dev/null 2>&1 && test -n "$DISPLAY"; then
-       merge_tool=xxdiff
-    elif type meld >/dev/null 2>&1 && test -n "$DISPLAY"; 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
+    if test -n "$DISPLAY"; then
+        merge_tool_candidates="kdiff3 tkdiff xxdiff meld gvimdiff"
+        if test -n "$GNOME_DESKTOP_SESSION_ID" ; then
+            merge_tool_candidates="meld $merge_tool_candidates"
+        fi
+        if test "$KDE_FULL_SESSION" = "true"; then
+            merge_tool_candidates="kdiff3 $merge_tool_candidates"
+        fi
+    fi
+    if echo "${VISUAL:-$EDITOR}" | grep 'emacs' > /dev/null 2>&1; then
+        merge_tool_candidates="$merge_tool_candidates emerge"
+    fi
+    if echo "${VISUAL:-$EDITOR}" | grep 'vim' > /dev/null 2>&1; then
+        merge_tool_candidates="$merge_tool_candidates vimdiff"
+    fi
+    merge_tool_candidates="$merge_tool_candidates opendiff emerge vimdiff"
+    echo "merge tool candidates: $merge_tool_candidates"
+    for i in $merge_tool_candidates; do
+        if test $i = emerge ; then
+            cmd=emacs
+        else
+            cmd=$i
+        fi
+        if type $cmd > /dev/null 2>&1; then
+            merge_tool=$i
+            break
+        fi
+    done
+    if test -z "$merge_tool" ; then
        echo "No available merge resolution programs available."
        exit 1
     fi
 fi
 
 case "$merge_tool" in
-    kdiff3|tkdiff|meld|xxdiff|vimdiff)
+    kdiff3|tkdiff|meld|xxdiff|vimdiff|gvimdiff|opendiff)
        if ! type "$merge_tool" > /dev/null 2>&1; then
            echo "The merge tool $merge_tool is not available"
            exit 1