diff --git a/pre_commit_hooks/end_of_file_fixer.py b/pre_commit_hooks/end_of_file_fixer.py index a88425c6..0a729766 100644 --- a/pre_commit_hooks/end_of_file_fixer.py +++ b/pre_commit_hooks/end_of_file_fixer.py @@ -5,6 +5,10 @@ from collections.abc import Sequence from typing import IO +LF = b'\n' +CR = b'\r' +CRLF = b'\r\n' + def fix_file(file_obj: IO[bytes]) -> int: # Test for newline at end of file @@ -15,13 +19,22 @@ def fix_file(file_obj: IO[bytes]) -> int: return 0 last_character = file_obj.read(1) # last_character will be '' for an empty file - if last_character not in {b'\n', b'\r'} and last_character != b'': + if last_character not in {LF, CR} and last_character != b'': + # Look at first line to determine line ending + file_obj.seek(0, os.SEEK_SET) + first_line = file_obj.readline() + if CRLF in first_line: + ending = CRLF + elif CR in first_line: + ending = CR + else: + ending = LF # Needs this seek for windows, otherwise IOError file_obj.seek(0, os.SEEK_END) - file_obj.write(b'\n') + file_obj.write(ending) return 1 - while last_character in {b'\n', b'\r'}: + while last_character in {LF, CR}: # Deal with the beginning of the file if file_obj.tell() == 1: # If we've reached the beginning of the file and it is all @@ -38,7 +51,7 @@ def fix_file(file_obj: IO[bytes]) -> int: # newlines. If we find extraneous newlines, then backtrack and trim them. position = file_obj.tell() remaining = file_obj.read() - for sequence in (b'\n', b'\r\n', b'\r'): + for sequence in (LF, CRLF, CR): if remaining == sequence: return 0 elif remaining.startswith(sequence): diff --git a/tests/end_of_file_fixer_test.py b/tests/end_of_file_fixer_test.py index 8a5d889e..99f40b7c 100644 --- a/tests/end_of_file_fixer_test.py +++ b/tests/end_of_file_fixer_test.py @@ -18,6 +18,8 @@ (b'foo\n\n\n', 1, b'foo\n'), (b'\xe2\x98\x83', 1, b'\xe2\x98\x83\n'), (b'foo\r\n', 0, b'foo\r\n'), + (b'foo\r\nbar', 1, b'foo\r\nbar\r\n'), + (b'foo\rbar', 1, b'foo\rbar\r'), (b'foo\r\n\r\n\r\n', 1, b'foo\r\n'), (b'foo\r', 0, b'foo\r'), (b'foo\r\r\r\r', 1, b'foo\r'),