#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# This is the post-receive git hook used to generate the activity feed
# public-inbox repository. It requires that ezpi is installed
# https://sr.ht/~monsieuricon/ezpi/
#
# Copyright (C) 2020 by The Linux Foundation
# SPDX-License-Identifier: GPL-2.0-or-later
#
__author__ = 'Konstantin Ryabitsev <konstantin@linuxfoundation.org>'

import os
import sys
import ezpi # noqa
import hashlib
import base64

from email.message import EmailMessage
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart

from typing import Optional


def get_config_from_git(regexp: str, defaults: Optional[dict] = None) -> dict:
    gitconfig = defaults if defaults else dict()

    args = ['config', '-z', '--get-regexp', regexp]
    ee, out, err = ezpi.git_run_command('', args)
    if ee > 0 or not len(out):
        return gitconfig

    for line in out.decode().split('\x00'):
        if not line:
            continue
        key, value = line.split('\n', 1)
        try:
            chunks = key.split('.')
            cfgkey = chunks[-1]
            gitconfig[cfgkey.lower()] = value
        except ValueError:
            pass

    return gitconfig


def run_hook(feedrepo: str, fromhdr: str, domain: str):
    # Look if we have a GL_USER and GL_REPO in the env
    user = os.getenv('GL_USER')
    if not user:
        user = os.getenv('USER')
    repo = os.getenv('GL_REPO')
    if not repo:
        repo = os.getcwd()
    ll = list()
    attachments = dict()
    ll.append('---')
    ll.append('service: git-receive-pack')
    ll.append(f'repo: {repo}')
    ll.append(f'user: {user}')
    # Do we have a ~/.activity-feed-secret?
    secret = None
    secretf = os.path.expanduser('~/.activity-feed-secret')
    # The idea is to rotate it frequently, with the value logged in syslog.
    # This allows us to see if a push is coming from the same remote IP address,
    # but only within the same calendar day.
    try:
        with open(secretf) as fh:
            secret = fh.read().strip()
    except (FileNotFoundError, IOError):
        pass

    if secret:
        conn_info = os.getenv('SSH_CONNECTION')
        if conn_info:
            remote_ip = conn_info.split()[0]
            ipline = f'{secret}{user}{remote_ip}'
            iph = hashlib.sha1()
            iph.update(ipline.encode())
            hashed = base64.b64encode(iph.digest()).decode()
            ll.append(f'remote_ip: {hashed}')

    # Do we have a push cert?
    cert = os.getenv('GIT_PUSH_CERT')
    if cert:
        gpcstatus = os.getenv('GIT_PUSH_CERT_STATUS')
        ll.append(f'git_push_cert_status: {gpcstatus}')
        args = ['cat-file', 'blob', cert]
        ee, out, err = ezpi.git_run_command('', args)
        if ee == 0 and out:
            attachments['git-push-certificate.txt'] = out.decode()

    ll.append('changes:')

    seenranges = dict()
    while True:
        line = sys.stdin.readline()
        if not line:
            break
        oldrev, newrev, ref = line.strip().split()
        ll.append(f'  - ref: {ref}')
        ll.append(f'    old: {oldrev}')
        ll.append(f'    new: {newrev}')

        if (oldrev, newrev) not in seenranges:
            args = ['rev-list', '--max-count=1024', '--reverse', '--pretty=oneline', newrev]
            if set(oldrev) != {0}:
                args += [f'^{oldrev}']
            ee, out, err = ezpi.git_run_command('', args)
            if ee > 0 or not len(out):
                continue
            seenranges[(oldrev, newrev)] = out
        else:
            out = seenranges[(oldrev, newrev)]

        if len(out) > 1024:
            # Add it as attachment, unless we already have one with this name
            filename = f'revlist-{oldrev[:12]}-{newrev[:12]}.txt'
            if filename not in attachments:
                attachments[filename] = out.decode()
            ll.append(f'    log: {filename}')
            continue

        ll.append('    log: |')
        for pretty in out.decode().split('\n'):
            ll.append(f'         {pretty}')

    body = '\n'.join(ll) + '\n'

    if attachments:
        msg = MIMEMultipart()
        msg.attach(MIMEText(body, 'plain'))
        for attfilename, attbody in attachments.items():
            att = MIMEText(attbody, 'plain')
            att.add_header('Content-Disposition', f'attachment; filename={attfilename}')
            msg.attach(att)
    else:
        msg = EmailMessage()
        msg.set_payload(body)

    msg['From'] = fromhdr
    msg['Subject'] = f'post-receive: {repo}'

    try:
        ezpi.add_rfc822(feedrepo, msg, domain)
        sys.stderr.write('Recorded in the transparency log\n')
        ezpi.run_hook(feedrepo)
    except RuntimeError:
        # Could not add it to the feed, complain
        sys.stderr.write('FAILED writing to the transparency log!\n')


if __name__ == '__main__':
    if sys.stdin.isatty():
        # Nothing passed via stdin, so nothing to add to the feed
        sys.exit(0)
    config = get_config_from_git(r'activityfeed\..*')
    _feedrepo = config.get('repo')
    if not config.get('repo'):
        # The audit repo is not defined in gitconfig, so nothing for us to do.
        sys.exit(0)
    _fromhdr = config.get('from')
    _domain = config.get('domain')
    if not _domain:
        _domain = 'localhost'

    if not _fromhdr:
        _fromhdr = f'Post-Receive Hook <post-receive@{_domain}>'

    run_hook(_feedrepo, _fromhdr, _domain)
