diff --git a/setup/git_hooks.py b/setup/git_hooks.py index 750474e573..e4da9d6d66 100644 --- a/setup/git_hooks.py +++ b/setup/git_hooks.py @@ -28,6 +28,7 @@ Hook = namedtuple('Hook', ['name', 'file', 'args_count', 'default']) HOOKS = {h.name:h for h in ( Hook('post-checkout', 'git_post_checkout_hook.py', 3, True), Hook('post-rewrite', 'git_post_rewrite_hook.py', 1, True), + Hook('pre-commit', 'git_pre_commit_hook.py', 0, True), # disable by default, because except Kovid, nobody can run this hook Hook('commit-msg', 'git_commit_msg_hook.py', 1, False), )} diff --git a/setup/git_pre_commit_hook.py b/setup/git_pre_commit_hook.py new file mode 100644 index 0000000000..6971020948 --- /dev/null +++ b/setup/git_pre_commit_hook.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python + +import os +import subprocess +import sys + +base = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) +os.chdir(base) +setup_py = os.path.realpath('./setup.py') + + +def testfile(file): + def t(f, start, end, exclude_end=None): + return f.startswith(start) and f.endswith(end) and not f.endswith(exclude_end) if exclude_end else True + if t(file, ('src/odf', 'src/calibre'), '.py', exclude_end='_ui.py'): + return True + if t(file, 'recipes', '.recipe'): + return True + if t(file, 'src/pyj', '.pyj'): + return True + return False + + +output = subprocess.check_output(( + 'git', 'diff', '--staged', '--name-only', '--no-ext-diff', '-z', + # Everything except for D + '--diff-filter=ACMRTUXB', +)).decode('utf-8') + +output = output.strip('\0') +if not output: + output = [] +else: + output = output.split('\0') + +filenames = tuple(filter(testfile, output)) +if not filenames: + sys.exit(0) + +check_args = [sys.executable, './setup.py', 'check', '--no-editor'] +# let's hope that too many arguments do not hold any surprises +for f in filenames: + check_args.append('-f') + check_args.append(f) + +returncode = subprocess.call(check_args) +sys.exit(returncode)