[PATCH] patch: fuzz more aggressively to match patch(1) behaviour

Matt Mackall mpm at selenic.com
Thu Feb 16 14:45:59 CST 2012


On Mon, 2012-02-13 at 17:28 +0100, Patrick Mezard wrote:
> # 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

Very nice, these are queued for stable.

> 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
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel at selenic.com
> http://selenic.com/mailman/listinfo/mercurial-devel


-- 
Mathematics is the supreme nostalgia of our time.




More information about the Mercurial-devel mailing list