From 43147a9abaa1254235b853e643514cf1c7b150d7 Mon Sep 17 00:00:00 2001 From: Jakub Hrozek Date: Mon, 28 Sep 2015 13:46:39 +0200 Subject: contrib: Add a pre-push hook to warn about commits without Reviewed-By --- contrib/git/pre-push | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100755 contrib/git/pre-push diff --git a/contrib/git/pre-push b/contrib/git/pre-push new file mode 100755 index 000000000..d05202dfd --- /dev/null +++ b/contrib/git/pre-push @@ -0,0 +1,73 @@ +#!/usr/bin/env python + +# A git pre-push hook that declines commits that don't contain a Reviewed-By: +# tag. The tag must be present on the beginning of the line. To activate, copy +# to $GIT_DIR/hooks/pre-push and make sure the executable flag is on. + +# The commit message should also be based on .git-commit-template, although +# that is just best practice and not enforced + +import sys +import re +import subprocess + + +def get_all_commits(ref_from, ref_to): + args = ['git', 'rev-list', '{:s}..{:s}'.format(ref_from, ref_to)] + p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + out, err = p.communicate() + return [commit.strip() for commit in out.split('\n') if commit != ''] + + +def commit_message(commit_hash): + args = ['git', 'cat-file', 'commit', commit_hash] + p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + out, err = p.communicate() + return out + + +def commit_has_rb(commit): + msg = commit_message(commit) + for l in msg.split('\n'): + has_rb = re.search('^Reviewed-by:', l) + if has_rb: + return True + + return False + + +def report_commit(commit_hash): + print("Commit {:s} does not have Reviewed-By!".format(commit_hash)) + print("Full message:\n======") + print("{:s}".format(commit_message(commit_hash))) + print("======") + + +# man 5 githooks says: +# Information about what is to be pushed is provided on the hook's +# standard input with lines of the form: +# SP SP SP LF +def check_push(hook_input): + ref_to = hook_input.split()[1][:6] + ref_from = hook_input.split()[3][:6] + commit_list = get_all_commits(ref_from, ref_to) + + no_rb_list = [] + for commit in commit_list: + if not commit_has_rb(commit): + no_rb_list.append(commit) + + return no_rb_list + +# Don't warn when pushing to personal repositories, only origin +remote = sys.argv[1] +if remote != 'origin': + sys.exit(0) + +for hook_input in sys.stdin.readlines(): + no_rb_list = check_push(hook_input) + + if len(no_rb_list) > 0: + for offender in no_rb_list: + report_commit(offender) + sys.exit(1) -- cgit