Mercurial > public > mercurial-scm > hg-stable
comparison mercurial/patch.py @ 16124:0e0060bf2f44 stable
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).
author | Patrick Mezard <patrick@mezard.eu> |
---|---|
date | Mon, 13 Feb 2012 17:22:35 +0100 |
parents | b0c7525f826d |
children | d23197e08d05 |
comparison
equal
deleted
inserted
replaced
16123:b0c7525f826d | 16124:0e0060bf2f44 |
---|---|
971 | 971 |
972 def _fuzzit(self, old, new, fuzz, toponly): | 972 def _fuzzit(self, old, new, fuzz, toponly): |
973 # this removes context lines from the top and bottom of list 'l'. It | 973 # this removes context lines from the top and bottom of list 'l'. It |
974 # checks the hunk to make sure only context lines are removed, and then | 974 # checks the hunk to make sure only context lines are removed, and then |
975 # returns a new shortened list of lines. | 975 # returns a new shortened list of lines. |
976 fuzz = min(fuzz, len(old)-1) | 976 fuzz = min(fuzz, len(old)) |
977 if fuzz: | 977 if fuzz: |
978 top = 0 | 978 top = 0 |
979 bot = 0 | 979 bot = 0 |
980 hlen = len(self.hunk) | 980 hlen = len(self.hunk) |
981 for x in xrange(hlen - 1): | 981 for x in xrange(hlen - 1): |
989 if self.hunk[hlen - bot - 1][0] == ' ': | 989 if self.hunk[hlen - bot - 1][0] == ' ': |
990 bot += 1 | 990 bot += 1 |
991 else: | 991 else: |
992 break | 992 break |
993 | 993 |
994 # top and bot now count context in the hunk | 994 bot = min(fuzz, bot) |
995 # adjust them if either one is short | 995 top = min(fuzz, top) |
996 context = max(top, bot, 3) | |
997 if bot < context: | |
998 bot = max(0, fuzz - (context - bot)) | |
999 else: | |
1000 bot = min(fuzz, bot) | |
1001 if top < context: | |
1002 top = max(0, fuzz - (context - top)) | |
1003 else: | |
1004 top = min(fuzz, top) | |
1005 | |
1006 return old[top:len(old)-bot], new[top:len(new)-bot], top | 996 return old[top:len(old)-bot], new[top:len(new)-bot], top |
1007 return old, new, 0 | 997 return old, new, 0 |
1008 | 998 |
1009 def fuzzit(self, fuzz, toponly): | 999 def fuzzit(self, fuzz, toponly): |
1010 old, new, top = self._fuzzit(self.a, self.b, fuzz, toponly) | 1000 old, new, top = self._fuzzit(self.a, self.b, fuzz, toponly) |