aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--diff.c20
-rwxr-xr-xgit-apply-patch-script75
2 files changed, 55 insertions, 40 deletions
diff --git a/diff.c b/diff.c
index a4d2b2d72..4a54688cb 100644
--- a/diff.c
+++ b/diff.c
@@ -83,7 +83,7 @@ static void builtin_diff(const char *name,
{
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 @@ void run_external_diff(const char *name,
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();
}
diff --git a/git-apply-patch-script b/git-apply-patch-script
index c28015aad..29548ba6a 100755
--- a/git-apply-patch-script
+++ b/git-apply-patch-script
@@ -19,40 +19,51 @@ then
echo >&2 "Unresolved patch conflicts in the previous run found."
exit 1
fi
-# This will say "patching ..." so we do not say anything outselves.
-diff -u -L "a/$name" -L "b/$name" "$tmp1" "$tmp2" | patch -p1
-test -f "$name.rej" || {
- case "$mode1,$mode2" in
- .,?x)
- # newly created
- case "$mode2" in
- +x)
- echo >&2 "created $name with mode +x."
- chmod "$mode2" "$name"
- ;;
- -x)
- echo >&2 "created $name."
- ;;
- esac
- git-update-cache --add -- "$name"
+case "$mode1,$mode2" in
+.,?x)
+ # newly created
+ dir=$(dirname "$name")
+ case "$dir" in '' | .) ;; *) mkdir -p "$dir" esac || {
+ echo >&2 "cannot create leading path for $name."
+ exit 1
+ }
+ case "$mode2" in
+ +x)
+ echo >&2 "created $name with mode +x."
+ chmod "$mode2" "$name"
;;
- ?x,.)
- # deleted
- echo >&2 "deleted $name."
- rm -f "$name"
- git-update-cache --remove -- "$name"
+ -x)
+ echo >&2 "created $name."
;;
+ esac
+ git-update-cache --add -- "$name"
+ ;;
+?x,.)
+ # deleted
+ echo >&2 "deleted $name."
+ rm -f "$name" || {
+ echo >&2 "cannot remove $name";
+ exit 1
+ }
+ git-update-cache --remove -- "$name"
+ ;;
+*)
+ # changed
+ dir=$(dirname "$name")
+ case "$dir" in '' | .) ;; *) mkdir -p "$dir" esac || {
+ echo >&2 "cannot create leading path for $name."
+ exit 1
+ }
+ # This will say "patching ..." so we do not say anything outselves.
+ diff -u -L "a/$name" -L "b/$name" "$tmp1" "$tmp2" | patch -p1 || exit
+
+ case "$mode1,$mode2" in
+ "$mode2,$mode1") ;;
*)
- # changed
- case "$mode1,$mode2" in
- "$mode2,$mode1") ;;
- *)
- echo >&2 "changing mode from $mode1 to $mode2."
- chmod "$mode2" "$name"
- ;;
- esac
- git-update-cache -- "$name"
+ echo >&2 "changing mode from $mode1 to $mode2."
+ chmod "$mode2" "$name"
+ ;;
esac
-}
-exit 0
+ git-update-cache -- "$name"
+esac