#!/usr/bin/env python3
import subprocess
import urllib.request
import os
import re
import tempfile
import collections
import copy
import sys

base = os.environ["SYSTEM_PULLREQUEST_TARGETBRANCH"]
if not re.match("^[0-9a-fA-F]{40}$", base):
    base = "refs/remotes/origin/" + base

with tempfile.TemporaryDirectory() as dfn:
    patches = subprocess.check_output(
        [
            "git", "format-patch",
            "--output-directory", dfn,
            os.environ["SYSTEM_PULLREQUEST_SOURCECOMMITID"], "^" + base
        ],
        universal_newlines=True).splitlines()
    if len(patches) == 0:
        sys.exit(0)

    ckp = os.path.join(dfn, "checkpatch.pl")
    opener = urllib.request.build_opener()
    opener.addheaders = [('User-agent', 'rdma-core/1.x (linux-rdma@vger.kernel.org)')]
    urllib.request.install_opener(opener)
    urllib.request.urlretrieve(
        "https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/plain/scripts/checkpatch.pl",
        ckp)
    urllib.request.urlretrieve(
        "https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/plain/scripts/spelling.txt",
        os.path.join(dfn, "spelling.txt"))
    os.symlink(
        os.path.join(os.getcwd(), "buildlib/const_structs.checkpatch"),
        os.path.join(dfn, "const_structs.checkpatch"))
    checkpatch = [
        "perl", ckp, "--no-tree", "--show-types", "--ignore",
        "PREFER_KERNEL_TYPES,FILE_PATH_CHANGES,EXECUTE_PERMISSIONS,USE_NEGATIVE_ERRNO,CONST_STRUCT",
        "--emacs", "--mailback", "--quiet", "--no-summary"
    ]

    environ = copy.copy(os.environ)
    environ["GIT_DIR"] = subprocess.check_output(["git","rev-parse","--absolute-git-dir"]).decode().strip()

    warnings = False
    errors = False
    for fn in patches:
        proc = subprocess.run(
            checkpatch + [os.path.basename(fn)],
            cwd=dfn,
            stdout=subprocess.PIPE,
            universal_newlines=True,
            env=environ,
            stderr=subprocess.STDOUT)
        if proc.returncode == 0:
            assert (not proc.stdout)
            continue
        sys.stdout.write(proc.stdout)

        warnings = True
        for g in re.finditer(
                r"^\d+-.*:\d+: (\S+):(\S+): (.*)(?:\n#(\d+): (?:FILE: (.*):(\d+):)?)?$",
                proc.stdout,
                flags=re.MULTILINE):
            itms = {}
            if g.group(1) == "WARNING":
                itms["type"] = "warning"
            else:
                itms["type"] = "error"

            itms["code"]=g.group(2)

            if g.group(4):
                itms["sourcepath"] = g.group(5)
                itms["linenumber"] = g.group(6)

            # Bump some warnings to errors
            if itms["code"] == "UNKNOWN_COMMIT_ID":
                itms["type"] = "error"

            if itms["type"] == "error":
                errors = True
            print("##vso[task.logissue %s]%s" % (";".join(
                "%s=%s" % (k, v)
                for k, v in sorted(itms.items())), g.group(3)))

if errors:
    print("##vso[task.complete result=Failed]azp-checkpatch")
elif warnings:
    print("##vso[task.complete result=SucceededWithIssues]azp-checkpatch")
