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)