# HG changeset patch # User Martin Geisler # Date 1261325884 -3600 # Node ID 1720d70cd6d4cbfdf6ed85833c4b0c1d17fec5f7 # Parent 155fe35534d3cc5f222f6f8847a31010f217eb13 patch: implement patch.eol=auto mode EOLs in patched files are restored to their original value after patching. We use the first EOL found in the file, files with inconsistent EOLs will thus be normalized during this process. diff -r 155fe35534d3 -r 1720d70cd6d4 doc/hgrc.5.txt --- a/doc/hgrc.5.txt Sun Dec 20 17:18:02 2009 +0100 +++ b/doc/hgrc.5.txt Sun Dec 20 17:18:04 2009 +0100 @@ -648,7 +648,10 @@ When set to 'strict' patch content and patched files end of lines are preserved. When set to ``lf`` or ``crlf``, both files end of lines are ignored when patching and the result line endings are - normalized to either LF (Unix) or CRLF (Windows). + normalized to either LF (Unix) or CRLF (Windows). When set to + ``auto``, end of lines are again ignored while patching but line + endings in patched files are normalized to their original setting + on a per-file basis. Default: strict. diff -r 155fe35534d3 -r 1720d70cd6d4 mercurial/patch.py --- a/mercurial/patch.py Sun Dec 20 17:18:02 2009 +0100 +++ b/mercurial/patch.py Sun Dec 20 17:18:04 2009 +0100 @@ -239,6 +239,7 @@ self.fp = fp self.buf = [] self.textmode = textmode + self.eol = None def push(self, line): if line is not None: @@ -250,6 +251,11 @@ del self.buf[0] return l l = self.fp.readline() + if not self.eol: + if l.endswith('\r\n'): + self.eol = '\r\n' + elif l.endswith('\n'): + self.eol = '\n' if self.textmode and l.endswith('\r\n'): l = l[:-2] + '\n' return l @@ -264,13 +270,13 @@ # @@ -start,len +start,len @@ or @@ -start +start @@ if len is 1 unidesc = re.compile('@@ -(\d+)(,(\d+))? \+(\d+)(,(\d+))? @@') contextdesc = re.compile('(---|\*\*\*) (\d+)(,(\d+))? (---|\*\*\*)') -eolmodes = ['strict', 'crlf', 'lf'] +eolmodes = ['strict', 'crlf', 'lf', 'auto'] class patchfile(object): def __init__(self, ui, fname, opener, missing=False, eolmode='strict'): self.fname = fname self.eolmode = eolmode - self.eol = {'strict': None, 'crlf': '\r\n', 'lf': '\n'}[eolmode] + self.eol = None self.opener = opener self.ui = ui self.lines = [] @@ -298,7 +304,10 @@ return [os.readlink(fname)] fp = self.opener(fname, 'r') try: - return list(linereader(fp, self.eolmode != 'strict')) + lr = linereader(fp, self.eolmode != 'strict') + lines = list(lr) + self.eol = lr.eol + return lines finally: fp.close() @@ -312,10 +321,17 @@ else: fp = self.opener(fname, 'w') try: - if self.eol and self.eol != '\n': + if self.eolmode == 'auto' and self.eol: + eol = self.eol + elif self.eolmode == 'crlf': + eol = '\r\n' + else: + eol = '\n' + + if self.eolmode != 'strict' and eol != '\n': for l in lines: if l and l[-1] == '\n': - l = l[:-1] + self.eol + l = l[:-1] + eol fp.write(l) else: fp.writelines(lines) diff -r 155fe35534d3 -r 1720d70cd6d4 tests/test-import-eol --- a/tests/test-import-eol Sun Dec 20 17:18:02 2009 +0100 +++ b/tests/test-import-eol Sun Dec 20 17:18:04 2009 +0100 @@ -28,19 +28,35 @@ python -c 'file("a", "wb").write("a\nbbb\ncc\n\nd\ne")' hg ci -Am adda python ../makepatch.py + echo % invalid eol hg --config patch.eol='LFCR' import eol.diff hg revert -a + echo % force LF hg --traceback --config patch.eol='LF' import eol.diff python -c 'print repr(file("a","rb").read())' hg st + echo % force CRLF hg up -C 0 hg --traceback --config patch.eol='CRLF' import eol.diff python -c 'print repr(file("a","rb").read())' hg st +echo % auto EOL on LF file +hg up -C 0 +hg --traceback --config patch.eol='auto' import eol.diff +python -c 'print repr(file("a","rb").read())' +hg st + +echo % auto EOL on CRLF file +python -c 'file("a", "wb").write("a\r\nbbb\r\ncc\r\n\r\nd\r\ne")' +hg commit -m 'switch EOLs in a' +hg --traceback --config patch.eol='auto' import eol.diff +python -c 'print repr(file("a","rb").read())' +hg st + # Test --eol and binary patches python -c 'file("b", "wb").write("a\x00\nb")' hg ci -Am addb diff -r 155fe35534d3 -r 1720d70cd6d4 tests/test-import-eol.out --- a/tests/test-import-eol.out Sun Dec 20 17:18:02 2009 +0100 +++ b/tests/test-import-eol.out Sun Dec 20 17:18:04 2009 +0100 @@ -10,6 +10,13 @@ 1 files updated, 0 files merged, 0 files removed, 0 files unresolved applying eol.diff 'a\r\nyyyy\r\ncc\r\n\r\nd\r\ne' +% auto EOL on LF file +1 files updated, 0 files merged, 0 files removed, 0 files unresolved +applying eol.diff +'a\nyyyy\ncc\n\nd\ne' +% auto EOL on CRLF file +applying eol.diff +'a\r\nyyyy\r\ncc\r\n\r\nd\r\ne' adding b % binary patch with --eol applying bin.diff