[PATCH] patch: fuzz more aggressively to match patch(1) behaviour
Patrick Mezard
patrick at mezard.eu
Mon Feb 13 16:28:06 UTC 2012
# HG changeset patch
# User Patrick Mezard <patrick at mezard.eu>
# Date 1329150155 -3600
# Branch stable
# Node ID 4826fe61e876583aab4675e89bafa10b0c64f469
# Parent 3a4855a08072bd2ca2b3ed8a60fad0c21488f1f7
patch: fuzz more aggressively to match patch(1) behaviour
The previous code was assuming a default context of 3 lines. When fuzzing, it
would take this value in account to reduce the amount of removed line from
hunks top or bottom. For instance, if a hunk has only 2 lines of bottom
context, fuzzing with fuzz=1 would do nothing and with fuzz=2 it would remove
one of those lines. A hunk with one line of bottom context could not be fuzzed
at all. patch(1) has apparently no such restrictions and takes the fuzz level
at face value.
- test-import.t: fuzz/offset changes at the beginning of file are explained by
the new fuzzing behaviour and match patch(1) ones. Patching locations are
different but those of my patch(1) do not make a lot of sense right now
(patched output are the same)
- test-import-bypass.t: more agressive fuzzing makes a patching supposed to
fail because of context, succeed. Change the diff to avoid this.
- test-mq-merge.t: more agressive fuzzing would allow the merged patch to apply
with fuzz, but fortunately we disallow this behaviour. The new output is
kept.
I have not enough experience with patch(1) fuzzing to know whether aligning our
implementation on it is a good or bad idea. Until now, it has been the
implementation reference. For instance, "qpush" tolerates fuzz (test-mq-merge.t
runs the special case of pushing merge revisions where fuzzing is forbidden).
diff --git a/mercurial/patch.py b/mercurial/patch.py
--- a/mercurial/patch.py
+++ b/mercurial/patch.py
@@ -967,7 +967,7 @@
# this removes context lines from the top and bottom of list 'l'. It
# checks the hunk to make sure only context lines are removed, and then
# returns a new shortened list of lines.
- fuzz = min(fuzz, len(old)-1)
+ fuzz = min(fuzz, len(old))
if fuzz:
top = 0
bot = 0
@@ -985,18 +985,8 @@
else:
break
- # top and bot now count context in the hunk
- # adjust them if either one is short
- context = max(top, bot, 3)
- if bot < context:
- bot = max(0, fuzz - (context - bot))
- else:
- bot = min(fuzz, bot)
- if top < context:
- top = max(0, fuzz - (context - top))
- else:
- top = min(fuzz, top)
-
+ bot = min(fuzz, bot)
+ top = min(fuzz, top)
return old[top:len(old)-bot], new[top:len(new)-bot], top
return old, new, 0
diff --git a/tests/test-import-bypass.t b/tests/test-import-bypass.t
--- a/tests/test-import-bypass.t
+++ b/tests/test-import-bypass.t
@@ -111,7 +111,15 @@
Test commit editor
- $ hg diff -c 1 > ../test.diff
+ $ cat > ../test.diff <<EOF
+ > diff -r 07f494440405 -r 4e322f7ce8e3 a
+ > --- a/a Thu Jan 01 00:00:00 1970 +0000
+ > +++ b/a Thu Jan 01 00:00:00 1970 +0000
+ > @@ -1,1 +1,2 @@
+ > -a
+ > +b
+ > +c
+ > EOF
$ HGEDITOR=cat hg import --bypass ../test.diff
applying ../test.diff
@@ -138,7 +146,7 @@
$ hg --config patch.eol=auto import -d '0 0' -m 'test patch.eol' --bypass ../test.diff
applying ../test.diff
$ shortlog
- o 3:d7805b4d2cb3 test 0 0 - default - test patch.eol
+ o 3:c606edafba99 test 0 0 - default - test patch.eol
|
@ 2:872023de769d test 0 0 - default - makeacrlf
|
diff --git a/tests/test-import.t b/tests/test-import.t
--- a/tests/test-import.t
+++ b/tests/test-import.t
@@ -445,7 +445,7 @@
$ hg import --no-commit -v fuzzy-tip.patch
applying fuzzy-tip.patch
patching file a
- Hunk #1 succeeded at 1 with fuzz 2 (offset -2 lines).
+ Hunk #1 succeeded at 2 with fuzz 1 (offset 0 lines).
applied to working directory
$ hg revert -a
reverting a
@@ -462,7 +462,7 @@
$ hg --config patch.eol=auto import --no-commit -v fuzzy-tip.patch
applying fuzzy-tip.patch
patching file a
- Hunk #1 succeeded at 1 with fuzz 2 (offset -2 lines).
+ Hunk #1 succeeded at 2 with fuzz 1 (offset 0 lines).
applied to working directory
$ cd ..
@@ -1031,6 +1031,19 @@
> +line
> EOF
+ $ cat > 04-middle-of-file-completely-fuzzed.diff <<EOF
+ > diff --git a/a b/a
+ > --- a/a
+ > +++ b/a
+ > @@ -1,1 +1,1 @@
+ > -2
+ > +add some skew
+ > @@ -2,2 +2,3 @@
+ > not matching, should fuzz
+ > ... a bit
+ > +line
+ > EOF
+
$ cat > a <<EOF
> 1
> 2
@@ -1073,4 +1086,14 @@
3
4
line
+ applying 04-middle-of-file-completely-fuzzed.diff
+ patching file a
+ Hunk #1 succeeded at 2 (offset 1 lines).
+ Hunk #2 succeeded at 5 with fuzz 2 (offset 1 lines).
+ applied to working directory
+ 1
+ add some skew
+ 3
+ 4
+ line
diff --git a/tests/test-mq-merge.t b/tests/test-mq-merge.t
--- a/tests/test-mq-merge.t
+++ b/tests/test-mq-merge.t
@@ -125,12 +125,10 @@
merging with queue at: $TESTTMP/t2/.hg/refqueue (glob)
applying patcha
patching file a
- Hunk #1 FAILED at 0
- 1 out of 1 hunks FAILED -- saving rejects to file a.rej
- patch failed, unable to continue (try -v)
- patch failed, rejects left in working dir
+ Hunk #1 succeeded at 2 with fuzz 1 (offset 0 lines).
+ fuzz found when applying patch, stopping
patch didn't work out, merging patcha
- 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+ 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
0 files updated, 2 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)
applying patcha2
More information about the Mercurial-devel
mailing list