1"""SCM hooks. Integration with git and mercurial.""" 2 3from __future__ import absolute_import 4 5import sys 6from os import path as op, chmod 7from subprocess import Popen, PIPE 8 9from .main import LOGGER, process_paths 10from .config import parse_options, setup_logger 11 12 13try: 14 from configparser import ConfigParser # noqa 15except ImportError: # Python 2 16 from ConfigParser import ConfigParser 17 18 19def run(command): 20 """Run a shell command. 21 22 :return str: Stdout 23 """ 24 p = Popen(command.split(), stdout=PIPE, stderr=PIPE) 25 (stdout, stderr) = p.communicate() 26 return (p.returncode, [line.strip() for line in stdout.splitlines()], 27 [line.strip() for line in stderr.splitlines()]) 28 29 30def git_hook(error=True): 31 """Run pylama after git commit.""" 32 _, files_modified, _ = run("git diff-index --cached --name-only HEAD") 33 34 options = parse_options() 35 setup_logger(options) 36 if sys.version_info >= (3,): 37 candidates = [f.decode('utf-8') for f in files_modified] 38 else: 39 candidates = [str(f) for f in files_modified] 40 41 if candidates: 42 process_paths(options, candidates=candidates, error=error) 43 44 45def hg_hook(ui, repo, node=None, **kwargs): 46 """Run pylama after mercurial commit.""" 47 seen = set() 48 paths = [] 49 if len(repo): 50 for rev in range(repo[node], len(repo)): 51 for file_ in repo[rev].files(): 52 file_ = op.join(repo.root, file_) 53 if file_ in seen or not op.exists(file_): 54 continue 55 seen.add(file_) 56 paths.append(file_) 57 58 options = parse_options() 59 setup_logger(options) 60 if paths: 61 process_paths(options, candidates=paths) 62 63 64def install_git(path): 65 """Install hook in Git repository.""" 66 hook = op.join(path, 'pre-commit') 67 with open(hook, 'w') as fd: 68 fd.write("""#!/usr/bin/env python 69import sys 70from pylama.hook import git_hook 71 72if __name__ == '__main__': 73 sys.exit(git_hook()) 74""") 75 chmod(hook, 484) 76 77 78def install_hg(path): 79 """ Install hook in Mercurial repository. """ 80 hook = op.join(path, 'hgrc') 81 if not op.isfile(hook): 82 open(hook, 'w+').close() 83 84 c = ConfigParser() 85 c.readfp(open(hook, 'r')) 86 if not c.has_section('hooks'): 87 c.add_section('hooks') 88 89 if not c.has_option('hooks', 'commit'): 90 c.set('hooks', 'commit', 'python:pylama.hooks.hg_hook') 91 92 if not c.has_option('hooks', 'qrefresh'): 93 c.set('hooks', 'qrefresh', 'python:pylama.hooks.hg_hook') 94 95 c.write(open(hook, 'w+')) 96 97 98def install_hook(path): 99 """ Auto definition of SCM and hook installation. """ 100 git = op.join(path, '.git', 'hooks') 101 hg = op.join(path, '.hg') 102 if op.exists(git): 103 install_git(git) 104 LOGGER.warn('Git hook has been installed.') 105 106 elif op.exists(hg): 107 install_hg(hg) 108 LOGGER.warn('Mercurial hook has been installed.') 109 110 else: 111 LOGGER.error('VCS has not found. Check your path.') 112 sys.exit(1) 113 114# pylama:ignore=F0401,E1103,D210,F0001 115