Mercurial > public > mercurial-scm > hg-stable
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) |