1#!/usr/bin/env python3 2# 3# Copyright 2020, Data61, CSIRO (ABN 41 687 119 230) 4# 5# SPDX-License-Identifier: BSD-2-Clause 6# 7""" 8run style tools over files 9""" 10 11import argparse 12import fnmatch 13import logging 14import os 15import re 16import subprocess 17import sys 18 19from filter import parse_filters 20 21# dict of style-tools to regex. The regex should match any full file path. 22# if the regex matches, that tool will be applied to that file. Multiple 23# tools can be defined for the same regex. 24STYLE_MAP = { 25 'style-c.sh': r'((\.c)|(\.h))$', 26 'style-cmake.sh': r'((\.cmake)|(CMakeLists.txt))$', 27 'style-py.sh': r'\.py$' 28} 29 30 31def main(): 32 parser = argparse.ArgumentParser("Run style updates on files.") 33 parser.add_argument('-f', '--filters', type=str, 34 help='File with glob filters of files to filter') 35 parser.add_argument('files', nargs='*', type=str, 36 help='List of files to run style updates on.') 37 args = parser.parse_args() 38 39 filters = parse_filters(args.filters) 40 regexmap = {k: re.compile(v) for k, v in STYLE_MAP.items()} 41 filemap = {k: [] for k, v in STYLE_MAP.items()} 42 43 args.files = filter(os.path.isfile, args.files) 44 # construct a list of files to pass to each tool 45 for fname in args.files: 46 def matches(pattern, fname=fname): 47 """filter any files that match the filter filters""" 48 return fnmatch.fnmatch(fname, pattern) 49 if not any(map(matches, filters)): 50 for k, regex in regexmap.items(): 51 if regex.search(fname): 52 filemap.get(k, list()).append(fname) 53 54 # now spawn processes to style all the files 55 # this is currently done sequentially to collect output. 56 # if this becomes a bottle neck we can consider spawning more processes 57 return_code = 0 58 for k, files in filemap.items(): 59 if files: 60 script = os.path.join(os.path.dirname(os.path.realpath(sys.argv[0])), k) 61 completed = subprocess.run([script] + files, stderr=subprocess.PIPE) 62 if completed.returncode: 63 logging.fatal("%s failed with error code %d\n%s", files, 64 completed.returncode, completed.stderr) 65 return_code = completed.returncode 66 return return_code 67 68 69if __name__ == '__main__': 70 sys.exit(main()) 71