#!/usr/bin/env python3

"""This gets executed on 'git commit' and rejects the commit in case the
submitted code does not pass validation. Validation is run only against
the files which were modified in the commit.
"""

import os
import subprocess
import sys


PYTHON = sys.executable
THIS_SCRIPT = os.path.realpath(__file__)


def term_supports_colors():
    try:
        import curses
        assert sys.stderr.isatty()
        curses.setupterm()
        assert curses.tigetnum("colors") > 0
    except Exception:  # noqa
        return False
    return True


def hilite(s, ok=True, bold=False):
    """Return an highlighted version of 'string'."""
    if not term_supports_colors():
        return s
    attr = []
    if ok is None:  # no color
        pass
    elif ok:   # green
        attr.append('32')
    else:   # red
        attr.append('31')
    if bold:
        attr.append('1')
    return '\x1b[%sm%s\x1b[0m' % (';'.join(attr), s)


def exit(msg):
    print(hilite("commit aborted: " + msg, ok=False), file=sys.stderr)
    sys.exit(1)


def sh(cmd):
    p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE,  # noqa
                         stderr=subprocess.PIPE, universal_newlines=True)
    stdout, stderr = p.communicate()
    if p.returncode != 0:
        raise RuntimeError(stderr)
    if stderr:
        print(stderr, file=sys.stderr)
    if stdout.endswith('\n'):
        stdout = stdout[:-1]
    return stdout


def git_commit_files():
    out = sh("git diff --cached --name-only")
    py_files = [x for x in out.split('\n') if x.endswith('.py') and
                os.path.exists(x)]
    return py_files


def ruff(files):
    print("running ruff (%s)" % len(files))
    cmd = [PYTHON, "-m", "ruff", "check", "--no-cache"] + files
    if subprocess.call(cmd) != 0:
        return exit(
            "Python code didn't pass 'ruff' style check."
            "Try running 'make fix-ruff'."
        )


def main():
    py_files = git_commit_files()
    if py_files:
        ruff(py_files)


main()
