From 628124ae84ac249f2c09402cef61ca56db5f29aa Mon Sep 17 00:00:00 2001 From: Silvie Chlupova Date: Tue, 16 Jul 2019 09:29:53 +0200 Subject: [PATCH] Adding tool for parsing build.log Fixes: #279 --- mock/mock.spec | 8 ++- mock/py/mock-parse-buildlog.py | 95 ++++++++++++++++++++++++++++++++++ 2 files changed, 101 insertions(+), 2 deletions(-) create mode 100755 mock/py/mock-parse-buildlog.py diff --git a/mock/mock.spec b/mock/mock.spec index c25653d59..8d8035017 100644 --- a/mock/mock.spec +++ b/mock/mock.spec @@ -129,12 +129,12 @@ of the buildroot. %prep %setup -q -for file in py/mock.py py/mockchain.py; do +for file in py/mock.py py/mockchain.py py/mock-parse-buildlog.py; do sed -i 1"s|#!/usr/bin/python3 |#!%{__python} |" $file done %build -for i in py/mock.py py/mockchain.py; do +for i in py/mock.py py/mockchain.py py/mock-parse-buildlog.py; do perl -p -i -e 's|^__VERSION__\s*=.*|__VERSION__="%{version}"|' $i perl -p -i -e 's|^SYSCONFDIR\s*=.*|SYSCONFDIR="%{_sysconfdir}"|' $i perl -p -i -e 's|^PYTHONDIR\s*=.*|PYTHONDIR="%{python_sitelib}"|' $i @@ -148,6 +148,7 @@ done install -d %{buildroot}%{_bindir} install -d %{buildroot}%{_libexecdir}/mock install py/mockchain.py %{buildroot}%{_bindir}/mockchain +install py/mock-parse-buildlog.py %{buildroot}%{_bindir}/mock-parse-buildlog install py/mock.py %{buildroot}%{_libexecdir}/mock/mock ln -s consolehelper %{buildroot}%{_bindir}/mock install create_default_route_in_container.sh %{buildroot}%{_libexecdir}/mock/ @@ -164,6 +165,7 @@ cp -a etc/consolehelper/mock %{buildroot}%{_sysconfdir}/security/console.apps/%{ install -d %{buildroot}%{_datadir}/bash-completion/completions/ cp -a etc/bash_completion.d/* %{buildroot}%{_datadir}/bash-completion/completions/ ln -s mock %{buildroot}%{_datadir}/bash-completion/completions/mockchain +ln -s mock %{buildroot}%{_datadir}/bash-completion/completions/mock-parse-buildlog install -d %{buildroot}%{_sysconfdir}/pki/mock cp -a etc/pki/* %{buildroot}%{_sysconfdir}/pki/mock/ @@ -188,12 +190,14 @@ pylint-3 py/mockbuild/ py/*.py py/mockbuild/plugins/* || : %config(noreplace) %{_sysconfdir}/mock/site-defaults.cfg %{_datadir}/bash-completion/completions/mock %{_datadir}/bash-completion/completions/mockchain +%{_datadir}/bash-completion/completions/mock-parse-buildlog %defattr(-, root, root) # executables %{_bindir}/mock %{_bindir}/mockchain +%{_bindir}/mock-parse-buildlog %{_libexecdir}/mock # python stuff diff --git a/mock/py/mock-parse-buildlog.py b/mock/py/mock-parse-buildlog.py new file mode 100755 index 000000000..55a8f97e6 --- /dev/null +++ b/mock/py/mock-parse-buildlog.py @@ -0,0 +1,95 @@ +#!/usr/bin/python3 -tt +# -*- coding: utf-8 -*- +# vim:expandtab:autoindent:tabstop=4:shiftwidth=4:filetype=python:textwidth=0: + +import argparse +import logging +import re + +FORMAT = "%(levelname)s: %(message)s" +logging.basicConfig(format=FORMAT, level=logging.WARNING) +log = logging.getLogger() + + +def argumentParser(): + parser = argparse.ArgumentParser( + description="Parses the build.log and return an error why build failed.", + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + ) + parser.add_argument("-p", "--path", required=True, help="Path to build.log") + arguments = parser.parse_args() + return arguments + + +def parseBuildLog(log_path): + """Parses the build log. + + Args: + log_path (str): Path to the RPM build log. + + Returns: + tuple: The first element is the type of error that was found + in the log (missing or deleted). The second element is + a list of problematic files. + """ + try: + with open(log_path, "r") as build_log: + lines = build_log.read().splitlines() + except IOError as error: + log.error("There was an error opening %s, %s", log_path, str(error)) + return + + error_re = re.compile( + r""" + ^ + (BUILDSTDERR:)? + \s* + ( + (?PFile\s+not\s+found:\s*)| + (?PInstalled\s+\(but\s+unpackaged\)\s+file\(s\)\s+found:) + )? + (?P/.*)? + $ + """, re.VERBOSE, + ) + + error_type = None + files = set() + + for line in lines: + match = error_re.match(line) + if match: + if match.group("missing"): + error_type = "deleted" + files.add(match.group("path")) + elif match.group("unpackaged"): + error_type = "missing" + elif error_type == "missing" and match.group("path"): + files.add(match.group("path")) + elif error_type and not match.group("path"): + break + + return error_type, list(files) + + +def main(log_path): + error = parseBuildLog(log_path) + if error[0] is not None: + if error[0] == "missing": + print( + "Error type: {0}".format("Build failed because problematic files are in %buildroot but not in %files") + ) + elif error[0] == "deleted": + print( + "Error type: {0}".format("Build failed because problematic files are in %files but not in %buildroot") + ) + print("Problematic files: ") + for files in error[1]: + print(files) + else: + log.error("Couldn't recognize the error that caused the build failure.") + + +if __name__ == "__main__": + programArguments = argumentParser() + main(programArguments.path)