comparison mercurial/patch.py @ 10128:ea7c392f2b08

patch: drop eol normalization fast-path for 'lf' and 'crlf' With eolmode set to 'lf' or 'crlf' we avoided the hunk duplication and normalization by reading the input patch in text mode. Dropping this optimization simplifies code expectations for a small overhead. The change in test-mq-eol comes from a tolerance to CRLF instead of LF for last lines without newlines being broken by this revision. This tolerance was only partially supported and will be added again in a better way.
author Patrick Mezard <pmezard@gmail.com>
date Wed, 23 Dec 2009 19:31:48 +0100
parents d8214e944b84
children ef5b537433da
comparison
equal deleted inserted replaced
10127:d8214e944b84 10128:ea7c392f2b08
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 435
436 horig = h 436 horig = h
437 if self.eolmode == 'auto' and self.eol: 437 if (self.eolmode in ('crlf', 'lf')
438 # If eolmode == 'auto' and target file exists and has line 438 or self.eolmode == 'auto' and self.eol):
439 # endings we have to normalize input data before patching. 439 # If new eols are going to be normalized, then normalize
440 # Otherwise, patchfile operates in 'strict' mode. If 440 # hunk data before patching. Otherwise, preserve input
441 # eolmode is set to 'crlf' or 'lf', input hunk is already 441 # line-endings.
442 # normalized to avoid data copy.
443 h = h.getnormalized() 442 h = h.getnormalized()
444 443
445 # fast case first, no offsets, no fuzz 444 # fast case first, no offsets, no fuzz
446 old = h.old() 445 old = h.old()
447 # patch starts counting at 1 unless we are adding the file 446 # patch starts counting at 1 unless we are adding the file
868 gitlr.push(firstline) 867 gitlr.push(firstline)
869 (dopatch, gitpatches) = readgitpatch(gitlr) 868 (dopatch, gitpatches) = readgitpatch(gitlr)
870 fp.seek(pos) 869 fp.seek(pos)
871 return dopatch, gitpatches 870 return dopatch, gitpatches
872 871
873 def iterhunks(ui, fp, sourcefile=None, textmode=False): 872 def iterhunks(ui, fp, sourcefile=None):
874 """Read a patch and yield the following events: 873 """Read a patch and yield the following events:
875 - ("file", afile, bfile, firsthunk): select a new target file. 874 - ("file", afile, bfile, firsthunk): select a new target file.
876 - ("hunk", hunk): a new hunk is ready to be applied, follows a 875 - ("hunk", hunk): a new hunk is ready to be applied, follows a
877 "file" event. 876 "file" event.
878 - ("git", gitchanges): current diff is in git format, gitchanges 877 - ("git", gitchanges): current diff is in git format, gitchanges
879 maps filenames to gitpatch records. Unique event. 878 maps filenames to gitpatch records. Unique event.
880
881 If textmode is True, input line-endings are normalized to LF.
882 """ 879 """
883 changed = {} 880 changed = {}
884 current_hunk = None 881 current_hunk = None
885 afile = "" 882 afile = ""
886 bfile = "" 883 bfile = ""
890 git = False 887 git = False
891 888
892 # our states 889 # our states
893 BFILE = 1 890 BFILE = 1
894 context = None 891 context = None
895 lr = linereader(fp, textmode) 892 lr = linereader(fp)
896 dopatch = True 893 dopatch = True
897 # gitworkdone is True if a git operation (copy, rename, ...) was 894 # gitworkdone is True if a git operation (copy, rename, ...) was
898 # performed already for the current file. Useful when the file 895 # performed already for the current file. Useful when the file
899 # section may have no hunk. 896 # section may have no hunk.
900 gitworkdone = False 897 gitworkdone = False
1007 rejects = 0 1004 rejects = 0
1008 err = 0 1005 err = 0
1009 current_file = None 1006 current_file = None
1010 gitpatches = None 1007 gitpatches = None
1011 opener = util.opener(os.getcwd()) 1008 opener = util.opener(os.getcwd())
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')
1016 1009
1017 def closefile(): 1010 def closefile():
1018 if not current_file: 1011 if not current_file:
1019 return 0 1012 return 0
1020 current_file.close() 1013 current_file.close()
1021 return len(current_file.rej) 1014 return len(current_file.rej)
1022 1015
1023 for state, values in iterhunks(ui, fp, sourcefile, textmode): 1016 for state, values in iterhunks(ui, fp, sourcefile):
1024 if state == 'hunk': 1017 if state == 'hunk':
1025 if not current_file: 1018 if not current_file:
1026 continue 1019 continue
1027 current_hunk = values 1020 current_hunk = values
1028 ret = current_file.apply(current_hunk) 1021 ret = current_file.apply(current_hunk)