Anton Shestakov <av6@dwimlabs.net>, Mon, 04 Jul 2016 19:29:46 +0800
viewer: stretch project name column to maximum on /
checker.py
Permissions: -rwxr-xr-x
from __future__ import print_function from argparse import ArgumentParser, FileType from datetime import datetime from shutil import rmtree from subprocess import check_call, check_output, CalledProcessError from tempfile import mkdtemp rel = lambda *x: os.path.abspath(os.path.join(os.path.dirname(__file__), *x)) def run_ignore_codes(fn, args, codes): except CalledProcessError as e: if e.returncode not in codes: def run(args, silent=False, get_output=False, ignore_codes=None): print('$ ' + ' '.join(args)) result = run_ignore_codes(fn, args, ignore_codes) print('# C&O error: {}'.format(e)) print('# C&O job failed') return datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S+00:00') def read_linter_config(name, path=rel('linters')): fd = open(os.path.join(path, '{}.yml'.format(name))) print("# C&O couldn't load linter config: {}".format(e)) return yaml.safe_load(fd) print("# C&O couldn't parse linter config: {}".format(e)) print("# C&O config doesn't have 'url' defined.") print("# C&O config doesn't have 'scm' defined.") elif config['scm'] != 'hg': print("# C&O checker doesn't support {} yet.".format(config['scm'])) def execute(tmp, config): if not prevalidate(config): print('# C&O task: clone') print('# C&O project URL: {}'.format(config['url'])) os.environ['HGPLAIN'] = '1' if not run(['hg', 'clone', config['url'], source]): print('$ cd {}'.format(source)) if not run(['hg', 'sum']): template = (r'# C&O commit: {rev}:{node}\n' r'# C&O commit branch: {branch}\n' r'# C&O commit date: {date|isodatesec}\n' r'# C&O commit author: {author|person}\n' r'# C&O commit message: {desc|firstline}\n') if not run(['hg', 'log', '-r', '.', '-T', template], silent=True): print('# C&O task: setup') to_install = [l['name'] for l in config.get('linters', []) if 'name' in l] print('# C&O linters to install: {}'.format(' '.join(to_install))) for linter in config.get('linters', []): if name in linter_config: lc = read_linter_config(name) if lc is None or 'exec' not in lc: for item in lc.get('setup', []): if 'version' in lc and not run(lc['exec'] + lc['version']): print('# C&O linters installed: {}'.format(' '.join(linter_config.keys()))) print('# C&O task: checks') for linter in config.get('linters', []): if 'name' not in linter or 'include' not in linter: if linter['name'] not in linter_config: for pat in linter['include']: for pat in linter.get('exclude', []): files = run(cmd, silent=True, get_output=True, ignore_codes=(1,)) lc = linter_config[linter['name']] for f in files.splitlines(): flags = lc.get('flags', []) + linter.get('flags', []) pf = lc.get('post_flags', []) + linter.get('post_flags', []) codes = lc.get('codes', (1,)) if not run(cmd + flags + [f] + pf, ignore_codes=codes): print('# C&O job started: {}'.format(now())) tmp = mkdtemp(prefix='candolint.') if not execute(tmp, config): print('# C&O job failed') print('# C&O task: cleanup') print('# C&O job finished: {}'.format(now())) print('# C&O job failed (exception not caught)') print('# C&O job finished: {}'.format(now())) parser = ArgumentParser() helptext = 'project configuration file (YAML)' parser.add_argument('config', type=FileType('r'), help=helptext) args = parser.parse_args() config = yaml.safe_load(args.config) if __name__ == '__main__':