From 66fdcf0e7c83a1e2eb4db97b9e24f224db656b65 Mon Sep 17 00:00:00 2001 From: Andreas Gruenbacher Date: Tue, 19 Jul 2016 22:40:40 +0200 Subject: Fix broken git-style patch behavior When a git-syle patch is applied, all file modifications are done to temporary files which are put in place when the patch ends. When a patch fails, GNU patch was trying to "roll back" to the start. A bug in that code that lead to accidental file deletion was recently discovered by Richard Weinberger . Even worse though, GNU patch should not exhibit this "rollback" behavior in the first place; that's not what people expect. Instead, the files modified so far should be put in place. * src/patch.c (cleanup): Put output files processed successfully in place instead of trying to "roll back" to the start. (forget_output_files): Remove obsolete (and broken) function. * tests/git-cleanup: New broken git-style patch test case that exercises the cleanup path. * tests/Makefile.am (TESTS): Add new test case. --- src/patch.c | 18 +------------ tests/Makefile.am | 1 + tests/git-cleanup | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 77 insertions(+), 17 deletions(-) create mode 100644 tests/git-cleanup diff --git a/src/patch.c b/src/patch.c index b0ed91a..bf7e5c2 100644 --- a/src/patch.c +++ b/src/patch.c @@ -1966,22 +1966,6 @@ output_files (struct stat const *st) gl_list_clear (files_to_output); } -static void -forget_output_files (void) -{ - gl_list_iterator_t iter = gl_list_iterator (files_to_output); - const void *elt; - - while (gl_list_iterator_next (&iter, &elt, NULL)) - { - const struct file_to_output *file_to_output = elt; - - safe_unlink (file_to_output->from); - } - gl_list_iterator_free (&iter); - gl_list_clear (files_to_output); -} - /* Fatal exit with cleanup. */ void @@ -2012,5 +1996,5 @@ cleanup (void) remove_if_needed (TMPOUTNAME, &TMPOUTNAME_needs_removal); remove_if_needed (TMPPATNAME, &TMPPATNAME_needs_removal); remove_if_needed (TMPREJNAME, &TMPREJNAME_needs_removal); - forget_output_files (); + output_files (NULL); } diff --git a/tests/Makefile.am b/tests/Makefile.am index 6d167bd..61a4ab8 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -36,6 +36,7 @@ TESTS = \ file-modes \ filename-choice \ git-binary-diff \ + git-cleanup \ garbage \ global-reject-files \ inname \ diff --git a/tests/git-cleanup b/tests/git-cleanup new file mode 100644 index 0000000..a71be97 --- /dev/null +++ b/tests/git-cleanup @@ -0,0 +1,75 @@ +# Copyright (C) 2009, 2011-2016 Free Software Foundation, Inc. +# +# Copying and distribution of this file, with or without modification, +# in any medium, are permitted without royalty provided the copyright +# notice and this notice are preserved. + +. $srcdir/test-lib.sh + +require cat +use_local_patch +use_tmpdir + +# ============================================================== + +cat > 1.diff < f +echo -n '' > g +echo -n '' > h + +check 'patch -f -i 1.diff || echo status: $?' <