lint-shell-locale.py
1 #!/usr/bin/env python3 2 # 3 # Copyright (c) 2018-present The Bitcoin Core developers 4 # Distributed under the MIT software license, see the accompanying 5 # file COPYING or http://www.opensource.org/licenses/mit-license.php. 6 7 """ 8 Make sure all shell scripts explicitly opt out of locale dependence using 9 "export LC_ALL=C" or "export LC_ALL=C.UTF-8", which also enables UTF-8 mode in 10 Python. See: https://docs.python.org/3/library/os.html#python-utf-8-mode 11 """ 12 13 import subprocess 14 import sys 15 import re 16 17 OPT_OUT_LINES = [ 18 'export LC_ALL=C', 19 'export LC_ALL=C.UTF-8', 20 ] 21 22 def get_shell_files_list(): 23 command = [ 24 'git', 25 'ls-files', 26 '--', 27 '*.sh', 28 ] 29 try: 30 return subprocess.check_output(command, stderr = subprocess.STDOUT, text=True).splitlines() 31 except subprocess.CalledProcessError as e: 32 if e.returncode > 1: # return code is 1 when match is empty 33 print(e.output, end='') 34 sys.exit(1) 35 return [] 36 37 def main(): 38 exit_code = 0 39 shell_files = get_shell_files_list() 40 for file_path in shell_files: 41 if re.search('src/(secp256k1|minisketch)/', file_path): 42 continue 43 44 with open(file_path, 'r') as file_obj: 45 contents = file_obj.read() 46 47 non_comment_pattern = re.compile(r'^\s*((?!#).+)$', re.MULTILINE) 48 non_comment_lines = re.findall(non_comment_pattern, contents) 49 if not non_comment_lines: 50 continue 51 52 first_non_comment_line = non_comment_lines[0] 53 if first_non_comment_line not in OPT_OUT_LINES: 54 print(f'Missing "export LC_ALL=C" (to avoid locale dependence) as first non-comment non-empty line in {file_path}') 55 exit_code = 1 56 57 return sys.exit(exit_code) 58 59 if __name__ == '__main__': 60 main() 61