import argparse import logging import os import re import sys from enum import Enum class LineEnding(Enum): CR = b'\r', '\\r', 'cr', re.compile(b'\r(?!\n)', re.DOTALL) CRLF = b'\r\n', '\\r\\n', 'crlf', re.compile(b'\r\n', re.DOTALL) LF = b'\n', '\\n', 'lf', re.compile(b'(? 0 mixed |= le_found_previously and le_found_cur le_found_previously |= le_found_cur if le_count == max_le_count: most_le = None elif le_count > max_le_count: max_le_count = le_count most_le = le if not mixed: return MixedLineDetection.NOT_MIXED for mld in MixedLineDetection: if mld.line_ending_enum is not None \ and mld.line_ending_enum == most_le: return mld return MixedLineDetection.UNKNOWN def _process_no_fix(filenames): logging.info('Checking if the files have mixed line ending.') mle_filenames = [] for filename in filenames: detect_result = _detect_line_ending(filename) logging.debug( 'mixed_line_ending: detect_result = %s', detect_result, ) if detect_result.mle_found: mle_filenames.append(filename) mle_found = len(mle_filenames) > 0 if mle_found: logging.info( 'The following files have mixed line endings:\n\t%s', '\n\t'.join(mle_filenames), ) return 1 if mle_found else 0 def _process_fix_auto(filenames): mle_found = False for filename in filenames: detect_result = _detect_line_ending(filename) logging.debug( 'mixed_line_ending: detect_result = %s', detect_result, ) if detect_result == MixedLineDetection.NOT_MIXED: logging.info('The file %s has no mixed line ending', filename) mle_found |= False elif detect_result == MixedLineDetection.UNKNOWN: logging.info( 'Could not define most frequent line ending in ' 'file %s. File skiped.', filename, ) mle_found = True else: le_enum = detect_result.line_ending_enum logging.info( 'The file %s has mixed line ending with a ' 'majority of "%s". Converting...', filename, le_enum.str_print, ) _convert_line_ending(filename, le_enum.string) mle_found = True logging.info( 'The file %s has been converted to "%s" line ' 'ending.', filename, le_enum.str_print, ) return 1 if mle_found else 0 def _process_fix_force(filenames, line_ending_enum): for filename in filenames: _convert_line_ending(filename, line_ending_enum.string) logging.info( 'The file %s has been forced to "%s" line ending.', filename, line_ending_enum.str_print, ) return 1 def _convert_line_ending(filename, line_ending): # read the file with open(filename, 'rb+') as f: bufin = f.read() # convert line ending bufout = ANY_LINE_ENDING_PATTERN.sub(line_ending, bufin) # write the result in the file f.seek(0) f.write(bufout) f.truncate() if __name__ == '__main__': sys.exit(mixed_line_ending())