summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Gruenbacher <agruen@linbit.com>2012-08-08 00:23:18 +0200
committerAndreas Gruenbacher <agruen@linbit.com>2012-08-08 13:39:08 +0200
commita18960d31e798d3424b81581a88a6934b4a45d2f (patch)
tree67cba22ee5e98213ff248d68b034defe116202bb
parente294241b865ed2262ba84ebfc0ac982cdf33c479 (diff)
downloadpatch-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.c48
-rw-r--r--tests/concat-git-diff24
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