Mercurial > public > mercurial-scm > hg
comparison mercurial/patch.py @ 10127:d8214e944b84
patch: fix eolmode=auto with new files
If target file does not exist or has no eol, current code was normalizing eols
to LF. Preserve patch file eols instead.
author | Patrick Mezard <pmezard@gmail.com> |
---|---|
date | Wed, 23 Dec 2009 19:31:47 +0100 |
parents | 1720d70cd6d4 |
children | ea7c392f2b08 |
comparison
equal
deleted
inserted
replaced
10126:78b8acae2088 | 10127:d8214e944b84 |
---|---|
319 if islink: | 319 if islink: |
320 fp = cStringIO.StringIO() | 320 fp = cStringIO.StringIO() |
321 else: | 321 else: |
322 fp = self.opener(fname, 'w') | 322 fp = self.opener(fname, 'w') |
323 try: | 323 try: |
324 if self.eolmode == 'auto' and self.eol: | 324 if self.eolmode == 'auto': |
325 eol = self.eol | 325 eol = self.eol |
326 elif self.eolmode == 'crlf': | 326 elif self.eolmode == 'crlf': |
327 eol = '\r\n' | 327 eol = '\r\n' |
328 else: | 328 else: |
329 eol = '\n' | 329 eol = '\n' |
330 | 330 |
331 if self.eolmode != 'strict' and eol != '\n': | 331 if self.eolmode != 'strict' and eol and eol != '\n': |
332 for l in lines: | 332 for l in lines: |
333 if l and l[-1] == '\n': | 333 if l and l[-1] == '\n': |
334 l = l[:-1] + eol | 334 l = l[:-1] + eol |
335 fp.write(l) | 335 fp.write(l) |
336 else: | 336 else: |
430 else: | 430 else: |
431 self.lines[:] = h.new() | 431 self.lines[:] = h.new() |
432 self.offset += len(h.new()) | 432 self.offset += len(h.new()) |
433 self.dirty = 1 | 433 self.dirty = 1 |
434 return 0 | 434 return 0 |
435 | |
436 horig = h | |
437 if self.eolmode == 'auto' and self.eol: | |
438 # If eolmode == 'auto' and target file exists and has line | |
439 # endings we have to normalize input data before patching. | |
440 # Otherwise, patchfile operates in 'strict' mode. If | |
441 # eolmode is set to 'crlf' or 'lf', input hunk is already | |
442 # normalized to avoid data copy. | |
443 h = h.getnormalized() | |
435 | 444 |
436 # fast case first, no offsets, no fuzz | 445 # fast case first, no offsets, no fuzz |
437 old = h.old() | 446 old = h.old() |
438 # patch starts counting at 1 unless we are adding the file | 447 # patch starts counting at 1 unless we are adding the file |
439 if h.starta == 0: | 448 if h.starta == 0: |
486 "(offset %d lines).\n") | 495 "(offset %d lines).\n") |
487 f(msg % (h.number, l+1, fuzzstr, offset)) | 496 f(msg % (h.number, l+1, fuzzstr, offset)) |
488 return fuzzlen | 497 return fuzzlen |
489 self.printfile(True) | 498 self.printfile(True) |
490 self.ui.warn(_("Hunk #%d FAILED at %d\n") % (h.number, orig_start)) | 499 self.ui.warn(_("Hunk #%d FAILED at %d\n") % (h.number, orig_start)) |
491 self.rej.append(h) | 500 self.rej.append(horig) |
492 return -1 | 501 return -1 |
493 | 502 |
494 class hunk(object): | 503 class hunk(object): |
495 def __init__(self, desc, num, lr, context, create=False, remove=False): | 504 def __init__(self, desc, num, lr, context, create=False, remove=False): |
496 self.number = num | 505 self.number = num |
498 self.hunk = [ desc ] | 507 self.hunk = [ desc ] |
499 self.a = [] | 508 self.a = [] |
500 self.b = [] | 509 self.b = [] |
501 self.starta = self.lena = None | 510 self.starta = self.lena = None |
502 self.startb = self.lenb = None | 511 self.startb = self.lenb = None |
503 if context: | 512 if lr is not None: |
504 self.read_context_hunk(lr) | 513 if context: |
505 else: | 514 self.read_context_hunk(lr) |
506 self.read_unified_hunk(lr) | 515 else: |
516 self.read_unified_hunk(lr) | |
507 self.create = create | 517 self.create = create |
508 self.remove = remove and not create | 518 self.remove = remove and not create |
519 | |
520 def getnormalized(self): | |
521 """Return a copy with line endings normalized to LF.""" | |
522 | |
523 def normalize(lines): | |
524 nlines = [] | |
525 for line in lines: | |
526 if line.endswith('\r\n'): | |
527 line = line[:-2] + '\n' | |
528 nlines.append(line) | |
529 return nlines | |
530 | |
531 # Dummy object, it is rebuilt manually | |
532 nh = hunk(self.desc, self.number, None, None, False, False) | |
533 nh.number = self.number | |
534 nh.desc = self.desc | |
535 nh.a = normalize(self.a) | |
536 nh.b = normalize(self.b) | |
537 nh.starta = self.starta | |
538 nh.startb = self.startb | |
539 nh.lena = self.lena | |
540 nh.lenb = self.lenb | |
541 nh.create = self.create | |
542 nh.remove = self.remove | |
543 return nh | |
509 | 544 |
510 def read_unified_hunk(self, lr): | 545 def read_unified_hunk(self, lr): |
511 m = unidesc.match(self.desc) | 546 m = unidesc.match(self.desc) |
512 if not m: | 547 if not m: |
513 raise PatchError(_("bad hunk #%d") % self.number) | 548 raise PatchError(_("bad hunk #%d") % self.number) |
972 rejects = 0 | 1007 rejects = 0 |
973 err = 0 | 1008 err = 0 |
974 current_file = None | 1009 current_file = None |
975 gitpatches = None | 1010 gitpatches = None |
976 opener = util.opener(os.getcwd()) | 1011 opener = util.opener(os.getcwd()) |
977 textmode = eolmode != 'strict' | 1012 # In 'auto' mode, we must preserve original eols if target file |
1013 # eols are undefined. Otherwise, hunk data will be normalized | |
1014 # later. | |
1015 textmode = eolmode not in ('strict', 'auto') | |
978 | 1016 |
979 def closefile(): | 1017 def closefile(): |
980 if not current_file: | 1018 if not current_file: |
981 return 0 | 1019 return 0 |
982 current_file.close() | 1020 current_file.close() |