diff options
author | Andreas Gruenbacher <agruen@linbit.com> | 2012-08-08 00:23:18 +0200 |
---|---|---|
committer | Andreas Gruenbacher <agruen@linbit.com> | 2012-08-08 13:39:08 +0200 |
commit | a18960d31e798d3424b81581a88a6934b4a45d2f (patch) | |
tree | 67cba22ee5e98213ff248d68b034defe116202bb | |
parent | e294241b865ed2262ba84ebfc0ac982cdf33c479 (diff) | |
download | patch-a18960d31e798d3424b81581a88a6934b4a45d2f.tar.gz |
Detect concatenated git-style patches by tracking what's in the output queue
* src/patch.c (main): Instead of looking at the SHA hashes to detect
concatenated git-style patches, detect when a file to write to is already in
the output queue.
* tests/concat-git-diff: Add create/delete tests.
-rw-r--r-- | src/patch.c | 48 | ||||
-rw-r--r-- | tests/concat-git-diff | 24 |
2 files changed, 46 insertions, 26 deletions
diff --git a/src/patch.c b/src/patch.c index 9dc71f2..febfd42 100644 --- a/src/patch.c +++ b/src/patch.c @@ -237,37 +237,47 @@ main (int argc, char **argv) outname = pch_name (! strcmp (inname, pch_name (OLD))); else outname = inname; - - if (! get_input_file (inname, outname, file_type)) - { - skip_rest_of_patch = true; - somefailed = true; - } } - if (pch_git_diff () && ! skip_rest_of_patch && ! inerrno) + if (pch_git_diff () && ! skip_rest_of_patch) { + struct stat outstat; + int outerrno = 0; + /* Try to recognize concatenated git diffs based on the SHA1 hashes in the headers. Will not always succeed for patches that rename or copy files. */ - char const *previous_sha1 = lookup_sha1 (&instat); - - if (previous_sha1) + if (! strcmp (inname, outname)) { - char const *sha1 = pch_sha1 (reverse); + if (inerrno == -1) + inerrno = lstat (inname, &instat) ? errno : 0; + outstat = instat; + outerrno = inerrno; + } + else + outerrno = lstat (outname, &outstat) ? errno : 0; - for (; *previous_sha1 && *sha1; previous_sha1++, sha1++) - if (*previous_sha1 != *sha1) - break; - if (*previous_sha1 && *sha1) + if (! outerrno) + { + if (has_queued_output (&outstat)) { - output_files (&instat); - update_sha1 (&instat, pch_sha1 (reverse)); + output_files (&outstat); + outerrno = lstat (outname, &outstat) ? errno : 0; + inerrno = -1; } + if (! outerrno) + set_queued_output (&outstat, true); + } + } + + if (! skip_rest_of_patch) + { + if (! get_input_file (inname, outname, file_type)) + { + skip_rest_of_patch = true; + somefailed = true; } - else - update_sha1 (&instat, pch_sha1 (reverse)); } if (read_only_behavior != RO_IGNORE diff --git a/tests/concat-git-diff b/tests/concat-git-diff index 52d3004..927eb5a 100644 --- a/tests/concat-git-diff +++ b/tests/concat-git-diff @@ -12,20 +12,29 @@ use_tmpdir # ============================================================== +echo zero > f + cat > concatenated.diff <<EOF diff --git a/f b/f -new file mode 100644 -index 0000000..5626abf ---- /dev/null +index 26af6a8..5626abf 100644 +--- a/f +++ b/f -@@ -0,0 +1 @@ +@@ -1 +1 @@ +-zero +one diff --git a/f b/f -index 5626abf..f719efd 100644 +deleted file mode 100644 +index 5626abf..0000000 --- a/f -+++ b/f -@@ -1 +1 @@ ++++ /dev/null +@@ -1 +0,0 @@ -one +diff --git a/f b/f +new file mode 100644 +index 0000000..f719efd +--- /dev/null ++++ b/f +@@ -0,0 +1 @@ +two diff --git a/f b/f index f719efd..2bdf67a 100644 @@ -40,6 +49,7 @@ check 'patch -p1 < concatenated.diff || echo "Status: $?"' <<EOF patching file f patching file f patching file f +patching file f EOF check 'cat f' <<EOF |