summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Gruenbacher <agruen@linbit.com>2012-08-02 15:50:49 +0200
committerAndreas Gruenbacher <agruen@linbit.com>2012-08-02 20:38:31 +0200
commit1e6c0d07abe8833bbb3bc493ed0f969b84d7bf25 (patch)
treeb2b7219e2e4d1803d16fbde8d348e56aecd557d0
parentcdc94fade38f2b745894c7b724512af506dc803c (diff)
downloadpatch-1e6c0d07abe8833bbb3bc493ed0f969b84d7bf25.tar.gz
In git-style diffs, create new files immediatetly and only remember files to modify
* src/patch.c (output_file): Create new files immediately. Document why things are implemented that way. * tests/concat-git-diff: Fix glitch in test case.
-rw-r--r--src/patch.c28
-rw-r--r--tests/concat-git-diff1
2 files changed, 26 insertions, 3 deletions
diff --git a/src/patch.c b/src/patch.c
index 2d6443a..082127b 100644
--- a/src/patch.c
+++ b/src/patch.c
@@ -1786,9 +1786,31 @@ output_file (char const *from, int *from_needs_removal,
const struct stat *to_st, mode_t mode, bool backup)
{
if (from == NULL)
- delete_file_later (to, to_st, backup);
- else if (pch_git_diff())
- output_file_later (from, from_needs_removal, from_st, to, mode, backup);
+ {
+ /* Remember which files should be deleted and only delete them when the
+ entire input to patch has been processed. This allows to correctly
+ determine for which files backup files have already been created. */
+
+ delete_file_later (to, to_st, backup);
+ }
+ else if (pch_git_diff () && pch_says_nonexistent (reverse) != 2)
+ {
+ /* In git-style diffs, the "before" state of each patch refers to the initial
+ state before modifying any files, input files can be referenced more than
+ once (when creating copies), and output files are modified at most once.
+ However, the input to GNU patch may consist of multiple concatenated
+ git-style diffs, which must be processed separately. (The same output
+ file may go through multiple revisions.)
+
+ To implement this, we remember which files to /modify/ instead of
+ modifying the files immediately, but we create /new/ output files
+ immediately. The new output files serve as markers to detect when a
+ file is modified more than once; this allows to recognize most
+ concatenated git-style diffs.
+ */
+
+ output_file_later (from, from_needs_removal, from_st, to, mode, backup);
+ }
else
output_file_now (from, from_needs_removal, from_st, to, mode, backup);
}
diff --git a/tests/concat-git-diff b/tests/concat-git-diff
index a6f1539..445fd97 100644
--- a/tests/concat-git-diff
+++ b/tests/concat-git-diff
@@ -39,6 +39,7 @@ EOF
check 'patch -p1 < concatenated.diff || echo "Status: $?"' <<EOF
patching file f
patching file f
+patching file f
EOF
check 'cat f' <<EOF