1
0
mirror of https://github.com/git/git synced 2024-07-05 00:58:49 +00:00

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>
This commit is contained in:
Junio C Hamano 2005-05-04 01:38:06 -07:00
parent ae7c0c92c0
commit 6fa28064b0
2 changed files with 56 additions and 41 deletions

20
diff.c
View File

@ -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();
}

View File

@ -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."
;;
*)
# changed
case "$mode1,$mode2" in
"$mode2,$mode1") ;;
*)
echo >&2 "changing mode from $mode1 to $mode2."
chmod "$mode2" "$name"
;;
esac
git-update-cache -- "$name"
esac
}
exit 0
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") ;;
*)
echo >&2 "changing mode from $mode1 to $mode2."
chmod "$mode2" "$name"
;;
esac
git-update-cache -- "$name"
esac