[PATCH] patch: fuzz more aggressively to match patch(1) behaviour
Matt Mackall
mpm at selenic.com
Thu Feb 16 20:45:59 UTC 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