mirror of
https://github.com/AdaCore/git-hooks.git
synced 2026-02-12 12:43:11 -08:00
This commit introduces a new class (ThirdPartyHook), which centralizes the handling of third-party hooks (scripts that project set up via the configuration file). Most of the code is simply a move of the code from maybe_call_thirdparty_hook, with a couple of enhancements: - Ability to specify the directory from which to call the hook; - Handling of the situation when calling the hook itself fails. We can already see the benefits of this in function style_check_files, where the code now necessary to call the style_checker is both clearer and more compact. In the future, the intent is to push this class one step further to allow users to specify hooks to be fetched from the repository, rather than requiring that the hooks be installed (usually by an admin) on the machine hosting the repository. The current class' API should allow us to implement this in a way that's transparent to all users. Change-Id: Ie8bf8accbbfd75a91b914628fad27d780532dac4 TN: T209-005
120 lines
4.4 KiB
Python
120 lines
4.4 KiB
Python
"""Implements git's post-receive hook.
|
|
|
|
The arguments for this hook are passed via stdin: For each reference
|
|
that is updated, stdin contains one line with 3 space-separated
|
|
tokens: the old SHA1, the new SHA1, and the reference name (Eg:
|
|
refs/heads/master).
|
|
"""
|
|
from argparse import ArgumentParser
|
|
from collections import OrderedDict
|
|
import sys
|
|
|
|
from config import ThirdPartyHook
|
|
from daemon import run_in_daemon
|
|
from git import git_show_ref
|
|
from init import init_all_globals
|
|
from updates.emails import EmailQueue
|
|
from updates.factory import new_update
|
|
from utils import debug, warn
|
|
|
|
|
|
def post_receive_one(ref_name, old_rev, new_rev, refs, submitter_email):
|
|
"""post-receive treatment for one reference.
|
|
|
|
PARAMETERS
|
|
ref_name: The name of the reference.
|
|
old_rev: The SHA1 of the reference before the update.
|
|
new_rev: The SHA1 of the reference after the update.
|
|
refs: A dictionary containing all references, as described
|
|
in git_show_ref.
|
|
submitter_email: Same as AbstractUpdate.__init__.
|
|
"""
|
|
debug('post_receive_one(ref_name=%s\n'
|
|
' old_rev=%s\n'
|
|
' new_rev=%s)'
|
|
% (ref_name, old_rev, new_rev))
|
|
|
|
update = new_update(ref_name, old_rev, new_rev, refs, submitter_email)
|
|
if update is None:
|
|
# We emit a warning, rather than trigger an assertion, because
|
|
# it gives the script a chance to process any other reference
|
|
# that was updated, but not processed yet.
|
|
warn("post-receive: Unsupported reference update: %s (ignored)."
|
|
% ref_name,
|
|
" old_rev = %s" % old_rev,
|
|
" new_rev = %s" % new_rev)
|
|
return
|
|
update.send_email_notifications()
|
|
|
|
|
|
def post_receive(updated_refs, submitter_email):
|
|
"""Implement the post-receive hook for all given updated_refs.
|
|
|
|
PARAMETERS
|
|
updated_refs: An OrderedDict, indexed by the name of the ref
|
|
being updated, and containing 2-elements tuple. This tuple
|
|
contains the previous revision, and the new revision of the
|
|
reference.
|
|
submitter_email: Same as AbstractUpdate.__init__.
|
|
"""
|
|
refs = git_show_ref()
|
|
|
|
for ref_name in updated_refs.keys():
|
|
(old_rev, new_rev) = updated_refs[ref_name]
|
|
post_receive_one(ref_name, old_rev, new_rev, refs,
|
|
submitter_email)
|
|
|
|
# Flush the email queue. Since this involves creating a daemon,
|
|
# only do so if there is at least one email to be sent.
|
|
email_queue = EmailQueue()
|
|
if email_queue.queue:
|
|
run_in_daemon(email_queue.flush)
|
|
|
|
|
|
def maybe_post_receive_hook(post_receive_data):
|
|
"""Call the post-receive-hook is required.
|
|
|
|
This function implements supports for the hooks.post-receive-hook
|
|
config variable, by calling this function if the config variable
|
|
is defined.
|
|
"""
|
|
result = ThirdPartyHook('hooks.post-receive-hook').call_if_defined(
|
|
hook_input=post_receive_data)
|
|
if result is not None:
|
|
hook_exe, p, out = result
|
|
sys.stdout.write(out)
|
|
# Flush stdout now, to make sure the script's output is printed
|
|
# ahead of the warning below, which is directed to stderr.
|
|
sys.stdout.flush()
|
|
if p.returncode != 0:
|
|
warn('!!! WARNING: %s returned code: %d.'
|
|
% (hook_exe, p.returncode))
|
|
|
|
|
|
def parse_command_line():
|
|
"""Return a namespace built after parsing the command line."""
|
|
# The command-line interface is very simple, so we could possibly
|
|
# handle it by hand. But it's nice to have features such as
|
|
# -h/--help switches which come for free if we use argparse.
|
|
ap = ArgumentParser(description='Git "post-receive" hook.')
|
|
ap.add_argument('--submitter-email',
|
|
help=('Use this email address as the sender'
|
|
' of email notifications instead of using the'
|
|
' email address of the user calling this'
|
|
' script'))
|
|
return ap.parse_args()
|
|
|
|
|
|
if __name__ == '__main__':
|
|
args = parse_command_line()
|
|
|
|
stdin = sys.stdin.read()
|
|
refs_data = OrderedDict()
|
|
for line in stdin.splitlines():
|
|
old_rev, new_rev, ref_name = line.strip().split()
|
|
refs_data[ref_name] = (old_rev, new_rev)
|
|
|
|
init_all_globals(refs_data)
|
|
post_receive(refs_data, args.submitter_email)
|
|
maybe_post_receive_hook(stdin)
|