#!/usr/bin/env python3
#
# ======- pre-push - LLVM Git Help Integration ---------*- python -*--========#
#
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
# See https://llvm.org/LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
# ==------------------------------------------------------------------------==#

"""
pre-push git hook integration
=============================

This script is intended to be setup as a pre-push hook, from the root of the
repo run:

   ln -sf ../../llvm/utils/git/pre-push.py .git/hooks/pre-push

From the git doc:

  The pre-push hook runs during git push, after the remote refs have been
  updated but before any objects have been transferred. It receives the name
  and location of the remote as parameters, and a list of to-be-updated refs
  through stdin. You can use it to validate a set of ref updates before a push
  occurs (a non-zero exit code will abort the push).
"""

import argparse
import collections
import os
import re
import shutil
import subprocess
import sys
import time
import getpass
from shlex import quote

VERBOSE = False
QUIET = False
dev_null_fd = None
z40 = '0000000000000000000000000000000000000000'


def eprint(*args, **kwargs):
    print(*args, file=sys.stderr, **kwargs)


def log(*args, **kwargs):
    if QUIET:
        return
    print(*args, **kwargs)


def log_verbose(*args, **kwargs):
    if not VERBOSE:
        return
    print(*args, **kwargs)


def die(msg):
    eprint(msg)
    sys.exit(1)


def ask_confirm(prompt):
    while True:
        query = input('%s (y/N): ' % (prompt))
        if query.lower() not in ['y', 'n', '']:
           print('Expect y or n!')
           continue
        return query.lower() == 'y'


def get_dev_null():
    """Lazily create a /dev/null fd for use in shell()"""
    global dev_null_fd
    if dev_null_fd is None:
        dev_null_fd = open(os.devnull, 'w')
    return dev_null_fd


def shell(cmd, strip=True, cwd=None, stdin=None, die_on_failure=True,
          ignore_errors=False, text=True, print_raw_stderr=False):
    # Escape args when logging for easy repro.
    quoted_cmd = [quote(arg) for arg in cmd]
    cwd_msg = ''
    if cwd:
      cwd_msg = ' in %s' % cwd
    log_verbose('Running%s: %s' % (cwd_msg, ' '.join(quoted_cmd)))

    err_pipe = subprocess.PIPE
    if ignore_errors:
        # Silence errors if requested.
        err_pipe = get_dev_null()

    start = time.time()
    p = subprocess.Popen(cmd, cwd=cwd, stdout=subprocess.PIPE, stderr=err_pipe,
                         stdin=subprocess.PIPE,
                         universal_newlines=text)
    stdout, stderr = p.communicate(input=stdin)
    elapsed = time.time() - start

    log_verbose('Command took %0.1fs' % elapsed)

    if p.returncode == 0 or ignore_errors:
        if stderr and not ignore_errors:
            if not print_raw_stderr:
                eprint('`%s` printed to stderr:' % ' '.join(quoted_cmd))
            eprint(stderr.rstrip())
        if strip:
            if text:
                stdout = stdout.rstrip('\r\n')
            else:
                stdout = stdout.rstrip(b'\r\n')
        if VERBOSE:
            for l in stdout.splitlines():
                log_verbose('STDOUT: %s' % l)
        return stdout
    err_msg = '`%s` returned %s' % (' '.join(quoted_cmd), p.returncode)
    eprint(err_msg)
    if stderr:
        eprint(stderr.rstrip())
    if die_on_failure:
        sys.exit(2)
    raise RuntimeError(err_msg)


def git(*cmd, **kwargs):
    return shell(['git'] + list(cmd), **kwargs)


def get_revs_to_push(range):
    commits = git('rev-list', range).splitlines()
    # Reverse the order so we print the oldest commit first
    commits.reverse()
    return commits


def handle_push(args, local_ref, local_sha, remote_ref, remote_sha):
    '''Check a single push request (which can include multiple revisions)'''
    log_verbose('Handle push, reproduce with '
                '`echo %s %s %s %s | pre-push.py %s %s'
                 % (local_ref, local_sha, remote_ref, remote_sha, args.remote,
                    args.url))
    # Handle request to delete
    if local_sha == z40:
        if not ask_confirm('Are you sure you want to delete "%s" on remote "%s"?' % (remote_ref, args.url)):
            die("Aborting")
        return

    # Push a new branch
    if remote_sha == z40:
      if not ask_confirm('Are you sure you want to push a new branch/tag "%s" on remote "%s"?' % (remote_ref, args.url)):
        die("Aborting")
      range=local_sha
      return
    else:
      # Update to existing branch, examine new commits
      range='%s..%s' % (remote_sha, local_sha)
      # Check that the remote commit exists, otherwise let git proceed
      if "commit" not in git('cat-file','-t', remote_sha, ignore_errors=True):
          return

    revs = get_revs_to_push(range)
    if not revs:
        # This can happen if someone is force pushing an older revision to a branch
        return

    # Print the revision about to be pushed commits
    print('Pushing to "%s" on remote "%s"' % (remote_ref, args.url))
    for sha in revs:
      print(' - ' + git('show', '--oneline', '--quiet', sha))

    if len(revs) > 1:
      if not ask_confirm('Are you sure you want to push %d commits?' % len(revs)):
          die('Aborting')


    for sha in revs:
      msg = git('log', '--format=%B', '-n1', sha)
      if 'Differential Revision' not in msg:
          continue
      for line in msg.splitlines():
          for tag in ['Summary', 'Reviewers', 'Subscribers', 'Tags']:
            if line.startswith(tag + ':'):
              eprint('Please remove arcanist tags from the commit message (found "%s" tag in %s)' % (tag, sha[:12]))
              if len(revs) == 1:
                  eprint('Try running: llvm/utils/git/arcfilter.sh')
              die('Aborting (force push by adding "--no-verify")')

    return


if __name__ == '__main__':
    if not shutil.which('git'):
        die('error: cannot find git command')

    argv = sys.argv[1:]
    p = argparse.ArgumentParser(
        prog='pre-push', formatter_class=argparse.RawDescriptionHelpFormatter,
        description=__doc__)
    verbosity_group = p.add_mutually_exclusive_group()
    verbosity_group.add_argument('-q', '--quiet', action='store_true',
                                 help='print less information')
    verbosity_group.add_argument('-v', '--verbose', action='store_true',
                                 help='print more information')

    p.add_argument('remote', type=str, help='Name of the remote')
    p.add_argument('url', type=str, help='URL for the remote')

    args = p.parse_args(argv)
    VERBOSE = args.verbose
    QUIET = args.quiet

    lines = sys.stdin.readlines()
    sys.stdin = open('/dev/tty', 'r')
    for line in lines:
      local_ref, local_sha, remote_ref, remote_sha = line.split()
      handle_push(args, local_ref, local_sha, remote_ref, remote_sha)
