Subject: [PATCH] rebase: Handle cases where format-patch fails

From: Andrew Wong <[email-masked]>
Date: Wed, 10 Oct 2012 23:54:03 -0400

'format-patch' could fail due to reasons such as out of memory. Such
failures are not detected or handled, which causes rebase to incorrectly
think that it completed successfully and continue with cleanup. i.e.
calling move_to_original_branch

Instead of using a pipe, we separate 'format-patch' and 'am' by using an
intermediate file. This gurantees that we can invoke 'am' with the
complete input, or not invoking 'am' at all if 'format-patch' failed.

Also remove the use of '&&' at the end of the if-block, and rearrange
the 'write_basic_state' and 'move_to_original_branch' to make the logic
flow a bit better and easier to read.

Signed-off-by: Andrew Wong <[email-masked]>
---
 git-rebase--am.sh | 51 +++++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 45 insertions(+), 6 deletions(-)

diff --git a/git-rebase--am.sh b/git-rebase--am.sh
index 392ebc9..85b594e 100644
--- a/git-rebase--am.sh
+++ b/git-rebase--am.sh
@@ -18,6 +18,7 @@ esac
 
 test -n "$rebase_root" && root_flag=--root
 
+ret=0
 if test -n "$keep_empty"
 then
 	# we have to do this the hard way.  git format-patch completely squashes
@@ -25,13 +26,51 @@ then
 	# itself well to recording empty patches.  fortunately, cherry-pick
 	# makes this easy
 	git cherry-pick --allow-empty "$revisions"
+	ret=$?
 else
+	rm -f "$GIT_DIR/format-patch"
+
 	git format-patch -k --stdout --full-index --ignore-if-in-upstream \
 		--src-prefix=a/ --dst-prefix=b/ \
-		--no-renames $root_flag "$revisions" |
-	git am $git_am_opt --rebasing --resolvemsg="$resolvemsg"
-fi && move_to_original_branch
+		--no-renames $root_flag "$revisions" > "$GIT_DIR/format-patch"
+	ret=$?
+
+	if test 0 != $ret
+	then
+		rm -f "$GIT_DIR/format-patch"
+
+		case "$head_name" in
+		refs/heads/*)
+			git checkout -q "$head_name"
+			;;
+		*)
+			git checkout -q "$orig_head"
+			;;
+		esac
+
+		cat >&2 <<-EOF
+
+		git encountered an error while preparing the patches to replay
+		these revisions:
+
+		    $revisions
+
+		As a result, git cannot rebase these revisions.
+		EOF
+
+		exit $?
+	fi
+
+	git am $git_am_opt --rebasing --resolvemsg="$resolvemsg" < "$GIT_DIR/format-patch"
+	ret=$?
+
+	rm -f "$GIT_DIR/format-patch"
+fi
+
+if test 0 != $ret
+then
+	test -d "$state_dir" && write_basic_state
+	exit $ret
+fi
 
-ret=$?
-test 0 != $ret -a -d "$state_dir" && write_basic_state
-exit $ret
+move_to_original_branch
-- 
1.8.0.rc0.19.gc58a63a.dirty