comparison mercurial/patch.py @ 10135:9a4034b630c4 stable

patch: better handling of sequence of offset patch hunks (issue1941) The built-in patch implementation applied the hunks to the wrong lines of the file if the file in the repo has been modified to skew the patch line numbers and the file contains repetitive sequences of lines.
author Greg Onufer <gonufer@jazzhaiku.com>
date Wed, 09 Dec 2009 16:56:00 -0800
parents 3f522d2fa633
children 270367ec4d30 6e26e3c2083f
comparison
equal deleted inserted replaced
10132:ebf69364e80f 10135:9a4034b630c4
284 self.ui.warn(_("unable to find '%s' for patching\n") % self.fname) 284 self.ui.warn(_("unable to find '%s' for patching\n") % self.fname)
285 285
286 self.hash = {} 286 self.hash = {}
287 self.dirty = 0 287 self.dirty = 0
288 self.offset = 0 288 self.offset = 0
289 self.skew = 0
289 self.rej = [] 290 self.rej = []
290 self.fileprinted = False 291 self.fileprinted = False
291 self.printfile(False) 292 self.printfile(False)
292 self.hunks = 0 293 self.hunks = 0
293 294
421 if h.starta == 0: 422 if h.starta == 0:
422 start = 0 423 start = 0
423 else: 424 else:
424 start = h.starta + self.offset - 1 425 start = h.starta + self.offset - 1
425 orig_start = start 426 orig_start = start
426 if diffhelpers.testhunk(old, self.lines, start) == 0: 427 # if there's skew we want to emit the "(offset %d lines)" even
428 # when the hunk cleanly applies at start + skew, so skip the
429 # fast case code
430 if self.skew == 0 and diffhelpers.testhunk(old, self.lines, start) == 0:
427 if h.rmfile(): 431 if h.rmfile():
428 self.unlink(self.fname) 432 self.unlink(self.fname)
429 else: 433 else:
430 self.lines[start : start + h.lena] = h.new() 434 self.lines[start : start + h.lena] = h.new()
431 self.offset += h.lenb - h.lena 435 self.offset += h.lenb - h.lena
437 if h.hunk[-1][0] != ' ': 441 if h.hunk[-1][0] != ' ':
438 # if the hunk tried to put something at the bottom of the file 442 # if the hunk tried to put something at the bottom of the file
439 # override the start line and use eof here 443 # override the start line and use eof here
440 search_start = len(self.lines) 444 search_start = len(self.lines)
441 else: 445 else:
442 search_start = orig_start 446 search_start = orig_start + self.skew
443 447
444 for fuzzlen in xrange(3): 448 for fuzzlen in xrange(3):
445 for toponly in [ True, False ]: 449 for toponly in [ True, False ]:
446 old = h.old(fuzzlen, toponly) 450 old = h.old(fuzzlen, toponly)
447 451
449 for l in cand: 453 for l in cand:
450 if diffhelpers.testhunk(old, self.lines, l) == 0: 454 if diffhelpers.testhunk(old, self.lines, l) == 0:
451 newlines = h.new(fuzzlen, toponly) 455 newlines = h.new(fuzzlen, toponly)
452 self.lines[l : l + len(old)] = newlines 456 self.lines[l : l + len(old)] = newlines
453 self.offset += len(newlines) - len(old) 457 self.offset += len(newlines) - len(old)
458 self.skew = l - orig_start
454 self.dirty = 1 459 self.dirty = 1
455 if fuzzlen: 460 if fuzzlen:
456 fuzzstr = "with fuzz %d " % fuzzlen 461 fuzzstr = "with fuzz %d " % fuzzlen
457 f = self.ui.warn 462 f = self.ui.warn
458 self.printfile(True) 463 self.printfile(True)