Terminate diff-* on non-zero exit from GIT_EXTERNAL_DIFF

(slightly updated from the version posted to the GIT mailing list
with small bugfixes).

This patch changes the git-apply-patch-script to exit non-zero when
the patch cannot be applied.  Previously, the external diff driver
deliberately ignored the exit status of GIT_EXTERNAL_DIFF command,
which was a design mistake.  It now stops the processing when
GIT_EXTERNAL_DIFF exits non-zero, so the damages from running
git-diff-* with git-apply-patch-script between two wrong trees can be
contained.

The "diff" command line generated by the built-in driver is changed to
always exit 0 in order to match this new behaviour.  I know Pasky does
not use GIT_EXTERNAL_DIFF yet, so this change should not break Cogito,
either.

Signed-off-by: Junio C Hamano <junkio@cox.net>
diff --git a/diff.c b/diff.c
index a4d2b2d..4a54688 100644
--- a/diff.c
+++ b/diff.c
@@ -83,7 +83,7 @@
 {
 	int i, next_at;
 	const char *diff_cmd = "diff -L'%s%s' -L'%s%s'";
-	const char *diff_arg  = "'%s' '%s'";
+	const char *diff_arg  = "'%s' '%s'||:"; /* "||:" is to return 0 */
 	const char *input_name_sq[2];
 	const char *path0[2];
 	const char *path1[2];
@@ -261,16 +261,20 @@
 			printf("* Unmerged path %s\n", name);
 		exit(0);
 	}
-	if (waitpid(pid, &status, 0) < 0 || !WIFEXITED(status)) {
-		/* We do not check the exit status because typically
+	if (waitpid(pid, &status, 0) < 0 ||
+	    !WIFEXITED(status) || WEXITSTATUS(status)) {
+		/* Earlier we did not check the exit status because
 		 * diff exits non-zero if files are different, and
-		 * we are not interested in knowing that.  We *knew*
-		 * they are different and that's why we ran diff
-		 * in the first place!  However if it dies by a signal,
-		 * we stop processing immediately.
+		 * we are not interested in knowing that.  It was a
+		 * mistake which made it harder to quit a diff-*
+		 * session that uses the git-apply-patch-script as
+		 * the GIT_EXTERNAL_DIFF.  A custom GIT_EXTERNAL_DIFF
+		 * should also exit non-zero only when it wants to
+		 * abort the entire diff-* session.
 		 */
 		remove_tempfile();
-		die("external diff died unexpectedly.\n");
+		fprintf(stderr, "external diff died, stopping at %s.\n", name);
+		exit(1);
 	}
 	remove_tempfile();
 }