Mercurial > public > mercurial-scm > hg-stable
comparison mercurial/patch.py @ 16121:ccba74472af2 stable
patch: fuzz old and new lines at the same time
In theory, the fuzzed offsets for old and new lines should be exactly the same
as they are based on hunk parsing. Make it true in practice.
author | Patrick Mezard <patrick@mezard.eu> |
---|---|
date | Mon, 13 Feb 2012 13:21:00 +0100 |
parents | d7829b2ecf32 |
children | 9ef3a4a2c6c0 |
comparison
equal
deleted
inserted
replaced
16119:5de83d9ca79c | 16121:ccba74472af2 |
---|---|
726 # hunk data before patching. Otherwise, preserve input | 726 # hunk data before patching. Otherwise, preserve input |
727 # line-endings. | 727 # line-endings. |
728 h = h.getnormalized() | 728 h = h.getnormalized() |
729 | 729 |
730 # fast case first, no offsets, no fuzz | 730 # fast case first, no offsets, no fuzz |
731 old = h.old() | 731 old, new = h.fuzzit(0, False) |
732 start = h.starta + self.offset | 732 start = h.starta + self.offset |
733 # zero length hunk ranges already have their start decremented | 733 # zero length hunk ranges already have their start decremented |
734 if h.lena: | 734 if h.lena: |
735 start -= 1 | 735 start -= 1 |
736 orig_start = start | 736 orig_start = start |
739 # fast case code | 739 # fast case code |
740 if self.skew == 0 and diffhelpers.testhunk(old, self.lines, start) == 0: | 740 if self.skew == 0 and diffhelpers.testhunk(old, self.lines, start) == 0: |
741 if self.remove: | 741 if self.remove: |
742 self.backend.unlink(self.fname) | 742 self.backend.unlink(self.fname) |
743 else: | 743 else: |
744 self.lines[start : start + h.lena] = h.new() | 744 self.lines[start : start + h.lena] = new |
745 self.offset += h.lenb - h.lena | 745 self.offset += h.lenb - h.lena |
746 self.dirty = True | 746 self.dirty = True |
747 return 0 | 747 return 0 |
748 | 748 |
749 # ok, we couldn't match the hunk. Lets look for offsets and fuzz it | 749 # ok, we couldn't match the hunk. Lets look for offsets and fuzz it |
757 else: | 757 else: |
758 search_start = orig_start + self.skew | 758 search_start = orig_start + self.skew |
759 | 759 |
760 for fuzzlen in xrange(3): | 760 for fuzzlen in xrange(3): |
761 for toponly in [True, False]: | 761 for toponly in [True, False]: |
762 old = h.old(fuzzlen, toponly) | 762 old, new = h.fuzzit(fuzzlen, toponly) |
763 | 763 |
764 cand = self.findlines(old[0][1:], search_start) | 764 cand = self.findlines(old[0][1:], search_start) |
765 for l in cand: | 765 for l in cand: |
766 if diffhelpers.testhunk(old, self.lines, l) == 0: | 766 if diffhelpers.testhunk(old, self.lines, l) == 0: |
767 newlines = h.new(fuzzlen, toponly) | 767 self.lines[l : l + len(old)] = new |
768 self.lines[l : l + len(old)] = newlines | 768 self.offset += len(new) - len(old) |
769 self.offset += len(newlines) - len(old) | |
770 self.skew = l - orig_start | 769 self.skew = l - orig_start |
771 self.dirty = True | 770 self.dirty = True |
772 offset = l - orig_start - fuzzlen | 771 offset = l - orig_start - fuzzlen |
773 if fuzzlen: | 772 if fuzzlen: |
774 msg = _("Hunk #%d succeeded at %d " | 773 msg = _("Hunk #%d succeeded at %d " |
969 lr.push(l) | 968 lr.push(l) |
970 | 969 |
971 def complete(self): | 970 def complete(self): |
972 return len(self.a) == self.lena and len(self.b) == self.lenb | 971 return len(self.a) == self.lena and len(self.b) == self.lenb |
973 | 972 |
974 def fuzzit(self, l, fuzz, toponly): | 973 def _fuzzit(self, old, new, fuzz, toponly): |
975 # this removes context lines from the top and bottom of list 'l'. It | 974 # this removes context lines from the top and bottom of list 'l'. It |
976 # checks the hunk to make sure only context lines are removed, and then | 975 # checks the hunk to make sure only context lines are removed, and then |
977 # returns a new shortened list of lines. | 976 # returns a new shortened list of lines. |
978 fuzz = min(fuzz, len(l)-1) | 977 fuzz = min(fuzz, len(old)-1) |
979 if fuzz: | 978 if fuzz: |
980 top = 0 | 979 top = 0 |
981 bot = 0 | 980 bot = 0 |
982 hlen = len(self.hunk) | 981 hlen = len(self.hunk) |
983 for x in xrange(hlen - 1): | 982 for x in xrange(hlen - 1): |
1003 if top < context: | 1002 if top < context: |
1004 top = max(0, fuzz - (context - top)) | 1003 top = max(0, fuzz - (context - top)) |
1005 else: | 1004 else: |
1006 top = min(fuzz, top) | 1005 top = min(fuzz, top) |
1007 | 1006 |
1008 return l[top:len(l)-bot] | 1007 return old[top:len(old)-bot], new[top:len(new)-bot] |
1009 return l | 1008 return old, new |
1010 | 1009 |
1011 def old(self, fuzz=0, toponly=False): | 1010 def fuzzit(self, fuzz, toponly): |
1012 return self.fuzzit(self.a, fuzz, toponly) | 1011 return self._fuzzit(self.a, self.b, fuzz, toponly) |
1013 | |
1014 def new(self, fuzz=0, toponly=False): | |
1015 return self.fuzzit(self.b, fuzz, toponly) | |
1016 | 1012 |
1017 class binhunk(object): | 1013 class binhunk(object): |
1018 'A binary patch file. Only understands literals so far.' | 1014 'A binary patch file. Only understands literals so far.' |
1019 def __init__(self, lr): | 1015 def __init__(self, lr): |
1020 self.text = None | 1016 self.text = None |