| #!/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") |