#!/usr/bin/env python """File generated by pre-commit: https://pre-commit.com""" from __future__ import print_function import distutils.spawn import os import subprocess import sys # work around https://github.com/Homebrew/homebrew-core/issues/30445 os.environ.pop('__PYVENV_LAUNCHER__', None) HERE = os.path.dirname(os.path.abspath(__file__)) Z40 = '0' * 40 ID_HASH = '138fd403232d2ddd5efb44317e38bf03' # start templated CONFIG = None HOOK_TYPE = None INSTALL_PYTHON = None SKIP_ON_MISSING_CONFIG = None # end templated class EarlyExit(RuntimeError): pass class FatalError(RuntimeError): pass def _norm_exe(exe): """Necessary for shebang support on windows. roughly lifted from `identify.identify.parse_shebang` """ with open(exe, 'rb') as f: if f.read(2) != b'#!': return () try: first_line = f.readline().decode('UTF-8') except UnicodeDecodeError: return () cmd = first_line.split() if cmd[0] == '/usr/bin/env': del cmd[0] return tuple(cmd) def _run_legacy(): if HOOK_TYPE == 'pre-push': stdin = getattr(sys.stdin, 'buffer', sys.stdin).read() else: stdin = None legacy_hook = os.path.join(HERE, '{}.legacy'.format(HOOK_TYPE)) if os.access(legacy_hook, os.X_OK): cmd = _norm_exe(legacy_hook) + (legacy_hook,) + tuple(sys.argv[1:]) proc = subprocess.Popen(cmd, stdin=subprocess.PIPE if stdin else None) proc.communicate(stdin) return proc.returncode, stdin else: return 0, stdin def _validate_config(): cmd = ('git', 'rev-parse', '--show-toplevel') top_level = subprocess.check_output(cmd).decode('UTF-8').strip() cfg = os.path.join(top_level, CONFIG) if os.path.isfile(cfg): pass elif SKIP_ON_MISSING_CONFIG or os.getenv('PRE_COMMIT_ALLOW_NO_CONFIG'): print( '`{}` config file not found. ' 'Skipping `pre-commit`.'.format(CONFIG), ) raise EarlyExit() else: raise FatalError( 'No {} file was found\n' '- To temporarily silence this, run ' '`PRE_COMMIT_ALLOW_NO_CONFIG=1 git ...`\n' '- To permanently silence this, install pre-commit with the ' '--allow-missing-config option\n' '- To uninstall pre-commit run ' '`pre-commit uninstall`'.format(CONFIG), ) def _exe(): with open(os.devnull, 'wb') as devnull: for exe in (INSTALL_PYTHON, sys.executable): try: if not subprocess.call( (exe, '-c', 'import pre_commit.main'), stdout=devnull, stderr=devnull, ): return (exe, '-m', 'pre_commit.main', 'run') except OSError: pass if distutils.spawn.find_executable('pre-commit'): return ('pre-commit', 'run') raise FatalError( '`pre-commit` not found. Did you forget to activate your virtualenv?', ) def _rev_exists(rev): return not subprocess.call(('git', 'rev-list', '--quiet', rev)) def _pre_push(stdin): remote = sys.argv[1] opts = () for line in stdin.decode('UTF-8').splitlines(): _, local_sha, _, remote_sha = line.split() if local_sha == Z40: continue elif remote_sha != Z40 and _rev_exists(remote_sha): opts = ('--origin', local_sha, '--source', remote_sha) else: # ancestors not found in remote ancestors = subprocess.check_output(( 'git', 'rev-list', local_sha, '--topo-order', '--reverse', '--not', '--remotes={}'.format(remote), )).decode().strip() if not ancestors: continue else: first_ancestor = ancestors.splitlines()[0] cmd = ('git', 'rev-list', '--max-parents=0', local_sha) roots = set(subprocess.check_output(cmd).decode().splitlines()) if first_ancestor in roots: # pushing the whole tree including root commit opts = ('--all-files',) else: cmd = ('git', 'rev-parse', '{}^'.format(first_ancestor)) source = subprocess.check_output(cmd).decode().strip() opts = ('--origin', local_sha, '--source', source) if opts: return opts else: # An attempt to push an empty changeset raise EarlyExit() def _opts(stdin): fns = { 'commit-msg': lambda _: ('--commit-msg-filename', sys.argv[1]), 'pre-commit': lambda _: (), 'pre-push': _pre_push, } stage = HOOK_TYPE.replace('pre-', '') return ('--config', CONFIG, '--hook-stage', stage) + fns[HOOK_TYPE](stdin) def main(): retv, stdin = _run_legacy() try: _validate_config() return retv | subprocess.call(_exe() + _opts(stdin)) except EarlyExit: return retv except FatalError as e: print(e.args[0]) return 1 if __name__ == '__main__': exit(main())