#!/usr/bin/python3
""" Run the Anaconda pylint tests on the files changed in this commit

    Set NOPYLINT env variable to skip this. eg. NOPYLINT= git commit


"""

import os
import sys
from subprocess import check_output, CalledProcessError
import tempfile

def is_python(filename):
    if filename.endswith(".py"):
        return True

    try:
        with open(filename) as testfile:
            if testfile.readline().startswith("#!/usr/bin/python"):
                return True
    except IOError:
        pass

    return False

OTHER_MODULES_PATH = ".:./tests/lib:../blivet/:../pykickstart/"

if "NOPYLINT" in os.environ:
    print("Skipping pre-commit pylint run")
    sys.exit(0)

# run pylint on all the python files changed by this commit
try:
    git_files = check_output(["git", "status", "--porcelain", "-z"])
except CalledProcessError:
    sys.exit(1)

# If git status returned nothing, return
if not git_files:
    sys.exit(0)

git_files = git_files.decode('utf-8').strip('\0').split('\0')

pylint_names = []
pylint_files = []
# Lines look like: MM tests/pylint/runpylint.sh
# The first character is the status in the index (or our side of a merge),
# the second character is the status in the tree (or their side of a merge).
# Use an iterator so we can skip lines in the case of renames
git_iter = iter(git_files)
for gf in git_iter:
    # If the file is being removed, or is not in git, or is not part of this
    # commit, ignore it
    if gf[0] in ('D', '?', ' '):
        continue

    # If the file is being renamed, the target filename (which we want) is on
    # the current line, and the next line is the source, which we want to skip
    if gf[0] == 'R':
        next(git_iter)

    if is_python(gf[3:]):
        pylint_names.append(gf[3:])

        # If the file is unmerged, changed, or deleted locally, create a
        # temporary file with the actual content that will be committed
        if gf[0] == 'U' or gf[1] in ('U', 'M', 'D'):
            tmpfile = tempfile.NamedTemporaryFile(prefix=gf[3:].replace('/', '.'))
            tmpfile.write(check_output(["git", "show", ":%s" % gf[3:]]))
            tmpfile.flush()
            pylint_files.append(tmpfile.name)
        else:
            pylint_files.append(gf[3:])

if not pylint_files:
    sys.exit(0)

# Make sure pykickstart and blivet can be found
# Note that if the checked out versions are too far off pylint may fail
env = os.environ.copy()
env["PYTHONPATH"] = OTHER_MODULES_PATH

print("Running pylint on %s" % " ".join(pylint_names))
try:
    check_output(["./tests/pylint/runpylint.py"] + pylint_files, env=env)
except CalledProcessError as e:
    print(e.output.decode('utf-8'))
    sys.exit(1)

sys.exit(0)
