Add write_or_die(), a helper function
[gitweb.git] / git-am.sh
index 25c95c24fde6894544f4b53439abd030008e757f..d0af786aec3f797943290cdc63fa77f393900160 100755 (executable)
--- a/git-am.sh
+++ b/git-am.sh
@@ -45,6 +45,12 @@ go_next () {
        this=$next
 }
 
+cannot_fallback () {
+       echo "$1"
+       echo "Cannot fall back to three-way merge."
+       exit 1
+}
+
 fall_back_3way () {
     O_OBJECT=`cd "$GIT_OBJECT_DIRECTORY" && pwd`
 
@@ -52,53 +58,23 @@ fall_back_3way () {
     mkdir "$dotest/patch-merge-tmp-dir"
 
     # First see if the patch records the index info that we can use.
-    if git-apply -z --index-info "$dotest/patch" \
-       >"$dotest/patch-merge-index-info" 2>/dev/null &&
-       GIT_INDEX_FILE="$dotest/patch-merge-tmp-index" \
-       git-update-index -z --index-info <"$dotest/patch-merge-index-info" &&
-       GIT_INDEX_FILE="$dotest/patch-merge-tmp-index" \
-       git-write-tree >"$dotest/patch-merge-base+" &&
-       # index has the base tree now.
-       (
-           cd "$dotest/patch-merge-tmp-dir" &&
-           GIT_INDEX_FILE="../patch-merge-tmp-index" \
-           GIT_OBJECT_DIRECTORY="$O_OBJECT" \
-           git-apply $binary --index <../patch
-        )
+    git-apply -z --index-info "$dotest/patch" \
+       >"$dotest/patch-merge-index-info" &&
+    GIT_INDEX_FILE="$dotest/patch-merge-tmp-index" \
+    git-update-index -z --index-info <"$dotest/patch-merge-index-info" &&
+    GIT_INDEX_FILE="$dotest/patch-merge-tmp-index" \
+    git-write-tree >"$dotest/patch-merge-base+" ||
+    cannot_fallback "Patch does not record usable index information."
+
+    echo Using index info to reconstruct a base tree...
+    if GIT_INDEX_FILE="$dotest/patch-merge-tmp-index" \
+       git-apply $binary --cached <"$dotest/patch"
     then
-       echo Using index info to reconstruct a base tree...
        mv "$dotest/patch-merge-base+" "$dotest/patch-merge-base"
        mv "$dotest/patch-merge-tmp-index" "$dotest/patch-merge-index"
     else
-       # Otherwise, try nearby trees that can be used to apply the
-       # patch.
-       (
-           N=10
-
-           # Hoping the patch is against our recent commits...
-           git-rev-list --max-count=$N HEAD
-
-           # or hoping the patch is against known tags...
-           git-ls-remote --tags .
-       ) |
-       while read base junk
-       do
-           # See if we have it as a tree...
-           git-cat-file tree "$base" >/dev/null 2>&1 || continue
-
-           rm -fr "$dotest"/patch-merge-* &&
-           mkdir "$dotest/patch-merge-tmp-dir" || break
-           (
-               cd "$dotest/patch-merge-tmp-dir" &&
-               GIT_INDEX_FILE=../patch-merge-tmp-index &&
-               GIT_OBJECT_DIRECTORY="$O_OBJECT" &&
-               export GIT_INDEX_FILE GIT_OBJECT_DIRECTORY &&
-               git-read-tree "$base" &&
-               git-apply $binary --index &&
-               mv ../patch-merge-tmp-index ../patch-merge-index &&
-               echo "$base" >../patch-merge-base
-           ) <"$dotest/patch"  2>/dev/null && break
-       done
+        cannot_fallback "Did you hand edit your patch?
+It does not apply to blobs recorded in its index."
     fi
 
     test -f "$dotest/patch-merge-index" &&
@@ -111,7 +87,7 @@ fall_back_3way () {
     # This is not so wrong.  Depending on which base we picked,
     # orig_tree may be wildly different from ours, but his_tree
     # has the same set of wildly different changes in parts the
-    # patch did not touch, so resolve ends up cancelling them,
+    # patch did not touch, so resolve ends up canceling them,
     # saying that we reverted all those changes.
 
     git-merge-resolve $orig_tree -- HEAD $his_tree || {
@@ -125,13 +101,14 @@ fall_back_3way () {
 }
 
 prec=4
+rloga=am
 dotest=.dotest sign= utf8= keep= skip= interactive= resolved= binary= ws= resolvemsg=
 
 while case "$#" in 0) break;; esac
 do
        case "$1" in
        -d=*|--d=*|--do=*|--dot=*|--dote=*|--dotes=*|--dotest=*)
-       dotest=`expr "$1" : '-[^=]*=\(.*\)'`; shift ;;
+       dotest=`expr "z$1" : 'z-[^=]*=\(.*\)'`; shift ;;
        -d|--d|--do|--dot|--dote|--dotes|--dotest)
        case "$#" in 1) usage ;; esac; shift
        dotest="$1"; shift;;
@@ -164,6 +141,9 @@ do
        --resolvemsg=*)
        resolvemsg=$(echo "$1" | sed -e "s/^--resolvemsg=//"); shift ;;
 
+       --reflog-action=*)
+       rloga=`expr "z$1" : 'z-[^=]*=\(.*\)'`; shift ;;
+
        --)
        shift; break ;;
        -*)
@@ -186,8 +166,10 @@ fi
 
 if test -d "$dotest"
 then
-       test ",$#," = ",0," ||
-       die "previous dotest directory $dotest still exists but mbox given."
+       if test ",$#," != ",0," || ! tty -s
+       then
+               die "previous dotest directory $dotest still exists but mbox given."
+       fi
        resume=yes
 else
        # Make sure we are not given --skip nor --resolved
@@ -447,7 +429,7 @@ do
        parent=$(git-rev-parse --verify HEAD) &&
        commit=$(git-commit-tree $tree -p $parent <"$dotest/final-commit") &&
        echo Committed: $commit &&
-       git-update-ref -m "am: $SUBJECT" HEAD $commit $parent ||
+       git-update-ref -m "$rloga: $SUBJECT" HEAD $commit $parent ||
        stop_here $this
 
        if test -x "$GIT_DIR"/hooks/post-applypatch