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).
This commit is contained in:
Patrick Mezard 2012-02-13 17:22:35 +01:00
parent 39da9af001
commit 20e5c736c0
4 changed files with 41 additions and 22 deletions

View File

@ -973,7 +973,7 @@ class hunk(object):
# 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
@ -991,18 +991,8 @@ class hunk(object):
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

View File

@ -111,7 +111,15 @@ Test unsupported combinations
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 @@ Test patch.eol is handled
$ 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
|

View File

@ -445,7 +445,7 @@ Test fuzziness (ambiguous patch location, fuzz=2)
$ 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 @@ test fuzziness with eol=auto
$ 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 ..
@ -1029,6 +1029,19 @@ Test corner case involving fuzz and skew
> +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
@ -1071,4 +1084,14 @@ Test corner case involving fuzz and skew
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

View File

@ -125,12 +125,10 @@ Merge:
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