On Thursday 22 October 2009 23:06, Bernhard Reutner-Fischer wrote:
> Hi,
> 
> I was having trouble with our patch.
> 
> It didn't warn about previously applied hunks, like:
> $ dmesg | tail | tee mess > mess.orig
> $ echo new line >> mess
> $ diff -u mess.orig mess > xxx
> $ #NOT mv mess.orig mess
> $ patch -i xxx
> 
> There is -N to allow to skip them (complaining loud).

Well. I see that the patch fixes this case:

# tail -100 input.old input z.patch
==> input.old <==
abc
123

==> input <==
abc
123
456

==> z.patch <==
--- input.old   Sat Oct 24 16:32:56 2009
+++ input       Sat Oct 24 16:41:48 2009
@@ -1,2 +1,3 @@
 abc
 123
+456


Bare "patch <z.patch" would complain, "patch -N <z.patch" skips the hunk.

But on these inputs:

# tail -100 input.old input z.patch
==> input.old <==
abc
123

==> input <==
abc
def
123

==> z.patch <==
--- input       Sat Oct 24 16:32:56 2009
+++ input       Sat Oct 24 16:33:01 2009
@@ -1,2 +1,3 @@
 abc
+def
 123


"patch <z.patch" still happily patches "input" by adding another "123" line,
same with -N option.
This is a regression from unpatched version.

I am adding this case to the testsuite.

I looked at Rob's version in toybox but it does not support -N yet,
and also does not pass one of existing testsuite entries
(it may be able to patch with offsets and fuzz, but I did not test that).


> And we didn't have --dry-run.
> I've picked the short-option -z for --dry-run out of the blue to
> facilitate !getopt_long usage of patch.

Can we have just a long option? Otherwise:
(1) people start using -z
(2) they get bitten by incompatibility when they move
    their scripts to a system with GNU patch

> A few points though:
> - The size increase is absolutely intolerable.
>   (rephrase hunk handling)

It's only ~150 bytes, after "static char msg[]" is constified. :)

> - for --dry-run we should just not write anything to dst_stream
>   and get rid of any temporary file in due course.

like opening it to "/dev/null"?

> I currently don't have more time for patch, so it would be great if
> somebody steps up and either applies it as a fix in it's current state
> or look a bit into it before committing it.

Partially merged.

The diff containing unapplied part of the patch is attached.

--
vda
diff -d -urpN busybox.8/editors/patch.c busybox.9/editors/patch.c
--- busybox.8/editors/patch.c	2009-10-24 16:54:12.000000000 +0200
+++ busybox.9/editors/patch.c	2009-10-24 16:47:46.000000000 +0200
@@ -168,6 +168,7 @@ int patch_main(int argc UNUSED_PARAM, ch
 			unsigned hunk_offset_start;
 			unsigned src_last_line = 1;
 			unsigned dst_last_line = 1;
+			char *src_line = NULL;
 
 			if ((sscanf(patch_line, "@@ -%d,%d +%d,%d", &src_beg_line, &src_last_line, &dst_beg_line, &dst_last_line) < 3)
 			 && (sscanf(patch_line, "@@ -%d +%d,%d", &src_beg_line, &dst_beg_line, &dst_last_line) < 2)
@@ -215,32 +216,40 @@ int patch_main(int argc UNUSED_PARAM, ch
 				) {
 					break; /* End of hunk */
 				}
-				if (*patch_line != plus) { /* '-' or ' ' */
-					char *src_line = NULL;
-					if (src_cur_line == src_last_line)
-						break;
-					if (src_stream) {
-						src_line = xmalloc_fgets(src_stream);
-						if (src_line) {
+				if (src_stream && !src_line) {
+					src_line = xmalloc_fgets(src_stream);
+					if (src_line) {
+						src_cur_line++;
+						if (*patch_line != plus) {
 							int diff = strcmp(src_line, patch_line + 1);
-							src_cur_line++;
 							free(src_line);
 							if (diff)
 								src_line = NULL;
 						}
 					}
-					/* Do not patch an already patched hunk with -N */
-					if (src_line == 0 && (opt & OPT_N)) {
+				}
+				if (*patch_line != plus && !src_line) {
+					bb_error_msg("hunk #%u FAILED at %u",
+								 hunk_count, hunk_offset_start);
+ bad_hunk:
+					bad_hunk_count++;
+					break;
+				}
+				if (src_cur_line > src_last_line) {
+					static const char msg[] ALIGN1 =
+						"Reversed (or previously applied) "
+						"hunk #%u at %u detected!%s";
+					if (opt & OPT_N) {
+						bb_error_msg(msg, hunk_count, hunk_offset_start, " Skipping.");
 						continue;
 					}
-					if (!src_line) {
-						bb_error_msg("hunk #%u FAILED at %u", hunk_count, hunk_offset_start);
-						bad_hunk_count++;
-						break;
-					}
-					if (*patch_line != ' ') { /* '-' */
+					bb_error_msg(msg, hunk_count, hunk_offset_start, "");
+					goto bad_hunk;
+				}
+				if (*patch_line != plus) {
+					src_line = NULL;
+					if (*patch_line != ' ') /* '-' */
 						continue;
-					}
 				}
 				if (dst_cur_line == dst_last_line)
 					break;
_______________________________________________
busybox mailing list
[email protected]
http://lists.busybox.net/mailman/listinfo/busybox

Reply via email to